From b345c0ccf0abd05eebb50af1fd950e203a075ab3 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 11 Apr 2026 16:03:07 +0100 Subject: [PATCH 01/34] Progress report --- .../LuaStudio.Intellisense.cs | 117 ++++ TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs | 25 +- .../LuaIntellisenseDocumentManager.cs | 163 +++++ .../LuaLanguageServerClient.cs | 577 ++++++++++++++++++ .../LuaLanguageServerDiagnosticsParser.cs | 297 +++++++++ .../LuaLanguageServerIntellisenseProvider.cs | 295 +++++++++ .../LuaLanguageServerLocator.cs | 96 +++ .../LuaLanguageServerPathHelper.cs | 83 +++ .../LuaLanguageServerResponseParser.cs | 359 +++++++++++ .../LuaLanguageServerSettingsFactory.cs | 44 ++ .../Settings/ClassicScriptSettingsControl.cs | 2 +- .../Settings/LuaSettingsControl.Designer.cs | 5 +- .../TombIDE.ScriptingStudio.csproj | 7 +- .../DocumentModePresets/ContextMenus/Lua.xml | 2 + .../TombIDE.ScriptingStudio/UI/UICommand.cs | 1 + TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs | 1 + TombIDE/TombIDE.Shared/IDEConfiguration.cs | 1 + .../Resources/Localization/EN/TombIDE.xml | 1 + .../Resources/Localization/Localization.cs | 1 + .../Resources/Localization/PL/TombIDE.xml | 1 + .../ClassicScriptEditor.cs | 9 +- .../TombLib.Scripting.ClassicScript.csproj | 5 +- .../Utils/ErrorDetector.cs | 75 ++- .../TombLib.Scripting.GameFlowScript.csproj | 4 +- .../LuaEditor.Intellisense.cs | 316 ++++++++++ .../LuaEditor.Navigation.cs | 171 ++++++ .../LuaEditor.SignatureHelp.cs | 171 ++++++ TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 17 +- .../Objects/LuaCompletionData.cs | 25 + .../Objects/LuaCompletionItem.cs | 18 + .../Objects/LuaDefinitionLocation.cs | 18 + .../Objects/LuaHoverInfo.cs | 16 + .../Objects/LuaSignatureInfo.cs | 34 ++ .../Services/ILuaIntellisenseProvider.cs | 33 + .../TombLib.Scripting.Lua.csproj | 5 +- .../Implementations/GameflowHoverService.cs | 4 +- .../Tomb1MainEditor.cs | 15 +- .../TombLib.Scripting.Tomb1Main.csproj | 7 +- .../Utils/ErrorDetector.cs | 39 +- .../TombLib.Scripting/Bases/TextEditorBase.cs | 485 ++++++++++++--- .../Interfaces/IErrorDetector.cs | 4 +- .../Objects/TextEditorDiagnostic.cs | 26 + .../Objects/TextEditorDiagnosticSeverity.cs | 23 + .../Rendering/BookmarkRenderer.cs | 20 +- .../Rendering/ErrorRenderer.cs | 127 +++- .../Rendering/MarkdownToolTipRenderer.cs | 479 +++++++++++++++ .../Rendering/TextRendering.cs | 56 -- .../TombLib.Scripting.csproj | 6 +- .../Workers/ErrorDetectionWorker.cs | 20 +- TombLib/TombLib.Test/TombLib.Test.csproj | 5 +- 50 files changed, 4039 insertions(+), 272 deletions(-) create mode 100644 TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs create mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs create mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs create mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs create mode 100644 TombLib/TombLib.Scripting/Objects/TextEditorDiagnostic.cs create mode 100644 TombLib/TombLib.Scripting/Objects/TextEditorDiagnosticSeverity.cs create mode 100644 TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs delete mode 100644 TombLib/TombLib.Scripting/Rendering/TextRendering.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs new file mode 100644 index 0000000000..23eb687372 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -0,0 +1,117 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Windows.Forms; +using ICSharpCode.AvalonEdit.Document; +using TombIDE.Shared; +using TombIDE.Shared.SharedClasses; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; +using TombLib.Scripting.Bases; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio +{ + public sealed partial class LuaStudio + { + private readonly ILuaIntellisenseProvider _intellisenseProvider; + + private void HookLuaIntellisense() + { + EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; + EditorTabControl.FileOpened += EditorTabControl_LuaFileOpened; + + _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; + _intellisenseProvider.DiagnosticsUpdated += IntellisenseProvider_DiagnosticsUpdated; + } + + private void DisposeLuaIntellisense() + { + EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; + _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; + _intellisenseProvider.Dispose(); + } + + private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() + { + TENApiService.InjectTENApi(IDE.Instance.Project, IDE.Instance.Project.GetCurrentEngineVersion()); + + string executablePath = LuaLanguageServerLocator.ResolveExecutablePath(IDE.Instance.IDEConfiguration); + return new LuaLanguageServerIntellisenseProvider(ScriptRootDirectoryPath, executablePath); + } + + private void EditorTabControl_LuaFileOpened(object sender, EventArgs e) + { + if (sender is not LuaEditor editor) + return; + + editor.IntellisenseProvider = _intellisenseProvider; + editor.DefinitionNavigationRequested = NavigateToDefinition; + editor.TextChangedDelayed -= LuaEditor_TextChangedDelayed; + editor.TextChangedDelayed += LuaEditor_TextChangedDelayed; + + _intellisenseProvider.OpenDocument(editor.FilePath, editor.Text); + ApplyDiagnosticsToEditor(editor, _intellisenseProvider.GetDiagnostics(editor.FilePath)); + } + + private void LuaEditor_TextChangedDelayed(object sender, EventArgs e) + { + if (sender is LuaEditor editor) + _intellisenseProvider.UpdateDocument(editor.FilePath, editor.Text); + } + + private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyList diagnostics) + { + if (InvokeRequired) + { + BeginInvoke(new Action>(IntellisenseProvider_DiagnosticsUpdated), filePath, diagnostics); + return; + } + + bool matched = false; + + foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) + { + if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) + { + ApplyDiagnosticsToEditor(editor, diagnostics); + matched = true; + } + } + + Debug.WriteLine($"[LuaLS] DiagnosticsUpdated for '{filePath}': {diagnostics?.Count ?? 0} items, tab matched={matched}."); + } + + private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) + { + if (definitionLocation is null || string.IsNullOrWhiteSpace(definitionLocation.FilePath) || !File.Exists(definitionLocation.FilePath)) + return; + + EditorTabControl.OpenFile(definitionLocation.FilePath); + + if (CurrentEditor is not TextEditorBase editor || editor.Document.LineCount == 0) + return; + + int lineNumber = Math.Max(1, Math.Min(definitionLocation.LineNumber, editor.Document.LineCount)); + DocumentLine documentLine = editor.Document.GetLineByNumber(lineNumber); + int columnNumber = Math.Max(1, Math.Min(definitionLocation.ColumnNumber, documentLine.Length + 1)); + int offset = documentLine.Offset + columnNumber - 1; + + editor.Focus(); + editor.CaretOffset = offset; + editor.Select(offset, 0); + editor.ScrollToLine(lineNumber); + } + + private static void ApplyDiagnosticsToEditor(LuaEditor editor, IReadOnlyList diagnostics) + { + int count = editor.LiveErrorUnderlining ? (diagnostics?.Count ?? 0) : 0; + Debug.WriteLine($"[LuaLS] Applying {count} diagnostics to '{editor.FilePath}' (LiveErrorUnderlining={editor.LiveErrorUnderlining})."); + + editor.SetDiagnostics(editor.LiveErrorUnderlining ? diagnostics : Array.Empty()); + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs index 9ebfae2417..7903600f20 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs @@ -5,8 +5,10 @@ using System.Linq; using System.Text.RegularExpressions; using System.Windows.Forms; +using ICSharpCode.AvalonEdit.Document; using TombIDE.ScriptingStudio.Bases; using TombIDE.ScriptingStudio.Controls; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombIDE.ScriptingStudio.ToolWindows; using TombIDE.ScriptingStudio.UI; using TombIDE.Shared; @@ -14,11 +16,14 @@ using TombLib.Scripting.Bases; using TombLib.Scripting.Enums; using TombLib.Scripting.Interfaces; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Objects; namespace TombIDE.ScriptingStudio { - public sealed class LuaStudio : StudioBase + public sealed partial class LuaStudio : StudioBase { public override StudioMode StudioMode => StudioMode.Lua; @@ -38,6 +43,9 @@ public LuaStudio() : base(IDE.Instance.Project.GetScriptRootDirectory(), IDE.Ins FileExplorer.Filter = "*.lua"; FileExplorer.CommentPrefix = "--"; + _intellisenseProvider = CreateLuaIntellisenseProvider(); + HookLuaIntellisense(); + EditorTabControl.CheckPreviousSession(); string initialFilePath = PathHelper.GetScriptFilePath(IDE.Instance.Project.GetScriptRootDirectory(), TombLib.LevelData.TRVersion.Game.TombEngine); @@ -58,6 +66,8 @@ protected override void OnIDEEventRaised(IIDEEvent obj) if (obj is IDE.ProgramClosingEvent) { + DisposeLuaIntellisense(); + IDE.Instance.IDEConfiguration.Lua_DockPanelState = DockPanel.GetDockPanelState(); IDE.Instance.IDEConfiguration.Save(); } @@ -267,7 +277,13 @@ protected override void ApplyUserSettings(IEditorControl editor) protected override void ApplyUserSettings() { foreach (TabPage tab in EditorTabControl.TabPages) - ApplyUserSettings(EditorTabControl.GetEditorOfTab(tab)); + { + IEditorControl editor = EditorTabControl.GetEditorOfTab(tab); + ApplyUserSettings(editor); + + if (editor is LuaEditor luaEditor) + ApplyDiagnosticsToEditor(luaEditor, _intellisenseProvider?.GetDiagnostics(luaEditor.FilePath)); + } UpdateSettings(); } @@ -281,6 +297,11 @@ protected override void HandleDocumentCommands(UICommand command) { switch (command) { + case UICommand.GoToDefinition: + if (CurrentEditor is LuaEditor luaEditor) + luaEditor.NavigateToDefinitionAtCaretAsync(); + break; + case UICommand.LuaBasics: string url = "https://github.com/MontyTRC89/TombEngine/wiki/Basics-of-Lua-Programming"; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs new file mode 100644 index 0000000000..aa03dae5d4 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal sealed class LuaIntellisenseDocumentManager + { + private sealed class DocumentState + { + public string FilePath { get; init; } + public string Uri { get; init; } + public string Content { get; set; } + public int Version { get; set; } + public bool IsOpen { get; set; } + } + + private readonly object _syncRoot = new(); + private readonly Dictionary _documents = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _diagnosticsByFilePath = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _diagnosticsVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); + + public IReadOnlyList GetDiagnostics(string filePath) + { + lock (_syncRoot) + return _diagnosticsByFilePath.TryGetValue(filePath, out IReadOnlyList diagnostics) + ? diagnostics + : Array.Empty(); + } + + public LuaDocumentSynchronizationRequest Synchronize(string filePath, string content) + { + string safeContent = content ?? string.Empty; + + lock (_syncRoot) + { + if (!_documents.TryGetValue(filePath, out DocumentState state)) + { + state = new DocumentState + { + FilePath = filePath, + Uri = LuaLanguageServerPathHelper.CreateFileUri(filePath), + Content = safeContent, + Version = 1, + IsOpen = true + }; + + _documents[filePath] = state; + return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, CreateSnapshot(state)); + } + + if (!state.IsOpen) + { + state.Content = safeContent; + state.Version++; + state.IsOpen = true; + return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, CreateSnapshot(state)); + } + + if (!string.Equals(state.Content, safeContent, StringComparison.Ordinal)) + { + state.Content = safeContent; + state.Version++; + return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Change, CreateSnapshot(state)); + } + + return null; + } + } + + public bool TryClose(string filePath, out LuaDocumentSnapshot document) + { + lock (_syncRoot) + { + if (!_documents.TryGetValue(filePath, out DocumentState state) || !state.IsOpen) + { + document = null; + return false; + } + + state.IsOpen = false; + document = CreateSnapshot(state); + return true; + } + } + + public void PrepareForRestart() + { + lock (_syncRoot) + { + foreach (DocumentState state in _documents.Values) + { + if (state.IsOpen) + state.IsOpen = false; + } + } + } + + public LuaDocumentSnapshot GetDocumentSnapshot(string filePath) + { + lock (_syncRoot) + return _documents.TryGetValue(filePath, out DocumentState state) + ? CreateSnapshot(state) + : null; + } + + public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) + { + lock (_syncRoot) + { + if (publishedDiagnostics.Version > 0 + && _diagnosticsVersionByFilePath.TryGetValue(publishedDiagnostics.FilePath, out int currentVersion) + && publishedDiagnostics.Version < currentVersion) + { + return false; + } + + if (publishedDiagnostics.Version > 0) + _diagnosticsVersionByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Version; + + _diagnosticsByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Diagnostics; + return true; + } + } + + private static LuaDocumentSnapshot CreateSnapshot(DocumentState state) + => new LuaDocumentSnapshot(state.FilePath, state.Uri, state.Content, state.Version); + } + + internal enum LuaDocumentSynchronizationKind + { + Open, + Change + } + + internal sealed class LuaDocumentSynchronizationRequest + { + public LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind kind, LuaDocumentSnapshot document) + { + Kind = kind; + Document = document ?? throw new ArgumentNullException(nameof(document)); + } + + public LuaDocumentSynchronizationKind Kind { get; } + public LuaDocumentSnapshot Document { get; } + } + + internal sealed class LuaDocumentSnapshot + { + public LuaDocumentSnapshot(string filePath, string uri, string content, int version) + { + FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); + Uri = uri ?? throw new ArgumentNullException(nameof(uri)); + Content = content ?? string.Empty; + Version = version; + } + + public string FilePath { get; } + public string Uri { get; } + public string Content { get; } + public int Version { get; } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs new file mode 100644 index 0000000000..7ffa0d104f --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -0,0 +1,577 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal sealed class LuaLanguageServerClient : IDisposable + { + private readonly string _workspaceRootDirectoryPath; + private readonly string _serverExecutablePath; + private readonly Func _settingsProvider; + + private readonly SemaphoreSlim _startLock = new(1, 1); + private readonly SemaphoreSlim _writeLock = new(1, 1); + private readonly ConcurrentDictionary> _pendingRequests = new(); + + private long _requestId; + private bool _isDisposed; + + private Process _process; + private Stream _inputStream; + private Stream _outputStream; + private Task _readLoopTask; + private Task _stderrLoopTask; + + public bool IsReady { get; private set; } + + public event Action DiagnosticsPublished; + + public LuaLanguageServerClient(string workspaceRootDirectoryPath, string serverExecutablePath, Func settingsProvider) + { + _workspaceRootDirectoryPath = workspaceRootDirectoryPath ?? throw new ArgumentNullException(nameof(workspaceRootDirectoryPath)); + _serverExecutablePath = serverExecutablePath ?? throw new ArgumentNullException(nameof(serverExecutablePath)); + _settingsProvider = settingsProvider ?? throw new ArgumentNullException(nameof(settingsProvider)); + } + + public async Task StartAsync(CancellationToken cancellationToken) + { + if (IsReady) + return true; + + await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + if (IsReady) + return true; + + ThrowIfDisposed(); + ResetProcessState(); + + var startInfo = new ProcessStartInfo + { + FileName = _serverExecutablePath, + WorkingDirectory = Path.GetDirectoryName(_serverExecutablePath), + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + _process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }; + _process.Exited += Process_Exited; + + if (!_process.Start()) + return false; + + _inputStream = _process.StandardOutput.BaseStream; + _outputStream = _process.StandardInput.BaseStream; + + _readLoopTask = Task.Run(ReadLoopAsync); + _stderrLoopTask = Task.Run(ReadStandardErrorLoopAsync); + + using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); + + await SendRequestAsync("initialize", BuildInitializeParams(), initializeTimeout.Token).ConfigureAwait(false); + + IsReady = true; + + await SendNotificationAsync("initialized", new { }, cancellationToken).ConfigureAwait(false); + await SendNotificationAsync("workspace/didChangeConfiguration", new { settings = _settingsProvider() }, cancellationToken).ConfigureAwait(false); + + return true; + } + catch + { + await DisposeProcessAsync().ConfigureAwait(false); + return false; + } + finally + { + _startLock.Release(); + } + } + + public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) + => WriteMessageAsync(new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken); + + public async Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) + { + ThrowIfDisposed(); + + long requestId = Interlocked.Increment(ref _requestId); + var responseSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + if (!_pendingRequests.TryAdd(requestId, responseSource)) + throw new InvalidOperationException("Unable to track a new language server request."); + + using var registration = cancellationToken.Register(() => responseSource.TrySetCanceled(cancellationToken)); + + try + { + await WriteMessageAsync(new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken).ConfigureAwait(false); + return await responseSource.Task.ConfigureAwait(false); + } + finally + { + _pendingRequests.TryRemove(requestId, out _); + } + } + + private object BuildInitializeParams() + => new + { + processId = Process.GetCurrentProcess().Id, + rootUri = CreateFileUri(_workspaceRootDirectoryPath), + workspaceFolders = new[] + { + new + { + uri = CreateFileUri(_workspaceRootDirectoryPath), + name = Path.GetFileName(_workspaceRootDirectoryPath) + } + }, + capabilities = new + { + workspace = new + { + workspaceFolders = true, + configuration = true + }, + textDocument = new + { + completion = new + { + completionItem = new + { + snippetSupport = false, + documentationFormat = new[] { "plaintext", "markdown" } + } + }, + hover = new + { + contentFormat = new[] { "plaintext", "markdown" } + }, + definition = new + { + linkSupport = true + }, + publishDiagnostics = new + { + versionSupport = true + }, + signatureHelp = new + { + signatureInformation = new + { + documentationFormat = new[] { "plaintext", "markdown" }, + parameterInformation = new + { + labelOffsetSupport = true + } + }, + contextSupport = true + } + } + } + }; + + private async Task ReadLoopAsync() + { + try + { + while (!_isDisposed) + { + Dictionary headers = await ReadHeadersAsync().ConfigureAwait(false); + + if (headers is null || !headers.TryGetValue("Content-Length", out string contentLengthValue) + || !int.TryParse(contentLengthValue, out int contentLength) || contentLength <= 0) + break; + + byte[] payloadBytes = await ReadPayloadAsync(contentLength).ConfigureAwait(false); + + if (payloadBytes is null) + break; + + using JsonDocument document = JsonDocument.Parse(payloadBytes); + await HandleMessageAsync(document.RootElement).ConfigureAwait(false); + } + } + catch (Exception exception) + { + FailPendingRequests(exception); + } + finally + { + IsReady = false; + } + } + + private async Task ReadStandardErrorLoopAsync() + { + try + { + while (!_isDisposed && _process is not null && !_process.HasExited) + { + string line = await _process.StandardError.ReadLineAsync().ConfigureAwait(false); + + if (line is null) + break; + + if (!string.IsNullOrWhiteSpace(line)) + Debug.WriteLine($"[LuaLS stderr] {line}"); + } + } + catch + { + // Ignore stderr read failures. + } + } + + private async Task> ReadHeadersAsync() + { + var buffer = new List(); + var singleByte = new byte[1]; + + while (true) + { + int bytesRead = await _inputStream.ReadAsync(singleByte.AsMemory(0, 1)).ConfigureAwait(false); + + if (bytesRead == 0) + return null; + + buffer.Add(singleByte[0]); + + if (buffer.Count >= 4 + && buffer[^4] == '\r' + && buffer[^3] == '\n' + && buffer[^2] == '\r' + && buffer[^1] == '\n') + break; + } + + string headerText = Encoding.ASCII.GetString(buffer.ToArray()); + var headers = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (string line in headerText.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) + { + int separatorIndex = line.IndexOf(':'); + + if (separatorIndex <= 0) + continue; + + string key = line[..separatorIndex].Trim(); + string value = line[(separatorIndex + 1)..].Trim(); + + headers[key] = value; + } + + return headers; + } + + private async Task ReadPayloadAsync(int contentLength) + { + byte[] payloadBytes = new byte[contentLength]; + int totalBytesRead = 0; + + while (totalBytesRead < contentLength) + { + int bytesRead = await _inputStream + .ReadAsync(payloadBytes.AsMemory(totalBytesRead, contentLength - totalBytesRead)) + .ConfigureAwait(false); + + if (bytesRead == 0) + return null; + + totalBytesRead += bytesRead; + } + + return payloadBytes; + } + + private async Task HandleMessageAsync(JsonElement message) + { + if (message.TryGetProperty("id", out JsonElement idElement)) + { + if (message.TryGetProperty("method", out JsonElement methodElement)) + { + JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) + ? paramsElement.Clone() + : default; + + await HandleServerRequestAsync(idElement.Clone(), methodElement.GetString(), parameters).ConfigureAwait(false); + } + else + { + HandleServerResponse(idElement, message); + } + } + else if (message.TryGetProperty("method", out JsonElement notificationMethodElement)) + { + JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) + ? paramsElement.Clone() + : default; + + HandleServerNotification(notificationMethodElement.GetString(), parameters); + } + } + + private void HandleServerResponse(JsonElement idElement, JsonElement message) + { + if (!idElement.TryGetInt64(out long requestId) || !_pendingRequests.TryGetValue(requestId, out TaskCompletionSource responseSource)) + return; + + if (message.TryGetProperty("error", out JsonElement errorElement)) + { + string messageText = errorElement.TryGetProperty("message", out JsonElement errorMessageElement) + ? errorMessageElement.GetString() + : "Lua language server request failed."; + + responseSource.TrySetException(new InvalidOperationException(messageText)); + return; + } + + if (message.TryGetProperty("result", out JsonElement resultElement)) + responseSource.TrySetResult(resultElement.Clone()); + else + responseSource.TrySetResult(default); + } + + private async Task HandleServerRequestAsync(JsonElement idElement, string method, JsonElement parameters) + { + object result = method switch + { + "workspace/configuration" => BuildConfigurationResponse(parameters), + "workspace/workspaceFolders" => BuildWorkspaceFolderResponse(), + "client/registerCapability" => null, + "window/workDoneProgress/create" => null, + _ => null + }; + + await WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None).ConfigureAwait(false); + } + + private object[] BuildConfigurationResponse(JsonElement parameters) + { + if (!parameters.TryGetProperty("items", out JsonElement itemsElement) || itemsElement.ValueKind != JsonValueKind.Array) + return Array.Empty(); + + JsonElement settingsElement = JsonSerializer.SerializeToElement(_settingsProvider()); + JsonElement luaElement = settingsElement.GetProperty("Lua"); + + var results = new List(); + + foreach (JsonElement item in itemsElement.EnumerateArray()) + { + string section = item.TryGetProperty("section", out JsonElement sectionElement) + ? sectionElement.GetString() + : null; + + results.Add(GetConfigurationSection(settingsElement, luaElement, section)); + } + + return results.ToArray(); + } + + private static object GetConfigurationSection(JsonElement settingsElement, JsonElement luaElement, string section) + { + if (string.IsNullOrWhiteSpace(section)) + return settingsElement.Clone(); + + if (section.Equals("Lua", StringComparison.OrdinalIgnoreCase)) + return luaElement.Clone(); + + if (section.StartsWith("Lua.", StringComparison.OrdinalIgnoreCase)) + { + JsonElement nestedSection = luaElement; + string[] parts = section[4..].Split('.'); + + foreach (string part in parts) + { + if (!nestedSection.TryGetProperty(part, out JsonElement nextSection)) + return new { }; + + nestedSection = nextSection; + } + + return nestedSection.Clone(); + } + + return new { }; + } + + private object[] BuildWorkspaceFolderResponse() + => new object[] + { + new + { + uri = CreateFileUri(_workspaceRootDirectoryPath), + name = Path.GetFileName(_workspaceRootDirectoryPath) + } + }; + + private void HandleServerNotification(string method, JsonElement parameters) + { + switch (method) + { + case "textDocument/publishDiagnostics": + DiagnosticsPublished?.Invoke(parameters); + return; + case "window/logMessage": + case "window/showMessage": + case "telemetry/event": + case "$/progress": + return; + } + } + + private async Task WriteMessageAsync(object payload, CancellationToken cancellationToken) + { + ThrowIfDisposed(); + + byte[] payloadBytes = JsonSerializer.SerializeToUtf8Bytes(payload); + byte[] headerBytes = Encoding.ASCII.GetBytes($"Content-Length: {payloadBytes.Length}\r\n\r\n"); + + await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await _outputStream.WriteAsync(headerBytes.AsMemory(0, headerBytes.Length), cancellationToken).ConfigureAwait(false); + await _outputStream.WriteAsync(payloadBytes.AsMemory(0, payloadBytes.Length), cancellationToken).ConfigureAwait(false); + await _outputStream.FlushAsync(cancellationToken).ConfigureAwait(false); + } + finally + { + _writeLock.Release(); + } + } + + private void Process_Exited(object sender, EventArgs e) + { + int? exitCode = null; + + try + { + if (_process is not null && _process.HasExited) + exitCode = _process.ExitCode; + } + catch + { + // Ignore exit-code access failures. + } + + IsReady = false; + Debug.WriteLine($"[LuaLS] Process exited unexpectedly{(exitCode is not null ? $" with code {exitCode.Value}" : string.Empty)}."); + FailPendingRequests(new IOException("The Lua language server process exited unexpectedly.")); + } + + private void FailPendingRequests(Exception exception) + { + foreach (KeyValuePair> pendingRequest in _pendingRequests) + pendingRequest.Value.TrySetException(exception); + } + + private async Task DisposeProcessAsync() + { + try + { + if (_process is not null && !_process.HasExited) + { + using var shutdownTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); + + try + { + await SendRequestAsync("shutdown", new { }, shutdownTimeout.Token).ConfigureAwait(false); + } + catch + { + // Ignore shutdown failures. + } + + try + { + await SendNotificationAsync("exit", new { }, shutdownTimeout.Token).ConfigureAwait(false); + } + catch + { + // Ignore exit notification failures. + } + + if (!_process.HasExited) + _process.Kill(true); + } + } + catch + { + // Ignore process disposal failures. + } + finally + { + ResetProcessState(); + IsReady = false; + } + } + + private void ResetProcessState() + { + try + { + if (_process is not null) + _process.Exited -= Process_Exited; + } + catch + { + // Ignore event detach failures. + } + + try + { + _inputStream?.Dispose(); + _outputStream?.Dispose(); + _process?.Dispose(); + } + catch + { + // Ignore stream disposal failures. + } + + _inputStream = null; + _outputStream = null; + _process = null; + _readLoopTask = null; + _stderrLoopTask = null; + } + + private void ThrowIfDisposed() + { + if (_isDisposed) + throw new ObjectDisposedException(nameof(LuaLanguageServerClient)); + } + + private static string CreateFileUri(string path) + => new Uri(Path.GetFullPath(path)).AbsoluteUri; + + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + FailPendingRequests(new ObjectDisposedException(nameof(LuaLanguageServerClient))); + + DisposeProcessAsync().GetAwaiter().GetResult(); + + _startLock.Dispose(); + _writeLock.Dispose(); + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs new file mode 100644 index 0000000000..d394d6fb81 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs @@ -0,0 +1,297 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using ICSharpCode.AvalonEdit.Document; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal static class LuaLanguageServerDiagnosticsParser + { + public static bool TryParse(JsonElement parameters, string filePath, + string documentContent, int documentVersion, out LuaPublishedDiagnostics publishedDiagnostics) + { + publishedDiagnostics = null; + + if (parameters.ValueKind != JsonValueKind.Object) + return false; + + int diagnosticsVersion = 0; + + if (parameters.TryGetProperty("version", out JsonElement versionElement) + && versionElement.ValueKind == JsonValueKind.Number + && versionElement.TryGetInt32(out int parsedVersion) + && parsedVersion > 0) + { + diagnosticsVersion = parsedVersion; + } + + if (diagnosticsVersion > 0 && documentVersion > 0 && diagnosticsVersion > documentVersion) + return false; + + IReadOnlyList diagnostics = Array.Empty(); + string resolvedContent = ResolveDocumentContent(filePath, documentContent); + + if (parameters.TryGetProperty("diagnostics", out JsonElement diagnosticsElement) + && diagnosticsElement.ValueKind == JsonValueKind.Array) + { + diagnostics = BuildDiagnostics(resolvedContent, diagnosticsElement); + } + + publishedDiagnostics = new LuaPublishedDiagnostics(filePath, diagnostics, diagnosticsVersion); + return true; + } + + private static string ResolveDocumentContent(string filePath, string documentContent) + { + if (!string.IsNullOrEmpty(documentContent)) + return documentContent; + + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + return string.Empty; + + try + { + return File.ReadAllText(filePath); + } + catch + { + return string.Empty; + } + } + + private static IReadOnlyList BuildDiagnostics(string content, JsonElement diagnosticsElement) + { + var document = new TextDocument(content ?? string.Empty); + var diagnostics = new List(); + + foreach (JsonElement diagnosticElement in diagnosticsElement.EnumerateArray()) + { + TextEditorDiagnosticSeverity severity = GetDiagnosticSeverity(diagnosticElement); + + if (severity > TextEditorDiagnosticSeverity.Warning) + continue; + + if (!TryCreateDiagnostic(document, diagnosticElement, severity, out TextEditorDiagnostic diagnostic)) + continue; + + diagnostics.Add(diagnostic); + } + + return diagnostics + .OrderBy(diagnostic => diagnostic.StartOffset) + .ThenBy(diagnostic => diagnostic.Severity) + .ToList(); + } + + private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagnosticElement, + TextEditorDiagnosticSeverity severity, out TextEditorDiagnostic diagnostic) + { + diagnostic = null; + + if (document.LineCount == 0 + || !diagnosticElement.TryGetProperty("range", out JsonElement rangeElement) + || !rangeElement.TryGetProperty("start", out JsonElement startElement) + || startElement.ValueKind != JsonValueKind.Object + || !startElement.TryGetProperty("line", out JsonElement lineElement) + || !lineElement.TryGetInt32(out int lineIndex)) + { + return false; + } + + lineIndex = Math.Max(0, Math.Min(lineIndex, document.LineCount - 1)); + + int startCharacter = startElement.TryGetProperty("character", out JsonElement characterElement) + && characterElement.TryGetInt32(out int character) + ? Math.Max(0, character) + : 0; + + int endLineIndex = lineIndex; + int endCharacter = startCharacter; + + if (rangeElement.TryGetProperty("end", out JsonElement endElement) + && endElement.ValueKind == JsonValueKind.Object + && endElement.TryGetProperty("line", out JsonElement endLineElement) + && endLineElement.TryGetInt32(out int rawEndLineIndex)) + { + endLineIndex = Math.Max(lineIndex, Math.Min(rawEndLineIndex, document.LineCount - 1)); + + if (endElement.TryGetProperty("character", out JsonElement endCharacterElement) + && endCharacterElement.TryGetInt32(out int endCharacterValue)) + { + endCharacter = Math.Max(0, endCharacterValue); + } + } + + if (!TryGetDiagnosticOffsets(document, lineIndex, startCharacter, endLineIndex, endCharacter, + out int startOffset, out int endOffset)) + { + return false; + } + + diagnostic = new TextEditorDiagnostic(severity, BuildDiagnosticMessage(diagnosticElement, severity), startOffset, endOffset); + return true; + } + + private static bool TryGetDiagnosticOffsets(TextDocument document, + int startLineIndex, int startCharacter, int endLineIndex, int endCharacter, + out int startOffset, out int endOffset) + { + startOffset = 0; + endOffset = 0; + + if (document.LineCount == 0) + return false; + + DocumentLine startLine = document.GetLineByNumber(startLineIndex + 1); + DocumentLine endLine = document.GetLineByNumber(endLineIndex + 1); + startOffset = startLine.Offset + Math.Max(0, Math.Min(startCharacter, startLine.Length)); + endOffset = endLine.Offset + Math.Max(0, Math.Min(endCharacter, endLine.Length)); + + if (endOffset > startOffset) + return true; + + string lineText = document.GetText(startLine); + + if (string.IsNullOrEmpty(lineText)) + return false; + + int safeCharacter = Math.Max(0, Math.Min(startCharacter, Math.Max(0, lineText.Length - 1))); + + if (TryGetWordBounds(lineText, safeCharacter, out int wordStart, out int wordEnd)) + { + startOffset = startLine.Offset + wordStart; + endOffset = startLine.Offset + wordEnd; + return endOffset > startOffset; + } + + int trimmedStart = 0; + int trimmedEnd = lineText.Length; + + while (trimmedStart < trimmedEnd && char.IsWhiteSpace(lineText[trimmedStart])) + trimmedStart++; + + while (trimmedEnd > trimmedStart && char.IsWhiteSpace(lineText[trimmedEnd - 1])) + trimmedEnd--; + + if (trimmedEnd > trimmedStart) + { + startOffset = startLine.Offset + trimmedStart; + endOffset = startLine.Offset + trimmedEnd; + return true; + } + + startOffset = startLine.Offset + safeCharacter; + endOffset = Math.Min(startOffset + 1, document.TextLength); + return endOffset > startOffset; + } + + private static bool TryGetWordBounds(string lineText, int index, out int wordStart, out int wordEnd) + { + wordStart = 0; + wordEnd = 0; + + if (string.IsNullOrEmpty(lineText)) + return false; + + int safeIndex = Math.Max(0, Math.Min(index, lineText.Length - 1)); + + if (!IsDiagnosticSegmentCharacter(lineText[safeIndex]) && safeIndex > 0 && IsDiagnosticSegmentCharacter(lineText[safeIndex - 1])) + safeIndex--; + + while (safeIndex < lineText.Length && !IsDiagnosticSegmentCharacter(lineText[safeIndex])) + { + safeIndex++; + + if (safeIndex >= lineText.Length) + return false; + } + + wordStart = safeIndex; + wordEnd = safeIndex; + + while (wordStart > 0 && IsDiagnosticSegmentCharacter(lineText[wordStart - 1])) + wordStart--; + + while (wordEnd < lineText.Length && IsDiagnosticSegmentCharacter(lineText[wordEnd])) + wordEnd++; + + return wordEnd > wordStart; + } + + private static bool IsDiagnosticSegmentCharacter(char c) + => char.IsLetterOrDigit(c) || c == '_' || c == '.' || c == ':' || c == '\'' || c == '"'; + + private static TextEditorDiagnosticSeverity GetDiagnosticSeverity(JsonElement diagnosticElement) + => diagnosticElement.TryGetProperty("severity", out JsonElement severityElement) + && severityElement.TryGetInt32(out int severity) + && severity > 0 + ? (TextEditorDiagnosticSeverity)severity + : TextEditorDiagnosticSeverity.Warning; + + private static string BuildDiagnosticMessage(JsonElement diagnosticElement, TextEditorDiagnosticSeverity severity) + { + string message = diagnosticElement.TryGetProperty("message", out JsonElement messageElement) + ? messageElement.GetString()?.Trim() + : null; + + if (string.IsNullOrWhiteSpace(message)) + message = "Unknown Lua diagnostic."; + + var builder = new StringBuilder(); + builder.Append(severity.GetLabel()); + builder.Append(": "); + builder.Append(message); + + string source = diagnosticElement.TryGetProperty("source", out JsonElement sourceElement) + ? sourceElement.GetString() + : null; + + string code = diagnosticElement.TryGetProperty("code", out JsonElement codeElement) + ? codeElement.ValueKind == JsonValueKind.String + ? codeElement.GetString() + : codeElement.ValueKind == JsonValueKind.Number + ? codeElement.GetRawText() + : null + : null; + + if (!string.IsNullOrWhiteSpace(source) || !string.IsNullOrWhiteSpace(code)) + { + builder.AppendLine(); + builder.AppendLine(); + builder.Append("Source: "); + + if (!string.IsNullOrWhiteSpace(source)) + builder.Append(source.Trim()); + else + builder.Append("Lua language server"); + + if (!string.IsNullOrWhiteSpace(code)) + { + builder.Append(" ("); + builder.Append(code.Trim()); + builder.Append(')'); + } + } + + return builder.ToString(); + } + } + + internal sealed class LuaPublishedDiagnostics + { + public LuaPublishedDiagnostics(string filePath, IReadOnlyList diagnostics, int version) + { + FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); + Diagnostics = diagnostics ?? Array.Empty(); + Version = version; + } + + public string FilePath { get; } + public IReadOnlyList Diagnostics { get; } + public int Version { get; } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs new file mode 100644 index 0000000000..5b3ea9a978 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -0,0 +1,295 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal sealed class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider + { + private readonly string _workspaceRootDirectoryPath; + private readonly LuaLanguageServerClient _client; + private readonly LuaIntellisenseDocumentManager _documents = new(); + private readonly SemaphoreSlim _startLock = new(1, 1); + + private bool _isDisposed; + private bool _startupSucceeded; + + public bool IsAvailable => !_isDisposed && _client is not null; + public event Action> DiagnosticsUpdated; + + public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string serverExecutablePath) + { + _workspaceRootDirectoryPath = workspaceRootDirectoryPath is null + ? throw new ArgumentNullException(nameof(workspaceRootDirectoryPath)) + : LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); + + if (!string.IsNullOrWhiteSpace(serverExecutablePath)) + { + _client = new LuaLanguageServerClient(_workspaceRootDirectoryPath, serverExecutablePath, BuildLuaSettings); + _client.DiagnosticsPublished += HandleDiagnosticsPublished; + } + } + + public IReadOnlyList GetDiagnostics(string filePath) + { + if (_isDisposed) + return Array.Empty(); + + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return Array.Empty(); + + return _documents.GetDiagnostics(normalizedFilePath); + } + + public void OpenDocument(string filePath, string content) + => _ = TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None); + + public void UpdateDocument(string filePath, string content) + => _ = TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None); + + public void CloseDocument(string filePath) + { + if (_isDisposed || _client is null || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return; + + if (!_documents.TryClose(normalizedFilePath, out LuaDocumentSnapshot document)) + return; + + _ = CloseDocumentAsync(document, CancellationToken.None); + } + + public async Task> GetCompletionItemsAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) + { + return Array.Empty(); + } + + JsonElement response = await _client.SendRequestAsync("textDocument/completion", + new + { + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column }, + context = new { triggerKind = 1 } + }, cancellationToken).ConfigureAwait(false); + + return LuaLanguageServerResponseParser.ParseCompletionItems(response); + } + + public async Task GetHoverAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) + { + return null; + } + + JsonElement response = await _client.SendRequestAsync("textDocument/hover", + new + { + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column } + }, cancellationToken).ConfigureAwait(false); + + return LuaLanguageServerResponseParser.ParseHoverInfo(response); + } + + public async Task GetDefinitionAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) + { + Debug.WriteLine($"[LuaLS] Definition request aborted: document sync failed for '{filePath}'."); + return null; + } + + JsonElement response = await _client.SendRequestAsync("textDocument/definition", + new + { + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column } + }, cancellationToken).ConfigureAwait(false); + + LuaDefinitionLocation result = LuaLanguageServerResponseParser.ParseDefinitionLocation(response); + Debug.WriteLine($"[LuaLS] Definition at ({line},{column}): {(result is not null ? $"'{result.FilePath}' L{result.LineNumber}" : "null")}."); + return result; + } + + public async Task GetSignatureHelpAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) + { + return null; + } + + JsonElement response = await _client.SendRequestAsync("textDocument/signatureHelp", + new + { + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column } + }, cancellationToken).ConfigureAwait(false); + + return LuaLanguageServerResponseParser.ParseSignatureHelp(response); + } + + private async Task EnsureStartedAsync(CancellationToken cancellationToken) + { + if (_client is null) + return false; + + if (_startupSucceeded && _client.IsReady) + return true; + + await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + if (_startupSucceeded && _client.IsReady) + return true; + + if (_startupSucceeded && !_client.IsReady) + { + Debug.WriteLine("[LuaLS] Server connection dropped, restarting and reopening tracked documents."); + _documents.PrepareForRestart(); + } + + _startupSucceeded = await _client.StartAsync(cancellationToken).ConfigureAwait(false); + + Debug.WriteLine($"[LuaLS] Server startup result: {_startupSucceeded}."); + return _startupSucceeded; + } + finally + { + _startLock.Release(); + } + } + + private Task TrySynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return Task.FromResult(false); + + return SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken); + } + + private async Task SynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) + { + if (_isDisposed || string.IsNullOrWhiteSpace(filePath) || _client is null) + return false; + + if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) + return false; + + LuaDocumentSynchronizationRequest request = _documents.Synchronize(filePath, content); + + if (request is null) + return true; + + if (request.Kind == LuaDocumentSynchronizationKind.Open) + { + await _client.SendNotificationAsync("textDocument/didOpen", + new + { + textDocument = new + { + uri = request.Document.Uri, + languageId = "lua", + version = request.Document.Version, + text = request.Document.Content + } + }, cancellationToken).ConfigureAwait(false); + } + else if (request.Kind == LuaDocumentSynchronizationKind.Change) + { + await _client.SendNotificationAsync("textDocument/didChange", + new + { + textDocument = new + { + uri = request.Document.Uri, + version = request.Document.Version + }, + contentChanges = new[] + { + new { text = request.Document.Content } + } + }, cancellationToken).ConfigureAwait(false); + } + + return true; + } + + private async Task CloseDocumentAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) + { + if (_client is null) + return; + + try + { + if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) + return; + + await _client.SendNotificationAsync("textDocument/didClose", + new { textDocument = new { uri = document.Uri } }, cancellationToken).ConfigureAwait(false); + } + catch + { + // Ignore best-effort close failures. + } + } + + private object BuildLuaSettings() + => LuaLanguageServerSettingsFactory.Create(_workspaceRootDirectoryPath); + + private void HandleDiagnosticsPublished(JsonElement parameters) + { + if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters, out string filePath)) + { + Debug.WriteLine("[LuaLS] Diagnostics rejected: unable to resolve file path."); + return; + } + + LuaDocumentSnapshot document = _documents.GetDocumentSnapshot(filePath); + + if (!LuaLanguageServerDiagnosticsParser.TryParse(parameters, filePath, + document?.Content, document?.Version ?? 0, out LuaPublishedDiagnostics publishedDiagnostics)) + { + Debug.WriteLine($"[LuaLS] Diagnostics rejected for '{filePath}'."); + return; + } + + if (!_documents.TryStoreDiagnostics(publishedDiagnostics)) + { + Debug.WriteLine($"[LuaLS] Diagnostics ignored as stale for '{publishedDiagnostics.FilePath}'."); + return; + } + + Debug.WriteLine($"[LuaLS] Publishing {publishedDiagnostics.Diagnostics.Count} diagnostics for '{publishedDiagnostics.FilePath}'."); + DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); + } + + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + if (_client is not null) + _client.DiagnosticsPublished -= HandleDiagnosticsPublished; + _startLock.Dispose(); + _client?.Dispose(); + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs new file mode 100644 index 0000000000..9c693b9ffe --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using TombIDE.Shared; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal static class LuaLanguageServerLocator + { + private const string ExecutableFileName = "lua-language-server.exe"; + + private static readonly string[] ExtensionRoots = + { + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".vscode", "extensions"), + Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".vscode-insiders", "extensions") + }; + + public static string ResolveExecutablePath(IDEConfiguration config) + { + if (config is not null && IsValidExecutablePath(config.LuaLanguageServerPath)) + return config.LuaLanguageServerPath; + + string executablePath = FindExecutableInPath(); + + if (executablePath is null) + executablePath = FindExecutableInExtensions(); + + if (config is not null && !string.IsNullOrWhiteSpace(executablePath) + && !string.Equals(config.LuaLanguageServerPath, executablePath, StringComparison.OrdinalIgnoreCase)) + { + config.LuaLanguageServerPath = executablePath; + config.Save(); + } + + return executablePath; + } + + private static bool IsValidExecutablePath(string executablePath) + => !string.IsNullOrWhiteSpace(executablePath) + && File.Exists(executablePath) + && Path.GetFileName(executablePath).Equals(ExecutableFileName, StringComparison.OrdinalIgnoreCase); + + private static string FindExecutableInPath() + { + string pathVariable = Environment.GetEnvironmentVariable("PATH"); + + if (string.IsNullOrWhiteSpace(pathVariable)) + return null; + + foreach (string pathPart in pathVariable.Split(Path.PathSeparator).Where(part => !string.IsNullOrWhiteSpace(part))) + { + try + { + string candidatePath = Path.Combine(pathPart.Trim(), ExecutableFileName); + + if (IsValidExecutablePath(candidatePath)) + return candidatePath; + } + catch + { + // Ignore invalid PATH entries. + } + } + + return null; + } + + private static string FindExecutableInExtensions() + { + var candidates = new List(); + + foreach (string extensionRoot in ExtensionRoots) + { + if (!Directory.Exists(extensionRoot)) + continue; + + foreach (string extensionDirectory in Directory.EnumerateDirectories(extensionRoot) + .Where(path => Path.GetFileName(path).Contains("lua", StringComparison.OrdinalIgnoreCase)) + .OrderByDescending(path => Path.GetFileName(path), StringComparer.OrdinalIgnoreCase)) + { + try + { + candidates.AddRange(Directory.EnumerateFiles(extensionDirectory, ExecutableFileName, SearchOption.AllDirectories)); + } + catch + { + // Ignore directories we cannot access. + } + } + } + + return candidates.FirstOrDefault(IsValidExecutablePath); + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs new file mode 100644 index 0000000000..dc9ad4292e --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs @@ -0,0 +1,83 @@ +using System; +using System.IO; +using System.Text.Json; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal static class LuaLanguageServerPathHelper + { + public static string CreateFileUri(string filePath) + => new Uri(NormalizeLocalPath(filePath)).AbsoluteUri; + + public static string NormalizeLocalPath(string filePath) + { + if (string.IsNullOrWhiteSpace(filePath)) + throw new ArgumentException("File path must not be empty.", nameof(filePath)); + + string sanitizedFilePath = filePath.Replace('/', Path.DirectorySeparatorChar); + return Path.GetFullPath(sanitizedFilePath); + } + + public static string NormalizeLocalPath(Uri uri) + { + if (uri is null) + throw new ArgumentNullException(nameof(uri)); + + string localPath = uri.LocalPath; + + if (Path.DirectorySeparatorChar == '\\' + && localPath.Length >= 3 + && localPath[0] == '/' + && char.IsLetter(localPath[1]) + && localPath[2] == ':') + { + localPath = localPath[1..]; + } + + localPath = localPath.Replace('/', Path.DirectorySeparatorChar); + return Path.GetFullPath(localPath); + } + + public static bool TryNormalizeLocalPath(string filePath, out string normalizedFilePath) + { + normalizedFilePath = null; + + if (string.IsNullOrWhiteSpace(filePath)) + return false; + + try + { + normalizedFilePath = NormalizeLocalPath(filePath); + return true; + } + catch + { + return false; + } + } + + public static bool TryGetFilePath(JsonElement parameters, out string filePath) + { + filePath = null; + + if (parameters.ValueKind != JsonValueKind.Object + || !parameters.TryGetProperty("uri", out JsonElement uriElement) + || string.IsNullOrWhiteSpace(uriElement.GetString()) + || !Uri.TryCreate(uriElement.GetString(), UriKind.Absolute, out Uri uri) + || !uri.IsFile) + { + return false; + } + + try + { + filePath = NormalizeLocalPath(uri); + return true; + } + catch + { + return false; + } + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs new file mode 100644 index 0000000000..64ac8cb6dc --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -0,0 +1,359 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal static class LuaLanguageServerResponseParser + { + private readonly struct MarkupContent + { + public MarkupContent(string text, bool isMarkdown) + { + Text = text; + IsMarkdown = isMarkdown; + } + + public string Text { get; } + public bool IsMarkdown { get; } + } + + public static IReadOnlyList ParseCompletionItems(JsonElement response) + { + JsonElement itemsElement = response; + + if (response.ValueKind == JsonValueKind.Object && response.TryGetProperty("items", out JsonElement completionItemsElement)) + itemsElement = completionItemsElement; + + if (itemsElement.ValueKind != JsonValueKind.Array) + return Array.Empty(); + + var items = new List(); + + foreach (JsonElement itemElement in itemsElement.EnumerateArray()) + { + if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) + continue; + + string label = labelElement.GetString(); + string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) + && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) + ? newTextElement.GetString() + : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) + ? insertTextElement.GetString() + : label; + + if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) + && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) + { + insertText = StripSnippetPlaceholders(insertText); + } + + string description = BuildCompletionDescription(itemElement); + items.Add(new LuaCompletionItem(label, insertText, description)); + } + + return items + .GroupBy(item => $"{item.Label}\0{item.InsertText}", StringComparer.OrdinalIgnoreCase) + .Select(group => group.First()) + .ToList(); + } + + public static LuaHoverInfo ParseHoverInfo(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) + return null; + + MarkupContent hoverContent = ExtractMarkupContent(contentsElement); + + return string.IsNullOrWhiteSpace(hoverContent.Text) + ? null + : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); + } + + public static LuaDefinitionLocation ParseDefinitionLocation(JsonElement response) + { + JsonElement definitionElement = response; + + if (response.ValueKind == JsonValueKind.Array) + { + definitionElement = response.EnumerateArray().FirstOrDefault(); + + if (definitionElement.ValueKind == JsonValueKind.Undefined) + return null; + } + + if (definitionElement.ValueKind != JsonValueKind.Object) + return null; + + string uri = definitionElement.TryGetProperty("targetUri", out JsonElement targetUriElement) + ? targetUriElement.GetString() + : definitionElement.TryGetProperty("uri", out JsonElement uriElement) + ? uriElement.GetString() + : null; + + if (string.IsNullOrWhiteSpace(uri) || !Uri.TryCreate(uri, UriKind.Absolute, out Uri parsedUri) || !parsedUri.IsFile) + return null; + + JsonElement startElement = definitionElement.TryGetProperty("targetSelectionRange", out JsonElement targetSelectionRangeElement) + && targetSelectionRangeElement.TryGetProperty("start", out JsonElement targetSelectionStartElement) + ? targetSelectionStartElement + : definitionElement.TryGetProperty("targetRange", out JsonElement targetRangeElement) + && targetRangeElement.TryGetProperty("start", out JsonElement targetRangeStartElement) + ? targetRangeStartElement + : definitionElement.TryGetProperty("range", out JsonElement rangeElement) + && rangeElement.TryGetProperty("start", out JsonElement rangeStartElement) + ? rangeStartElement + : default; + + if (startElement.ValueKind != JsonValueKind.Object) + return null; + + int lineNumber = startElement.TryGetProperty("line", out JsonElement lineElement) ? lineElement.GetInt32() + 1 : 1; + int columnNumber = startElement.TryGetProperty("character", out JsonElement characterElement) ? characterElement.GetInt32() + 1 : 1; + + return new LuaDefinitionLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), lineNumber, columnNumber); + } + + public static LuaSignatureInfo ParseSignatureHelp(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object + || !response.TryGetProperty("signatures", out JsonElement signaturesElement) + || signaturesElement.ValueKind != JsonValueKind.Array) + { + return null; + } + + int activeSignature = response.TryGetProperty("activeSignature", out JsonElement activeSignatureElement) + && activeSignatureElement.TryGetInt32(out int parsedActiveSignature) + ? Math.Max(0, parsedActiveSignature) + : 0; + + int signatureIndex = 0; + JsonElement signatureElement = default; + + foreach (JsonElement candidate in signaturesElement.EnumerateArray()) + { + if (signatureIndex == activeSignature) + { + signatureElement = candidate; + break; + } + + signatureIndex++; + } + + if (signatureElement.ValueKind != JsonValueKind.Object + || !signatureElement.TryGetProperty("label", out JsonElement labelElement)) + { + return null; + } + + string label = labelElement.GetString(); + + if (string.IsNullOrWhiteSpace(label)) + return null; + + string documentation = signatureElement.TryGetProperty("documentation", out JsonElement documentationElement) + ? ExtractMarkupText(documentationElement) + : null; + + int activeParameter = response.TryGetProperty("activeParameter", out JsonElement activeParameterElement) + && activeParameterElement.TryGetInt32(out int parsedActiveParameter) + ? Math.Max(0, parsedActiveParameter) + : signatureElement.TryGetProperty("activeParameter", out JsonElement signatureActiveParameterElement) + && signatureActiveParameterElement.TryGetInt32(out int parsedSignatureActiveParameter) + ? Math.Max(0, parsedSignatureActiveParameter) + : 0; + + var parameters = new List(); + + if (signatureElement.TryGetProperty("parameters", out JsonElement parametersElement) + && parametersElement.ValueKind == JsonValueKind.Array) + { + foreach (JsonElement paramElement in parametersElement.EnumerateArray()) + { + string parameterLabel = paramElement.TryGetProperty("label", out JsonElement paramLabelElement) + ? paramLabelElement.ValueKind == JsonValueKind.String + ? paramLabelElement.GetString() + : TryExtractParameterLabel(label, paramLabelElement, out string extractedLabel) + ? extractedLabel + : null + : null; + + string parameterDocumentation = paramElement.TryGetProperty("documentation", out JsonElement parameterDocumentationElement) + ? ExtractMarkupText(parameterDocumentationElement) + : null; + + parameters.Add(new LuaParameterInfo(parameterLabel, parameterDocumentation)); + } + } + + return new LuaSignatureInfo(label, documentation, parameters, activeParameter); + } + + private static string BuildCompletionDescription(JsonElement itemElement) + { + var descriptionBuilder = new StringBuilder(); + + if (itemElement.TryGetProperty("detail", out JsonElement detailElement)) + { + string detail = detailElement.GetString(); + + if (!string.IsNullOrWhiteSpace(detail)) + descriptionBuilder.AppendLine(detail.Trim()); + } + + if (itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) + { + string documentation = ExtractMarkupText(documentationElement); + + if (!string.IsNullOrWhiteSpace(documentation)) + { + if (descriptionBuilder.Length > 0) + descriptionBuilder.AppendLine(); + + descriptionBuilder.Append(documentation.Trim()); + } + } + + return descriptionBuilder.Length == 0 ? null : descriptionBuilder.ToString(); + } + + private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, out string parameterLabel) + { + parameterLabel = null; + + if (string.IsNullOrEmpty(signatureLabel) + || parameterLabelElement.ValueKind != JsonValueKind.Array) + { + return false; + } + + JsonElement.ArrayEnumerator labelParts = parameterLabelElement.EnumerateArray(); + + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int startIndex)) + return false; + + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int endIndex)) + return false; + + startIndex = Math.Max(0, Math.Min(startIndex, signatureLabel.Length)); + endIndex = Math.Max(startIndex, Math.Min(endIndex, signatureLabel.Length)); + + if (endIndex <= startIndex) + return false; + + parameterLabel = signatureLabel[startIndex..endIndex]; + return true; + } + + private static string ExtractMarkupText(JsonElement element) + => NormalizeMarkupText(ExtractMarkupContent(element).Text); + + private static MarkupContent ExtractMarkupContent(JsonElement element) + { + return element.ValueKind switch + { + JsonValueKind.String => new MarkupContent(element.GetString(), true), + JsonValueKind.Array => CombineMarkupContent(element.EnumerateArray().Select(ExtractMarkupContent)), + JsonValueKind.Object when element.TryGetProperty("value", out JsonElement valueElement) + && element.TryGetProperty("kind", out JsonElement kindElement) + => new MarkupContent(valueElement.GetString(), + string.Equals(kindElement.GetString(), "markdown", StringComparison.OrdinalIgnoreCase)), + JsonValueKind.Object when element.TryGetProperty("language", out JsonElement languageElement) + && element.TryGetProperty("value", out JsonElement codeValueElement) + => new MarkupContent($"```{languageElement.GetString()}\n{codeValueElement.GetString()}\n```", true), + JsonValueKind.Object when element.TryGetProperty("value", out JsonElement plainValueElement) + => new MarkupContent(plainValueElement.GetString(), false), + _ => default + }; + } + + private static MarkupContent CombineMarkupContent(IEnumerable items) + { + bool isMarkdown = false; + var parts = new List(); + + foreach (MarkupContent item in items) + { + if (string.IsNullOrWhiteSpace(item.Text)) + continue; + + parts.Add(item.Text.Trim()); + isMarkdown |= item.IsMarkdown; + } + + return parts.Count == 0 + ? default + : new MarkupContent(string.Join(Environment.NewLine + Environment.NewLine, parts), isMarkdown); + } + + private static string NormalizeMarkupText(string text) + { + if (string.IsNullOrWhiteSpace(text)) + return null; + + string normalized = text + .Replace("```lua", string.Empty, StringComparison.OrdinalIgnoreCase) + .Replace("```", string.Empty, StringComparison.Ordinal) + .Replace("`", string.Empty, StringComparison.Ordinal) + .Replace("\r", string.Empty, StringComparison.Ordinal) + .Trim(); + + string[] lines = normalized + .Split('\n') + .Select(line => line.TrimEnd()) + .ToArray(); + + return string.Join(Environment.NewLine, lines).Trim(); + } + + private static string StripSnippetPlaceholders(string snippet) + { + if (string.IsNullOrWhiteSpace(snippet)) + return snippet; + + var builder = new StringBuilder(snippet.Length); + int index = 0; + + while (index < snippet.Length) + { + if (snippet[index] == '$') + { + if (index + 1 < snippet.Length && snippet[index + 1] == '{') + { + int endIndex = snippet.IndexOf('}', index + 2); + + if (endIndex > index) + { + string placeholder = snippet[(index + 2)..endIndex]; + int separatorIndex = placeholder.IndexOf(':'); + + if (separatorIndex >= 0 && separatorIndex < placeholder.Length - 1) + builder.Append(placeholder[(separatorIndex + 1)..]); + + index = endIndex + 1; + continue; + } + } + + index++; + + while (index < snippet.Length && char.IsDigit(snippet[index])) + index++; + + continue; + } + + builder.Append(snippet[index]); + index++; + } + + return builder.ToString(); + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs new file mode 100644 index 0000000000..951aef8c7f --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs @@ -0,0 +1,44 @@ +using System; +using System.IO; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal static class LuaLanguageServerSettingsFactory + { + public static object Create(string workspaceRootDirectoryPath) + { + string apiDirectory = Path.Combine(workspaceRootDirectoryPath, ".API"); + string[] library = Directory.Exists(apiDirectory) + ? new[] { Path.GetFullPath(apiDirectory) } + : Array.Empty(); + + return new + { + Lua = new + { + runtime = new + { + version = "Lua 5.4" + }, + workspace = new + { + checkThirdParty = false, + library + }, + completion = new + { + callSnippet = "Disable" + }, + diagnostics = new + { + disable = new[] { "duplicate-set-field" } + }, + telemetry = new + { + enable = false + } + } + }; + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Settings/ClassicScriptSettingsControl.cs b/TombIDE/TombIDE.ScriptingStudio/Settings/ClassicScriptSettingsControl.cs index cd90cb033a..1ead99be19 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Settings/ClassicScriptSettingsControl.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Settings/ClassicScriptSettingsControl.cs @@ -547,7 +547,7 @@ private void UpdatePreviewTemp(bool forceUpdate = true) if (editorPreview.LiveErrorUnderlining) editorPreview.CheckForErrors(); else - editorPreview.ResetAllErrors(); + editorPreview.ClearDiagnostics(); editorPreview.WordWrap = checkBox_WordWrapping.Checked; diff --git a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.Designer.cs b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.Designer.cs index 17450950d1..c97b4fcf41 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.Designer.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.Designer.cs @@ -113,13 +113,12 @@ private void InitializeComponent() // checkBox_Autocomplete // checkBox_Autocomplete.AutoSize = true; - checkBox_Autocomplete.Enabled = false; checkBox_Autocomplete.Location = new System.Drawing.Point(6, 166); checkBox_Autocomplete.Margin = new System.Windows.Forms.Padding(6, 6, 3, 0); checkBox_Autocomplete.Name = "checkBox_Autocomplete"; - checkBox_Autocomplete.Size = new System.Drawing.Size(30, 17); + checkBox_Autocomplete.Size = new System.Drawing.Size(135, 17); checkBox_Autocomplete.TabIndex = 6; - checkBox_Autocomplete.Text = "-"; + checkBox_Autocomplete.Text = "Enable autocomplete"; // // checkBox_HighlightCurrentLine // diff --git a/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj b/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj index a9a2c4c87b..ffb6cb8f7f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj +++ b/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj @@ -27,10 +27,9 @@ ..\..\Libs\CustomTabControl.dll - - False - ..\..\Libs\ICSharpCode.AvalonEdit.dll - + + + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml index 8d3bb645af..5689996749 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml @@ -4,6 +4,8 @@ + + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs b/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs index fd6858bae4..ce4ed0fc23 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs +++ b/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs @@ -72,6 +72,7 @@ public enum UICommand // Other: + GoToDefinition, TypeFirstAvailableId, NewFileAtCaret } diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs b/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs index 842f096a46..73af7d14ac 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs +++ b/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs @@ -24,6 +24,7 @@ internal struct UIKeys public const Keys CommentOut = Keys.Control | Keys.Shift | Keys.C; public const Keys Uncomment = Keys.Control | Keys.Shift | Keys.U; public const Keys ToggleBookmark = Keys.Control | Keys.B; + public const Keys GoToDefinition = Keys.F12; public const Keys PrevBookmark = Keys.Control | Keys.Oemcomma; public const Keys NextBookmark = Keys.Control | Keys.OemPeriod; public const Keys ClearBookmarks = Keys.Control | Keys.Shift | Keys.B; diff --git a/TombIDE/TombIDE.Shared/IDEConfiguration.cs b/TombIDE/TombIDE.Shared/IDEConfiguration.cs index a2c51993f1..d82c0a616f 100644 --- a/TombIDE/TombIDE.Shared/IDEConfiguration.cs +++ b/TombIDE/TombIDE.Shared/IDEConfiguration.cs @@ -48,6 +48,7 @@ public class IDEConfiguration public DockPanelState Lua_DockPanelState { get; set; } = DefaultLayouts.LuaLayout; public string VSCodePath { get; set; } = string.Empty; + public string LuaLanguageServerPath { get; set; } = string.Empty; public bool DoNotAskToInstallLuaExtension { get; set; } public static string DefaultPath => Path.Combine(DefaultPaths.ConfigsDirectory, "TombIDEConfiguration.xml"); diff --git a/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml b/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml index 94ac9707ca..9d472b237f 100644 --- a/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml +++ b/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml @@ -64,6 +64,7 @@ Comment out Selected Lines Uncomment Selected Lines Toggle Bookmark + Go to Definition Go to Previous Bookmark Go to Next Bookmark Clear All Bookmarks... diff --git a/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs b/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs index e62cc48d05..c1e0fff52d 100644 --- a/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs +++ b/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs @@ -53,6 +53,7 @@ public class Localization public string CommentOut { get; set; } public string Uncomment { get; set; } public string ToggleBookmark { get; set; } + public string GoToDefinition { get; set; } public string PrevBookmark { get; set; } public string NextBookmark { get; set; } public string ClearBookmarks { get; set; } diff --git a/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml b/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml index 7311a4e7ca..64c95a2b34 100644 --- a/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml +++ b/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml @@ -64,6 +64,7 @@ Wstaw zakomentowanie Usuń zakomentowanie Przełącz zakładkę + Przejdź do definicji Idź do poprzedniej zakładki Idź do następnej zakładki Wyczyść wszystkie zakładki... diff --git a/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs b/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs index 41fba200b5..e80004c37e 100644 --- a/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs +++ b/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs @@ -376,13 +376,10 @@ public void CheckForErrors() private void ErrorWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { - if (e.Result == null) + if (e.Result is not IReadOnlyList diagnostics) return; - ResetAllErrors(); - ApplyErrorsToLines(e.Result as List); - - TextArea.TextView.InvalidateLayer(KnownLayer.Caret); + SetDiagnostics(diagnostics); } #endregion Error handling @@ -444,7 +441,7 @@ private void HandleDefinitionToolTips(MouseEventArgs e) DocumentLine hoveredLine = Document.GetLineByOffset(hoveredOffset); - if (hoveredLine.HasError) + if (HasDiagnosticsOnLine(hoveredLine)) return; string hoveredWord = WordParser.GetWordFromOffset(Document, hoveredOffset); diff --git a/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj b/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj index 02113ddaa1..a44aebf4ac 100644 --- a/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj +++ b/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj @@ -31,10 +31,7 @@ - - False - ..\..\Libs\ICSharpCode.AvalonEdit.dll - + diff --git a/TombLib/TombLib.Scripting.ClassicScript/Utils/ErrorDetector.cs b/TombLib/TombLib.Scripting.ClassicScript/Utils/ErrorDetector.cs index 23615135d3..a819e67358 100644 --- a/TombLib/TombLib.Scripting.ClassicScript/Utils/ErrorDetector.cs +++ b/TombLib/TombLib.Scripting.ClassicScript/Utils/ErrorDetector.cs @@ -7,6 +7,7 @@ using TombLib.Scripting.ClassicScript.Parsers; using TombLib.Scripting.ClassicScript.Resources; using TombLib.Scripting.Interfaces; +using TombLib.Scripting.Objects; namespace TombLib.Scripting.ClassicScript.Utils { @@ -14,16 +15,16 @@ public class ErrorDetector : IErrorDetector { #region Public methods - public object FindErrors(string editorContent, Version engineVersion) + public IReadOnlyList FindErrors(string editorContent, Version engineVersion) => DetectErrorLines(new TextDocument(editorContent)); #endregion Public methods #region Error line finding - private static List DetectErrorLines(TextDocument document) + private static List DetectErrorLines(TextDocument document) { - var errorLines = new List(); + var errorLines = new List(); bool commandSectionCheckRequired = DocumentParser.DocumentContainsSections(document); @@ -34,7 +35,7 @@ private static List DetectErrorLines(TextDocument document) if (LineParser.IsEmptyOrComments(processedLineText)) continue; - ErrorLine error = FindErrorsInLine(document, processedLine, processedLineText, commandSectionCheckRequired); + TextEditorDiagnostic error = FindErrorsInLine(document, processedLine, processedLineText, commandSectionCheckRequired); if (error != null) errorLines.Add(error); @@ -43,40 +44,41 @@ private static List DetectErrorLines(TextDocument document) return errorLines; } - private static ErrorLine FindErrorsInLine(TextDocument document, DocumentLine line, string lineText, bool commandSectionCheckRequired) + private static TextEditorDiagnostic FindErrorsInLine(TextDocument document, DocumentLine line, string lineText, bool commandSectionCheckRequired) { if (LineParser.IsSectionHeaderLine(lineText)) - return FindErrorsInSectionHeaderLine(line, lineText); + return FindErrorsInSectionHeaderLine(document, line, lineText); else { if (commandSectionCheckRequired && LineParser.IsLineInStandardStringSection(document, line)) return null; else if (commandSectionCheckRequired && LineParser.IsLineInExtraNGSection(document, line)) - return FindErrorsInNGStringLine(line, lineText); + return FindErrorsInNGStringLine(document, line, lineText); else return FindErrorsInCommandLine(document, line, lineText, commandSectionCheckRequired); } } - private static ErrorLine FindErrorsInSectionHeaderLine(DocumentLine line, string lineText) + private static TextEditorDiagnostic FindErrorsInSectionHeaderLine(TextDocument document, DocumentLine line, string lineText) { if (!IsValidSectionName(lineText)) - return new ErrorLine("Invalid section name. Please check its spelling.", - line.LineNumber, LineParser.RemoveComments(lineText)); + return CreateDiagnostic(document, line, + "Invalid section name. Please check its spelling.", LineParser.RemoveComments(lineText)); return null; } - private static ErrorLine FindErrorsInNGStringLine(DocumentLine line, string lineText) + private static TextEditorDiagnostic FindErrorsInNGStringLine(TextDocument document, DocumentLine line, string lineText) { if (!IsNGStringLineWellFormatted(lineText)) - return new ErrorLine("NG string must start with an index.\n\nExample:\n0: First String\n1: Second String", - line.LineNumber, LineParser.RemoveComments(lineText)); + return CreateDiagnostic(document, line, + "NG string must start with an index.\n\nExample:\n0: First String\n1: Second String", + LineParser.RemoveComments(lineText)); return null; } - private static ErrorLine FindErrorsInCommandLine(TextDocument document, DocumentLine line, string lineText, bool commandSectionCheckRequired) + private static TextEditorDiagnostic FindErrorsInCommandLine(TextDocument document, DocumentLine line, string lineText, bool commandSectionCheckRequired) { string commandKey = CommandParser.GetCommandKey(document, line.Offset); @@ -90,13 +92,14 @@ private static ErrorLine FindErrorsInCommandLine(TextDocument document, Document if (commandKey == null) errorSegmentText = lineText.TrimEnd(); - return new ErrorLine("Invalid command. Please check its spelling.", - line.LineNumber, errorSegmentText); + return CreateDiagnostic(document, line, + "Invalid command. Please check its spelling.", errorSegmentText); } if (commandSectionCheckRequired && !IsCommandLineInCorrectSection(document, line.LineNumber, commandKey)) - return new ErrorLine("Command is placed in the wrong section. Please check the command syntax.", - line.LineNumber, LineParser.RemoveComments(lineText)); + return CreateDiagnostic(document, line, + "Command is placed in the wrong section. Please check the command syntax.", + LineParser.RemoveComments(lineText)); if (ContainsBrokenNextLines(document, line.Offset)) { @@ -105,8 +108,9 @@ private static ErrorLine FindErrorsInCommandLine(TextDocument document, Document if (errorSegmentText.Length == 0) errorSegmentText = LineParser.RemoveComments(lineText); - return new ErrorLine("Misplaced \">\" symbols were found.\nYou can only use these symbols at the end of the line and there can only be one on each line.", - line.LineNumber, errorSegmentText); + return CreateDiagnostic(document, line, + "Misplaced \">\" symbols were found.\nYou can only use these symbols at the end of the line and there can only be one on each line.", + errorSegmentText); } if (!IsArgumentCountValid(document, line.Offset)) @@ -116,8 +120,8 @@ private static ErrorLine FindErrorsInCommandLine(TextDocument document, Document if (errorSegmentText.Length == 0) errorSegmentText = LineParser.RemoveComments(lineText); - return new ErrorLine("Invalid argument count. Please check the command syntax.", - line.LineNumber, errorSegmentText); + return CreateDiagnostic(document, line, + "Invalid argument count. Please check the command syntax.", errorSegmentText); } if (ContainsEmptyArguments(document, line.Offset)) @@ -127,13 +131,36 @@ private static ErrorLine FindErrorsInCommandLine(TextDocument document, Document if (errorSegmentText.Length == 0) errorSegmentText = LineParser.RemoveComments(lineText); - return new ErrorLine("Empty arguments were found.", - line.LineNumber, errorSegmentText); + return CreateDiagnostic(document, line, "Empty arguments were found.", errorSegmentText); } return null; } + private static TextEditorDiagnostic CreateDiagnostic(TextDocument document, DocumentLine line, string message, string errorSegmentText) + { + string lineText = document.GetText(line); + string segmentText = string.IsNullOrWhiteSpace(errorSegmentText) + ? lineText.Trim() + : errorSegmentText; + + int startOffset = line.Offset; + int endOffset = Math.Max(line.Offset + 1, line.EndOffset); + + if (!string.IsNullOrWhiteSpace(segmentText)) + { + int matchIndex = lineText.IndexOf(segmentText, StringComparison.Ordinal); + + if (matchIndex >= 0) + { + startOffset = line.Offset + matchIndex; + endOffset = startOffset + segmentText.Length; + } + } + + return new TextEditorDiagnostic(TextEditorDiagnosticSeverity.Error, message, startOffset, endOffset); + } + #endregion Error line finding #region Error detection methods diff --git a/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj b/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj index 1c1e9202f5..08d3d8c2d4 100644 --- a/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj +++ b/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj @@ -23,9 +23,7 @@ x86 - - ..\..\Libs\ICSharpCode.AvalonEdit.dll - + diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs new file mode 100644 index 0000000000..f9b79ee6c1 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -0,0 +1,316 @@ +using ICSharpCode.AvalonEdit.Document; +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua +{ + public sealed partial class LuaEditor + { + private CancellationTokenSource _hoverCancellationTokenSource; + private CancellationTokenSource _signatureCancellationTokenSource; + private int _hoverRequestToken; + private Window _hostWindow; + + private void BindLuaIntellisenseEvents() + { + IsKeyboardFocusWithinChanged += LuaEditor_IsKeyboardFocusWithinChanged; + Loaded += LuaEditor_Loaded; + TextArea.TextEntering += TextArea_TextEntering; + TextArea.TextEntered += TextArea_TextEntered; + AddHandler(PreviewKeyDownEvent, new KeyEventHandler(TextEditor_KeyDown), true); + AddHandler(PreviewMouseDownEvent, new MouseButtonEventHandler(TextEditor_PreviewMouseDown), true); + AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(TextEditor_PreviewMouseLeftButtonDown), true); + Unloaded += LuaEditor_Unloaded; + } + + private void LuaEditor_Loaded(object sender, RoutedEventArgs e) + => AttachHostWindowHandlers(); + + private void LuaEditor_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (e.NewValue is bool hasKeyboardFocus && !hasKeyboardFocus) + DismissTransientToolTips(); + } + + private void AttachHostWindowHandlers() + { + Window window = Window.GetWindow(this); + + if (window == _hostWindow) + return; + + if (_hostWindow is not null) + _hostWindow.Deactivated -= HostWindow_Deactivated; + + _hostWindow = window; + + if (_hostWindow is not null) + _hostWindow.Deactivated += HostWindow_Deactivated; + } + + private void HostWindow_Deactivated(object sender, EventArgs e) + => DismissTransientToolTips(); + + private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) + { + _hoverCancellationTokenSource?.Cancel(); + _hoverCancellationTokenSource?.Dispose(); + _hoverCancellationTokenSource = null; + + _signatureCancellationTokenSource?.Cancel(); + _signatureCancellationTokenSource?.Dispose(); + _signatureCancellationTokenSource = null; + + if (_hostWindow is not null) + _hostWindow.Deactivated -= HostWindow_Deactivated; + + _hostWindow = null; + + DismissSignatureHelp(); + ClearDiagnostics(); + + IntellisenseProvider?.CloseDocument(FilePath); + } + + private async void TextArea_TextEntering(object sender, TextCompositionEventArgs e) + { + if (!AutocompleteEnabled || !IsIntellisenseAvailable()) + return; + + if (e.Text == " " && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) + { + e.Handled = true; + + await RequestCompletionAsync(CaretOffset).ConfigureAwait(true); + } + } + + private async void TextArea_TextEntered(object sender, TextCompositionEventArgs e) + { + if (!IsIntellisenseAvailable()) + return; + + if (e.Text == "(" || e.Text == ",") + { + CloseCompletionWindow(); + await RequestSignatureHelpAsync(CaretOffset).ConfigureAwait(true); + return; + } + + if (e.Text == ")") + { + CloseCompletionWindow(); + DismissSignatureHelp(); + return; + } + + if (_completionWindow is not null && !ShouldKeepCompletionWindowOpen(e.Text)) + { + CloseCompletionWindow(); + return; + } + + if (!AutocompleteEnabled) + return; + + if (ShouldTriggerAutocomplete(e.Text)) + await RequestCompletionAsync(CaretOffset).ConfigureAwait(true); + } + + protected override async void HandleMouseHover(MouseEventArgs e) + { + int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); + + if (hoveredOffset == -1) + return; + + if (TryShowDiagnosticToolTip(hoveredOffset)) + return; + + if (!IsIntellisenseAvailable()) + return; + + string hoveredWord = GetWordFromOffset(hoveredOffset); + + if (string.IsNullOrWhiteSpace(hoveredWord)) + return; + + _hoverCancellationTokenSource?.Cancel(); + _hoverCancellationTokenSource?.Dispose(); + + _hoverCancellationTokenSource = new CancellationTokenSource(); + CancellationToken cancellationToken = _hoverCancellationTokenSource.Token; + int hoverRequestToken = ++_hoverRequestToken; + + try + { + LuaHoverInfo hoverInfo = await RequestHoverAsync(hoveredOffset, cancellationToken).ConfigureAwait(true); + + if (hoverInfo is null || string.IsNullOrWhiteSpace(hoverInfo.Content)) + return; + + if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) + return; + + int currentHoveredOffset = GetOffsetFromPoint(Mouse.GetPosition(this)); + + if (currentHoveredOffset != hoveredOffset) + return; + + if (hoverInfo.IsMarkdown) + ShowMarkdownToolTip(hoverInfo.Content); + else + ShowToolTip(hoverInfo.Content); + } + catch + { + // Ignore hover failures and keep the editor responsive. + } + } + + private bool IsIntellisenseAvailable() + => IntellisenseProvider is not null && IntellisenseProvider.IsAvailable && !string.IsNullOrWhiteSpace(FilePath); + + private static bool ShouldTriggerAutocomplete(string inputText) + => inputText == "." || inputText == ":"; + + private static bool ShouldKeepCompletionWindowOpen(string inputText) + => inputText?.Length == 1 && (char.IsLetterOrDigit(inputText[0]) || inputText[0] == '_'); + + private void CloseCompletionWindow() + { + if (_completionWindow is null) + return; + + _completionWindow.Close(); + _completionWindow = null; + } + + private async Task RequestCompletionAsync(int offset) + { + try + { + if (!IsIntellisenseAvailable()) + return; + + (int line, int column) = GetPositionFromOffset(offset); + var items = await IntellisenseProvider + .GetCompletionItemsAsync(FilePath, Text, line, column, CancellationToken.None) + .ConfigureAwait(true); + + if (items is null || items.Count == 0) + { + CloseCompletionWindow(); + return; + } + + CloseCompletionWindow(); + + InitializeCompletionWindow(); + SetCompletionWindowOffsets(offset); + + foreach (LuaCompletionItem item in items) + _completionWindow.CompletionList.CompletionData.Add(new LuaCompletionData(item)); + + if (_completionWindow.CompletionList.CompletionData.Count > 0) + ShowCompletionWindow(); + } + catch + { + CloseCompletionWindow(); + // Ignore completion failures and keep the editor responsive. + } + } + + private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) + { + if (!IsIntellisenseAvailable()) + return null; + + (int line, int column) = GetPositionFromOffset(offset); + + return await IntellisenseProvider + .GetHoverAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); + } + + private async Task RequestSignatureHelpAsync(int offset) + { + if (!IsIntellisenseAvailable()) + { + DismissSignatureHelp(); + return; + } + + _signatureCancellationTokenSource?.Cancel(); + _signatureCancellationTokenSource?.Dispose(); + _signatureCancellationTokenSource = new CancellationTokenSource(); + + CancellationToken cancellationToken = _signatureCancellationTokenSource.Token; + + try + { + (int line, int column) = GetPositionFromOffset(offset); + LuaSignatureInfo signatureInfo = await IntellisenseProvider + .GetSignatureHelpAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested) + return; + + if (signatureInfo is null) + { + DismissSignatureHelp(); + return; + } + + ShowSignatureToolTip(signatureInfo); + } + catch + { + // Ignore signature help failures and keep the editor responsive. + } + } + + private void DismissTransientToolTips() + { + _hoverCancellationTokenSource?.Cancel(); + _hoverRequestToken++; + DismissSignatureHelp(); + CloseDefinitionToolTip(true); + } + + private void ScheduleSignatureHelpRefresh() + => Dispatcher.BeginInvoke(new Action(() => _ = RequestSignatureHelpAsync(CaretOffset))); + + private (int line, int column) GetPositionFromOffset(int offset) + { + int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + TextLocation location = Document.GetLocation(safeOffset); + + return (location.Line - 1, location.Column - 1); + } + + private void SetCompletionWindowOffsets(int offset) + { + int startOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + + while (startOffset > 0) + { + char currentChar = Document.GetCharAt(startOffset - 1); + + if (char.IsLetterOrDigit(currentChar) || currentChar == '_') + startOffset--; + else + break; + } + + _completionWindow.StartOffset = startOffset; + _completionWindow.EndOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs new file mode 100644 index 0000000000..3fa6aa17da --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Input; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua +{ + public sealed partial class LuaEditor + { + private async void TextEditor_KeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Escape && (_signaturePopup.IsOpen || _specialToolTip.IsOpen)) + { + DismissTransientToolTips(); + e.Handled = true; + return; + } + + if (_signaturePopup.IsOpen && (e.Key == Key.Back || e.Key == Key.Delete)) + ScheduleSignatureHelpRefresh(); + + if (e.Key == Key.F12) + { + Debug.WriteLine("[LuaLS] F12 pressed, attempting definition navigation."); + + if (await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true)) + e.Handled = true; + } + } + + private void TextEditor_PreviewMouseDown(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left || e.ChangedButton == MouseButton.Right) + DismissTransientToolTips(); + } + + private async void TextEditor_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + if (!Keyboard.Modifiers.HasFlag(ModifierKeys.Control) || e.ChangedButton != MouseButton.Left) + return; + + int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); + + if (hoveredOffset == -1) + return; + + Debug.WriteLine("[LuaLS] CTRL+Click detected, attempting definition navigation."); + + if (await TryNavigateToDefinitionAsync(hoveredOffset, CancellationToken.None).ConfigureAwait(true)) + e.Handled = true; + } + + private async Task TryNavigateToDefinitionAsync(int offset, CancellationToken cancellationToken) + { + if (!IsIntellisenseAvailable()) + { + Debug.WriteLine("[LuaLS] Definition aborted: intellisense not available."); + return false; + } + + if (DefinitionNavigationRequested is null) + { + Debug.WriteLine("[LuaLS] Definition aborted: DefinitionNavigationRequested callback not set."); + return false; + } + + try + { + foreach (int candidateOffset in GetDefinitionCandidateOffsets(offset)) + { + (int line, int column) = GetPositionFromOffset(candidateOffset); + + Debug.WriteLine($"[LuaLS] Requesting definition at offset {candidateOffset} -> ({line},{column})."); + + LuaDefinitionLocation definitionLocation = await IntellisenseProvider + .GetDefinitionAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); + + if (definitionLocation is null) + continue; + + Debug.WriteLine($"[LuaLS] Definition found: '{definitionLocation.FilePath}' L{definitionLocation.LineNumber}."); + DefinitionNavigationRequested(definitionLocation); + return true; + } + + Debug.WriteLine("[LuaLS] Definition not found for any candidate offset."); + return false; + } + catch (OperationCanceledException) + { + return false; + } + catch (Exception exception) + { + Debug.WriteLine($"[LuaLS] Definition navigation failed: {exception.Message}"); + return false; + } + } + + public async void NavigateToDefinitionAtCaretAsync() + => await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true); + + private IEnumerable GetDefinitionCandidateOffsets(int offset) + { + int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + var offsets = new List(); + + AddDefinitionCandidateOffset(offsets, safeOffset); + + if (safeOffset > 0) + AddDefinitionCandidateOffset(offsets, safeOffset - 1); + + if (TryGetDefinitionWordBounds(safeOffset, out int wordStart, out int wordEnd)) + { + AddDefinitionCandidateOffset(offsets, wordStart); + AddDefinitionCandidateOffset(offsets, wordEnd - 1); + } + + return offsets; + } + + private bool TryGetDefinitionWordBounds(int offset, out int wordStart, out int wordEnd) + { + wordStart = 0; + wordEnd = 0; + + if (Document.TextLength == 0) + return false; + + int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + int probeOffset = safeOffset; + + if (probeOffset >= Document.TextLength) + probeOffset = Document.TextLength - 1; + + if (probeOffset > 0 + && !IsDefinitionIdentifierCharacter(Document.GetCharAt(probeOffset)) + && IsDefinitionIdentifierCharacter(Document.GetCharAt(probeOffset - 1))) + { + probeOffset--; + } + + if (!IsDefinitionIdentifierCharacter(Document.GetCharAt(probeOffset))) + return false; + + wordStart = probeOffset; + wordEnd = probeOffset + 1; + + while (wordStart > 0 && IsDefinitionIdentifierCharacter(Document.GetCharAt(wordStart - 1))) + wordStart--; + + while (wordEnd < Document.TextLength && IsDefinitionIdentifierCharacter(Document.GetCharAt(wordEnd))) + wordEnd++; + + return wordEnd > wordStart; + } + + private static bool IsDefinitionIdentifierCharacter(char c) + => char.IsLetterOrDigit(c) || c == '_'; + + private static void AddDefinitionCandidateOffset(ICollection offsets, int offset) + { + if (!offsets.Contains(offset)) + offsets.Add(offset); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs new file mode 100644 index 0000000000..055484f9f9 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -0,0 +1,171 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Documents; +using System.Windows.Media; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua +{ + public sealed partial class LuaEditor + { + private static readonly SolidColorBrush SignatureParamDocForeground = CreateFrozenBrush(Color.FromRgb(180, 180, 180)); + private static readonly SolidColorBrush SignatureActiveParamForeground = CreateFrozenBrush(Color.FromRgb(86, 180, 235)); + private static readonly SolidColorBrush SignatureForeground = CreateFrozenBrush(Colors.Gainsboro); + + private readonly Popup _signaturePopup = new Popup(); + private readonly Border _signaturePopupBorder = new Border(); + private readonly ContentPresenter _signaturePopupPresenter = new ContentPresenter(); + + private void InitializeSignaturePopup() + { + _signaturePopup.AllowsTransparency = true; + _signaturePopup.PopupAnimation = PopupAnimation.None; + _signaturePopup.StaysOpen = true; + _signaturePopup.Placement = PlacementMode.RelativePoint; + + _signaturePopupBorder.SnapsToDevicePixels = true; + _signaturePopupBorder.CornerRadius = new CornerRadius(3.0); + _signaturePopupBorder.BorderThickness = new Thickness(1.0); + _signaturePopupBorder.Padding = new Thickness(8.0, 6.0, 8.0, 6.0); + _signaturePopupBorder.BorderBrush = DefaultToolTipBorder; + _signaturePopupBorder.Background = DefaultToolTipBackground; + _signaturePopupBorder.Child = _signaturePopupPresenter; + + _signaturePopup.Child = _signaturePopupBorder; + } + + private void DismissSignatureHelp() + { + _signatureCancellationTokenSource?.Cancel(); + + if (_signaturePopup.IsOpen) + _signaturePopup.IsOpen = false; + + _signaturePopupPresenter.Content = null; + } + + private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) + { + double availablePopupWidth = Math.Max(0.0, Math.Min(500.0, ActualWidth - 16.0)); + double popupHorizontalPadding = _signaturePopupBorder.Padding.Left + + _signaturePopupBorder.Padding.Right + + _signaturePopupBorder.BorderThickness.Left + + _signaturePopupBorder.BorderThickness.Right; + double popupVerticalPadding = _signaturePopupBorder.Padding.Top + + _signaturePopupBorder.Padding.Bottom + + _signaturePopupBorder.BorderThickness.Top + + _signaturePopupBorder.BorderThickness.Bottom; + double contentMaxWidth = Math.Max(0.0, availablePopupWidth - popupHorizontalPadding); + + var panel = new StackPanel { MaxWidth = contentMaxWidth }; + panel.Children.Add(BuildSignatureBlock(signatureInfo)); + + if (signatureInfo.ActiveParameter < signatureInfo.Parameters.Count) + { + LuaParameterInfo activeParam = signatureInfo.Parameters[signatureInfo.ActiveParameter]; + + if (!string.IsNullOrWhiteSpace(activeParam.Documentation)) + { + var parameterDocumentation = new TextBlock + { + Text = activeParam.Label + ": " + activeParam.Documentation, + Foreground = SignatureParamDocForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), + TextWrapping = TextWrapping.Wrap, + Margin = new Thickness(0.0, 4.0, 0.0, 0.0) + }; + + panel.Children.Add(parameterDocumentation); + } + } + + panel.Measure(new Size(contentMaxWidth, double.PositiveInfinity)); + Size popupSize = new Size( + Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), + panel.DesiredSize.Height + popupVerticalPadding); + + if (_signaturePopup.IsOpen) + _signaturePopup.IsOpen = false; + + _signaturePopupPresenter.Content = panel; + _signaturePopupPresenter.InvalidateMeasure(); + _signaturePopupBorder.InvalidateMeasure(); + AttachHostWindowHandlers(); + _signaturePopup.PlacementTarget = this; + TextArea.TextView.EnsureVisualLines(); + + Rect caretRectangle = TextArea.Caret.CalculateCaretRectangle(); + Vector scrollOffset = TextArea.TextView.ScrollOffset; + Point caretViewportPoint = new Point( + caretRectangle.X - scrollOffset.X, + caretRectangle.Y - scrollOffset.Y); + Point editorPoint = TextArea.TextView.TranslatePoint(caretViewportPoint, this); + double lineHeight = Math.Max(TextArea.TextView.DefaultLineHeight, caretRectangle.Height); + double lineSlack = Math.Max(0.0, lineHeight - caretRectangle.Height); + double horizontalOffset = Math.Max(0.0, editorPoint.X + 2.0f); + double maxHorizontalOffset = Math.Max(0.0, ActualWidth - popupSize.Width - 8.0f); + horizontalOffset = Math.Min(horizontalOffset, maxHorizontalOffset); + + double verticalOffset = editorPoint.Y - popupSize.Height - lineSlack - 8.0f; + + if (verticalOffset < 0.0) + verticalOffset = Math.Min(Math.Max(0.0, ActualHeight - popupSize.Height), editorPoint.Y + lineHeight + 4.0f); + + _signaturePopup.HorizontalOffset = horizontalOffset; + _signaturePopup.VerticalOffset = verticalOffset; + _signaturePopup.IsOpen = true; + } + + private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo) + { + var textBlock = new TextBlock + { + FontFamily = new FontFamily("Consolas"), + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), + TextWrapping = TextWrapping.Wrap, + Foreground = SignatureForeground + }; + + string label = signatureInfo.Label; + int paramStart = label.IndexOf('('); + + if (paramStart < 0 || signatureInfo.Parameters.Count == 0) + { + textBlock.Text = label; + return textBlock; + } + + textBlock.Inlines.Add(new Run(label[..(paramStart + 1)])); + + string paramSection = label[(paramStart + 1)..]; + int closingParen = paramSection.LastIndexOf(')'); + + if (closingParen >= 0) + paramSection = paramSection[..closingParen]; + + string[] parameterNames = paramSection.Split(','); + + for (int i = 0; i < parameterNames.Length; i++) + { + if (i > 0) + textBlock.Inlines.Add(new Run(", ")); + + var run = new Run(parameterNames[i].Trim()); + + if (i == signatureInfo.ActiveParameter) + { + run.FontWeight = FontWeights.Bold; + run.Foreground = SignatureActiveParamForeground; + } + + textBlock.Inlines.Add(run); + } + + textBlock.Inlines.Add(new Run(")")); + return textBlock; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index ea3831ec74..ea15cb1edc 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -5,16 +5,23 @@ using System.Windows.Media; using System.Xml; using TombLib.Scripting.Bases; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Services; namespace TombLib.Scripting.Lua { - public sealed class LuaEditor : TextEditorBase + public sealed partial class LuaEditor : TextEditorBase { public override string DefaultFileExtension => ".lua"; + public ILuaIntellisenseProvider IntellisenseProvider { get; set; } + public Action DefinitionNavigationRequested { get; set; } + public LuaEditor(Version engineVersion) : base(engineVersion) { CommentPrefix = "--"; + InitializeSignaturePopup(); + BindLuaIntellisenseEvents(); } public override void UpdateSettings(Bases.ConfigurationBase configuration) @@ -31,6 +38,14 @@ public override void UpdateSettings(Bases.ConfigurationBase configuration) Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("White")); base.UpdateSettings(configuration); + LiveErrorUnderlining = true; + } + + private static SolidColorBrush CreateFrozenBrush(Color color) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + return brush; } } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs new file mode 100644 index 0000000000..30861220eb --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -0,0 +1,25 @@ +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Editing; +using System; +using System.Windows.Media; + +namespace TombLib.Scripting.Lua.Objects +{ + public sealed class LuaCompletionData : ICompletionData + { + private readonly LuaCompletionItem _item; + + public LuaCompletionData(LuaCompletionItem item) + => _item = item ?? throw new ArgumentNullException(nameof(item)); + + public ImageSource Image => null; + public string Text => _item.Label; + public object Content => _item.Label; + public object Description => _item.Description; + public double Priority => 0; + + public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) + => textArea.Document.Replace(completionSegment, _item.InsertText); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs new file mode 100644 index 0000000000..08bf9bc2a7 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -0,0 +1,18 @@ +using System; + +namespace TombLib.Scripting.Lua.Objects +{ + public sealed class LuaCompletionItem + { + public LuaCompletionItem(string label, string insertText = null, string description = null) + { + Label = label ?? throw new ArgumentNullException(nameof(label)); + InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; + Description = description; + } + + public string Label { get; } + public string InsertText { get; } + public string Description { get; } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs new file mode 100644 index 0000000000..794dc2d36d --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs @@ -0,0 +1,18 @@ +using System; + +namespace TombLib.Scripting.Lua.Objects +{ + public sealed class LuaDefinitionLocation + { + public LuaDefinitionLocation(string filePath, int lineNumber, int columnNumber) + { + FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); + LineNumber = lineNumber; + ColumnNumber = columnNumber; + } + + public string FilePath { get; } + public int LineNumber { get; } + public int ColumnNumber { get; } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs new file mode 100644 index 0000000000..0ae97ad068 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs @@ -0,0 +1,16 @@ +using System; + +namespace TombLib.Scripting.Lua.Objects +{ + public sealed class LuaHoverInfo + { + public LuaHoverInfo(string content, bool isMarkdown) + { + Content = content ?? throw new ArgumentNullException(nameof(content)); + IsMarkdown = isMarkdown; + } + + public string Content { get; } + public bool IsMarkdown { get; } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs new file mode 100644 index 0000000000..0ce669955e --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; + +namespace TombLib.Scripting.Lua.Objects +{ + public sealed class LuaSignatureInfo + { + public LuaSignatureInfo(string label, string documentation, IReadOnlyList parameters, + int activeParameter) + { + Label = label ?? throw new ArgumentNullException(nameof(label)); + Documentation = documentation; + Parameters = parameters ?? Array.Empty(); + ActiveParameter = Math.Max(0, activeParameter); + } + + public string Label { get; } + public string Documentation { get; } + public IReadOnlyList Parameters { get; } + public int ActiveParameter { get; } + } + + public sealed class LuaParameterInfo + { + public LuaParameterInfo(string label, string documentation) + { + Label = label ?? string.Empty; + Documentation = documentation; + } + + public string Label { get; } + public string Documentation { get; } + } +} diff --git a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs new file mode 100644 index 0000000000..efe42780ed --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Objects; + +namespace TombLib.Scripting.Lua.Services +{ + public interface ILuaIntellisenseProvider : IDisposable + { + bool IsAvailable { get; } + event Action> DiagnosticsUpdated; + + IReadOnlyList GetDiagnostics(string filePath); + + void OpenDocument(string filePath, string content); + void UpdateDocument(string filePath, string content); + void CloseDocument(string filePath); + + Task> GetCompletionItemsAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); + + Task GetHoverAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); + + Task GetDefinitionAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); + + Task GetSignatureHelpAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index 61120144f3..0adc84feb0 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -24,10 +24,7 @@ x86 - - False - ..\..\Libs\ICSharpCode.AvalonEdit.dll - + diff --git a/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/GameflowHoverService.cs b/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/GameflowHoverService.cs index 15c28f9e3a..b669cea8d3 100644 --- a/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/GameflowHoverService.cs +++ b/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/GameflowHoverService.cs @@ -96,10 +96,10 @@ public GameflowHoverService(IGameflowSchemaService schemaService) private static string FormatPropertyInfo(string propertyName, JSchema propertySchema) { - var info = $"\"{propertyName}\""; + var info = $"`\"{propertyName}\"`"; if (propertySchema.Type.HasValue) - info += $"\nType: {propertySchema.Type.Value}"; + info += $"\nType: `{propertySchema.Type.Value}`"; if (!string.IsNullOrEmpty(propertySchema.Description)) info += $"\n\n{propertySchema.Description}"; diff --git a/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs b/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs index 5064136913..e2ff039545 100644 --- a/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs +++ b/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs @@ -118,20 +118,25 @@ private void TextEditor_TextChanged(object? sender, EventArgs e) private void TextView_MouseHover(object? sender, MouseEventArgs e) { int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); + + if (hoveredOffset == -1) + return; + + if (TryShowDiagnosticToolTip(hoveredOffset)) + return; + string? hoverInfo = _hoverService.GetHoverInfo(Document, hoveredOffset); if (!string.IsNullOrEmpty(hoverInfo)) - ShowToolTip(hoverInfo); + ShowMarkdownToolTip(hoverInfo); } private void ErrorWorker_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) { - if (e.Result is null) + if (e.Result is not IReadOnlyList diagnostics) return; - ResetAllErrors(); - ApplyErrorsToLines(e.Result as List); - TextArea.TextView.InvalidateLayer(KnownLayer.Caret); + SetDiagnostics(diagnostics); } #endregion Event handlers diff --git a/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj b/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj index 854819d119..2fc068c975 100644 --- a/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj +++ b/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj @@ -23,12 +23,7 @@ x86 - - False - ..\..\Libs\ICSharpCode.AvalonEdit.dll - - - + GlobalPaths.cs diff --git a/TombLib/TombLib.Scripting.Tomb1Main/Utils/ErrorDetector.cs b/TombLib/TombLib.Scripting.Tomb1Main/Utils/ErrorDetector.cs index 61f9187bba..5f9b1a39d6 100644 --- a/TombLib/TombLib.Scripting.Tomb1Main/Utils/ErrorDetector.cs +++ b/TombLib/TombLib.Scripting.Tomb1Main/Utils/ErrorDetector.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using TombLib.Scripting.Interfaces; +using TombLib.Scripting.Objects; using TombLib.Scripting.Tomb1Main.Parsers; using TombLib.Scripting.Tomb1Main.Resources; @@ -9,18 +10,18 @@ namespace TombLib.Scripting.Tomb1Main.Utils; public class ErrorDetector : IErrorDetector { - public object FindErrors(string editorContent, Version engineVersion) + public IReadOnlyList FindErrors(string editorContent, Version engineVersion) { // Anything before 4.8 should not have errors checked if (engineVersion < new Version(4, 8)) - return null; + return Array.Empty(); return DetectErrorLines(new TextDocument(editorContent), engineVersion); } - private static List DetectErrorLines(TextDocument document, Version engineVersion) + private static List DetectErrorLines(TextDocument document, Version engineVersion) { - var errorLines = new List(); + var errorLines = new List(); foreach (DocumentLine processedLine in document.Lines) { @@ -30,7 +31,7 @@ private static List DetectErrorLines(TextDocument document, Version e continue; processedLineText = LineParser.EscapeComments(processedLineText); - ErrorLine error = FindErrorsInLine(processedLine, processedLineText, engineVersion); + TextEditorDiagnostic error = FindErrorsInLine(processedLine, processedLineText, engineVersion); if (error != null) errorLines.Add(error); @@ -39,7 +40,7 @@ private static List DetectErrorLines(TextDocument document, Version e return errorLines; } - private static ErrorLine FindErrorsInLine(DocumentLine line, string lineText, Version engineVersion) + private static TextEditorDiagnostic FindErrorsInLine(DocumentLine line, string lineText, Version engineVersion) { // Check whether there are JSON keys which are marked as "Removed" foreach (RemovedKeyword keyword in Keywords.RemovedProperties) @@ -51,9 +52,9 @@ private static ErrorLine FindErrorsInLine(DocumentLine line, string lineText, Ve if (lineText.Contains(keyPattern)) { - return new ErrorLine($"This property has been removed from the script syntax and cannot be used in TR1X {keyword.RemovedVersion} or newer." - + (string.IsNullOrEmpty(keyword.Message) ? "" : "\n" + keyword.Message), - line.LineNumber, keyPattern); + return CreateDiagnostic(line, lineText, + $"This property has been removed from the script syntax and cannot be used in TR1X {keyword.RemovedVersion} or newer." + + (string.IsNullOrEmpty(keyword.Message) ? "" : "\n" + keyword.Message), keyPattern); } } @@ -66,12 +67,26 @@ private static ErrorLine FindErrorsInLine(DocumentLine line, string lineText, Ve if (lineText.Contains(keyPattern)) { - return new ErrorLine($"This constant has been removed from the script syntax and cannot be used in TR1X {keyword.RemovedVersion} or newer." - + (string.IsNullOrEmpty(keyword.Message) ? "" : "\n" + keyword.Message), - line.LineNumber, keyPattern); + return CreateDiagnostic(line, lineText, + $"This constant has been removed from the script syntax and cannot be used in TR1X {keyword.RemovedVersion} or newer." + + (string.IsNullOrEmpty(keyword.Message) ? "" : "\n" + keyword.Message), keyPattern); } } return null; } + + private static TextEditorDiagnostic CreateDiagnostic(DocumentLine line, string lineText, string message, string keyPattern) + { + int matchIndex = string.IsNullOrWhiteSpace(keyPattern) + ? -1 + : lineText.IndexOf(keyPattern, StringComparison.Ordinal); + + int startOffset = matchIndex >= 0 ? line.Offset + matchIndex : line.Offset; + int endOffset = matchIndex >= 0 + ? startOffset + keyPattern.Length + : Math.Max(line.Offset + 1, line.EndOffset); + + return new TextEditorDiagnostic(TextEditorDiagnosticSeverity.Error, message, startOffset, endOffset); + } } diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 21c13ccaee..6a2cd460b1 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -1,8 +1,4 @@ using DarkUI.Forms; -using ICSharpCode.AvalonEdit; -using ICSharpCode.AvalonEdit.CodeCompletion; -using ICSharpCode.AvalonEdit.Document; -using ICSharpCode.AvalonEdit.Rendering; using System; using System.Collections.Generic; using System.ComponentModel; @@ -11,10 +7,15 @@ using System.Text; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Rendering; using TombLib.Scripting.Enums; using TombLib.Scripting.Interfaces; using TombLib.Scripting.Objects; @@ -27,6 +28,22 @@ namespace TombLib.Scripting.Bases { public abstract class TextEditorBase : TextEditor, IEditorControl, ISupportsFindReplace { + private const double ToolTipMaxHeight = 420.0; + private const double ToolTipMaxWidth = 540.0; + private const double ToolTipTextMaxWidth = 500.0; + private static readonly double ToolTipTextFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); + protected static readonly SolidColorBrush DefaultToolTipBorder = CreateFrozenBrush(Color.FromRgb(96, 96, 96)); + protected static readonly SolidColorBrush DefaultToolTipBackground = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); + private static readonly SolidColorBrush ErrorToolTipBorder = CreateFrozenBrush(Color.FromRgb(128, 86, 86)); + private static readonly SolidColorBrush ErrorToolTipBackground = CreateFrozenBrush(Color.FromRgb(78, 44, 44)); + private static readonly SolidColorBrush WarningToolTipBorder = CreateFrozenBrush(Color.FromRgb(145, 122, 62)); + private static readonly SolidColorBrush WarningToolTipBackground = CreateFrozenBrush(Color.FromRgb(86, 69, 30)); + private static readonly SolidColorBrush InformationToolTipBorder = CreateFrozenBrush(Color.FromRgb(80, 118, 168)); + private static readonly SolidColorBrush InformationToolTipBackground = CreateFrozenBrush(Color.FromRgb(46, 68, 104)); + private static readonly SolidColorBrush HintToolTipBorder = CreateFrozenBrush(Color.FromRgb(108, 108, 108)); + private static readonly SolidColorBrush HintToolTipBackground = CreateFrozenBrush(Color.FromRgb(58, 58, 58)); + private static readonly SolidColorBrush ToolTipForeground = CreateFrozenBrush(Colors.Gainsboro); + public EditorType EditorType => EditorType.Text; public abstract string DefaultFileExtension { get; } @@ -105,16 +122,24 @@ public TimeSpan TextChangedDelayedInterval #region Fields - protected ToolTip _specialToolTip = new ToolTip(); + protected Popup _specialToolTip = new Popup(); protected CompletionWindow _completionWindow; private ContentChangedWorker _contentChangedWorker; private DispatcherTimer _textChangedDelayedTimer = new DispatcherTimer(); + private DispatcherTimer _toolTipCloseTimer = new DispatcherTimer(); + private bool _toolTipContentHovered; + private readonly Border _specialToolTipBorder = new Border(); + private readonly ContentPresenter _specialToolTipPresenter = new ContentPresenter(); + private readonly List _bookmarkAnchors = new List(); + private IReadOnlyList _diagnostics = Array.Empty(); private IBackgroundRenderer _bookmarkRenderer; private IBackgroundRenderer _errorRenderer; + internal IReadOnlyList Diagnostics => _diagnostics; + #endregion Fields #region Construction @@ -125,6 +150,7 @@ public TextEditorBase(Version engineVersion) InitializeBackgroundWorkers(); InitializeTimers(); + InitializeToolTip(); InitializeRenderers(); BindEventMethods(); @@ -159,6 +185,26 @@ private void InitializeTimers() { TextChangedDelayedInterval = new TimeSpan(0, 0, 0, 0, 300); _textChangedDelayedTimer.Tick += TextChangedDelayedTimer_Tick; + _toolTipCloseTimer.Interval = new TimeSpan(0, 0, 0, 0, 900); + _toolTipCloseTimer.Tick += ToolTipCloseTimer_Tick; + } + + private void InitializeToolTip() + { + _specialToolTip.AllowsTransparency = true; + _specialToolTip.PopupAnimation = PopupAnimation.Fade; + _specialToolTip.StaysOpen = true; + _specialToolTip.Placement = PlacementMode.RelativePoint; + + _specialToolTipBorder.SnapsToDevicePixels = true; + _specialToolTipBorder.CornerRadius = new CornerRadius(3.0); + _specialToolTipBorder.BorderThickness = new Thickness(1.0); + _specialToolTipBorder.Padding = new Thickness(8.0, 6.0, 8.0, 6.0); + _specialToolTipBorder.Child = _specialToolTipPresenter; + _specialToolTipBorder.MouseEnter += SpecialToolTip_MouseEnter; + _specialToolTipBorder.MouseLeave += SpecialToolTip_MouseLeave; + + _specialToolTip.Child = _specialToolTipBorder; } private void InitializeRenderers() @@ -217,7 +263,7 @@ private void ContentChangedWorker_RunWorkerCompleted(object sender, RunWorkerCom private void TextArea_TextEntering(object sender, TextCompositionEventArgs e) { - CloseDefinitionToolTip(); // Prevents the ToolTip from covering the screen while typing + CloseDefinitionToolTip(true); // Prevents the ToolTip from covering the screen while typing HandleAutoClosing(e); } @@ -238,10 +284,13 @@ private void TextChangedDelayedTimer_Tick(object sender, EventArgs e) } private void TextEditor_MouseHover(object sender, MouseEventArgs e) + => HandleMouseHover(e); + + protected virtual void HandleMouseHover(MouseEventArgs e) => HandleErrorToolTips(e); private void TextEditor_MouseHoverStopped(object sender, MouseEventArgs e) - => CloseDefinitionToolTip(); + => ScheduleDefinitionToolTipClose(); private void TextEditor_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { @@ -252,17 +301,54 @@ private void TextEditor_PreviewMouseWheel(object sender, MouseWheelEventArgs e) private void TextEditor_MouseRightButtonDown(object sender, MouseButtonEventArgs e) => MoveCaretToMousePosition(); - private void CloseDefinitionToolTip() + private void ToolTipCloseTimer_Tick(object sender, EventArgs e) + { + _toolTipCloseTimer.Stop(); + + if (!_toolTipContentHovered && !_specialToolTipBorder.IsMouseOver) + CloseDefinitionToolTip(true); + } + + private void SpecialToolTip_MouseEnter(object sender, MouseEventArgs e) { + _toolTipContentHovered = true; + _toolTipCloseTimer.Stop(); + } + + private void SpecialToolTip_MouseLeave(object sender, MouseEventArgs e) + { + _toolTipContentHovered = false; + ScheduleDefinitionToolTipClose(); + } + + protected void CloseDefinitionToolTip(bool force = false) + { + _toolTipCloseTimer.Stop(); + + if (!force && (_toolTipContentHovered || _specialToolTipBorder.IsMouseOver)) + return; + if (_specialToolTip.IsOpen) _specialToolTip.IsOpen = false; + + _specialToolTipPresenter.Content = null; + _toolTipContentHovered = false; + } + + private void ScheduleDefinitionToolTipClose() + { + if (!_specialToolTip.IsOpen) + return; + + _toolTipCloseTimer.Stop(); + _toolTipCloseTimer.Start(); } private void MoveCaretToMousePosition() { if (string.IsNullOrEmpty(SelectedText)) { - TextViewPosition? position = TextArea.TextView.GetPosition(Mouse.GetPosition(TextArea.TextView) + TextArea.TextView.ScrollOffset); + TextViewPosition? position = GetTextViewPosition(Mouse.GetPosition(this)); if (position != null) { @@ -302,7 +388,10 @@ public void Save() private void SaveBookmarks() { - IEnumerable bookmarkedLines = Document.Lines.Where(line => line.IsBookmarked); + if (string.IsNullOrWhiteSpace(FilePath)) + return; + + List bookmarkedLines = CollectBookmarkedLines(); var builder = new StringBuilder(); @@ -313,7 +402,7 @@ private void SaveBookmarks() { string bookmarkFileName = FilePath + ".bkmrk"; - if (bookmarkedLines.Count() > 0) + if (bookmarkedLines.Count > 0) File.WriteAllText(bookmarkFileName, builder.ToString()); else if (File.Exists(bookmarkFileName)) File.Delete(bookmarkFileName); @@ -326,6 +415,8 @@ private void SaveBookmarks() private void RestoreBookmarks() { + _bookmarkAnchors.Clear(); + string bookmarkFileName = FilePath + ".bkmrk"; if (!File.Exists(bookmarkFileName)) @@ -335,12 +426,12 @@ private void RestoreBookmarks() { foreach (string line in File.ReadAllLines(bookmarkFileName)) { - if (int.TryParse(line, out int lineNumber)) + if (int.TryParse(line, out int lineNumber) && lineNumber >= 1 && lineNumber <= Document.LineCount) { DocumentLine documentLine = Document.GetLineByNumber(lineNumber); - if (documentLine != null) - documentLine.IsBookmarked = true; + if (FindBookmarkAnchor(documentLine) is null) + AddBookmark(documentLine); } } } @@ -383,21 +474,27 @@ private void SetContent(string content) #region Error handling - public void ApplyErrorsToLines(List errorLines) + public void SetDiagnostics(IReadOnlyList diagnostics) { - foreach (ErrorLine line in errorLines) - { - if (line.LineNumber > Document.LineCount) - continue; + _diagnostics = diagnostics ?? Array.Empty(); + InvalidateDiagnosticLayer(); + } - Document.GetLineByNumber(line.LineNumber).Error = line; - } + public void ClearDiagnostics() + { + if (_diagnostics.Count == 0) + return; + + _diagnostics = Array.Empty(); + InvalidateDiagnosticLayer(); } - public void ResetAllErrors() + private void InvalidateDiagnosticLayer() { - foreach (DocumentLine line in Document.Lines) - line.ClearError(); + TextArea.TextView.InvalidateLayer(KnownLayer.Background); + TextArea.TextView.InvalidateLayer(KnownLayer.Selection); + TextArea.TextView.InvalidateLayer(KnownLayer.Caret); + TextArea.TextView.InvalidateVisual(); } private void HandleErrorToolTips(MouseEventArgs e) @@ -407,15 +504,42 @@ private void HandleErrorToolTips(MouseEventArgs e) if (hoveredOffset == -1) return; - DocumentLine hoveredLine = Document.GetLineByOffset(hoveredOffset); + TryShowDiagnosticToolTip(hoveredOffset); + } + + protected bool TryShowDiagnosticToolTip(int hoveredOffset) + { + if (!LiveErrorUnderlining || _diagnostics.Count == 0) + return false; + + List hoveredDiagnostics = GetDiagnosticsAtOffset(hoveredOffset); + + if (hoveredDiagnostics.Count == 0) + hoveredDiagnostics = GetDiagnosticsForLine(Document.GetLineByOffset(hoveredOffset)); - if (hoveredLine.HasError) - ShowToolTip("Error:\n" + hoveredLine.Error.Message, - new SolidColorBrush(Color.FromRgb(128, 96, 96)), - new SolidColorBrush(Color.FromRgb(96, 64, 64)), - new SolidColorBrush(Colors.Gainsboro)); + if (hoveredDiagnostics.Count == 0) + return false; + + TextEditorDiagnosticSeverity severity = hoveredDiagnostics + .OrderBy(diagnostic => diagnostic.Severity) + .Select(diagnostic => diagnostic.Severity) + .First(); + + string message = string.Join(Environment.NewLine + Environment.NewLine, + hoveredDiagnostics + .OrderBy(diagnostic => diagnostic.Severity) + .ThenBy(diagnostic => diagnostic.StartOffset) + .Select(FormatDiagnosticMessage) + .Distinct(StringComparer.Ordinal)); + + GetDiagnosticToolTipColors(severity, out SolidColorBrush border, out SolidColorBrush background); + ShowToolTip(message, border, background, ToolTipForeground); + return true; } + protected bool HasDiagnosticsOnLine(DocumentLine line) + => line is not null && GetDiagnosticsForLine(line).Count > 0; + #endregion Error handling #region Auto bracket closing @@ -507,8 +631,6 @@ public void CommentOutLines() if (!string.IsNullOrWhiteSpace(currentLineText)) builder.AppendLine(whitespaceBuilder.ToString() + CommentPrefix + currentLineText.TrimStart()); - else - builder.AppendLine(whitespaceBuilder.ToString()); totalLineLength += currentLine.TotalLength; } @@ -568,7 +690,13 @@ public void UncommentLines() public void ToggleBookmark() { DocumentLine currentLine = Document.GetLineByOffset(CaretOffset); - currentLine.IsBookmarked = !currentLine.IsBookmarked; + + TextAnchor bookmarkAnchor = FindBookmarkAnchor(currentLine); + + if (bookmarkAnchor is null) + AddBookmark(currentLine); + else + _bookmarkAnchors.Remove(bookmarkAnchor); TextArea.TextView.InvalidateLayer(KnownLayer.Background); @@ -578,61 +706,31 @@ public void ToggleBookmark() public void GoToNextBookmark() { DocumentLine currentLine = Document.GetLineByOffset(CaretOffset); + List bookmarkedLines = CollectBookmarkedLines(); - for (int i = 1; i < Document.LineCount; i++) - { - DocumentLine iLine = Document.GetLineByNumber(i); + if (bookmarkedLines.Count == 0) + return; - if (iLine.IsBookmarked && iLine.LineNumber > currentLine.LineNumber) - { - CaretOffset = iLine.EndOffset; - ScrollToLine(iLine.LineNumber); - break; - } + DocumentLine nextBookmark = bookmarkedLines.FirstOrDefault(line => line.LineNumber > currentLine.LineNumber) + ?? bookmarkedLines[0]; - if (i == Document.LineCount - 1) - for (int j = 1; j < Document.LineCount; j++) - { - DocumentLine jLine = Document.GetLineByNumber(j); - - if (jLine.IsBookmarked) - { - CaretOffset = jLine.EndOffset; - ScrollToLine(jLine.LineNumber); - break; - } - } - } + CaretOffset = nextBookmark.EndOffset; + ScrollToLine(nextBookmark.LineNumber); } public void GoToPrevBookmark() { DocumentLine currentLine = Document.GetLineByOffset(CaretOffset); + List bookmarkedLines = CollectBookmarkedLines(); - for (int i = Document.LineCount - 1; i > 0; i--) - { - if (i == 1) - for (int j = Document.LineCount - 1; j > 0; j--) - { - DocumentLine jLine = Document.GetLineByNumber(j); - - if (jLine.IsBookmarked) - { - CaretOffset = jLine.EndOffset; - ScrollToLine(jLine.LineNumber); - break; - } - } + if (bookmarkedLines.Count == 0) + return; - DocumentLine iLine = Document.GetLineByNumber(i); + DocumentLine previousBookmark = bookmarkedLines.LastOrDefault(line => line.LineNumber < currentLine.LineNumber) + ?? bookmarkedLines[bookmarkedLines.Count - 1]; - if (iLine.IsBookmarked && iLine.LineNumber < currentLine.LineNumber) - { - CaretOffset = iLine.EndOffset; - ScrollToLine(iLine.LineNumber); - break; - } - } + CaretOffset = previousBookmark.EndOffset; + ScrollToLine(previousBookmark.LineNumber); } #endregion Bookmarks @@ -710,9 +808,7 @@ public void ClearAllBookmarks(System.Windows.Forms.IWin32Window promptOwner) "Are you sure?", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question); if (result == System.Windows.Forms.DialogResult.Yes) - foreach (DocumentLine line in Document.Lines) - if (line.IsBookmarked) - line.IsBookmarked = false; + _bookmarkAnchors.Clear(); TextArea.TextView.InvalidateLayer(KnownLayer.Background); @@ -754,13 +850,13 @@ public void ReplaceContent(string newContent) public int GetOffsetFromPoint(Point point) { - TextViewPosition? position = GetPositionFromPoint(point); + TextViewPosition? position = GetTextViewPosition(point); if (position == null) return -1; DocumentLine pointLine = Document.GetLineByNumber(((TextViewPosition)position).Line); - int offset = pointLine.Offset + ((TextViewPosition)position).Column; + int offset = pointLine.Offset + Math.Min(pointLine.Length, Math.Max(0, ((TextViewPosition)position).Column - 1)); if (offset > Document.TextLength) return -1; @@ -768,6 +864,15 @@ public int GetOffsetFromPoint(Point point) return offset; } + private TextViewPosition? GetTextViewPosition(Point point) + { + if (TextArea?.TextView is null) + return null; + + Point textViewPoint = TranslatePoint(point, TextArea.TextView); + return TextArea.TextView.GetPosition(textViewPoint + TextArea.TextView.ScrollOffset); + } + public string GetWordFromOffset(int offset) { int wordStart = TextUtilities.GetNextCaretPosition(Document, offset, LogicalDirection.Backward, CaretPositioningMode.WordBorder); @@ -781,22 +886,220 @@ public string GetWordFromOffset(int offset) public void ShowToolTip(string content) => ShowToolTip(content, - new SolidColorBrush(Color.FromRgb(96, 96, 96)), - new SolidColorBrush(Color.FromRgb(64, 64, 64)), - new SolidColorBrush(Colors.Gainsboro)); + DefaultToolTipBorder, + DefaultToolTipBackground, + ToolTipForeground); + + public void ShowMarkdownToolTip(string content) + => ShowMarkdownToolTip(content, + DefaultToolTipBorder, + DefaultToolTipBackground, + ToolTipForeground); public void ShowToolTip(string content, SolidColorBrush border, SolidColorBrush background, SolidColorBrush foreground) - { - _specialToolTip.PlacementTarget = this; // Required for property inheritance + => ShowToolTip(CreatePlainToolTipContent(content, foreground), border, background); - _specialToolTip.BorderBrush = border; - _specialToolTip.Background = background; - _specialToolTip.Foreground = foreground; + public void ShowMarkdownToolTip(string content, SolidColorBrush border, SolidColorBrush background, SolidColorBrush foreground) + => ShowToolTip(CreateMarkdownToolTipContent(content, foreground, background), border, background); - _specialToolTip.Content = content; + protected void ShowToolTip(object content, SolidColorBrush border, SolidColorBrush background) + { + _toolTipCloseTimer.Stop(); + _toolTipContentHovered = false; + _specialToolTip.PlacementTarget = this; + Point mousePosition = Mouse.GetPosition(this); + _specialToolTip.HorizontalOffset = mousePosition.X + 14.0; + _specialToolTip.VerticalOffset = mousePosition.Y + 20.0; + + _specialToolTipBorder.BorderBrush = border; + _specialToolTipBorder.Background = background; + _specialToolTipPresenter.Content = content; _specialToolTip.IsOpen = true; } + private static bool IsSeverityPrefixed(string message) + => !string.IsNullOrWhiteSpace(message) + && (message.StartsWith("Error:", StringComparison.OrdinalIgnoreCase) + || message.StartsWith("Warning:", StringComparison.OrdinalIgnoreCase) + || message.StartsWith("Information:", StringComparison.OrdinalIgnoreCase) + || message.StartsWith("Hint:", StringComparison.OrdinalIgnoreCase) + || message.StartsWith("Diagnostic:", StringComparison.OrdinalIgnoreCase)); + + private static object CreatePlainToolTipContent(string content, Brush foreground) + => WrapToolTipContent(CreateToolTipTextBlock(content, foreground)); + + private static object CreateMarkdownToolTipContent(string content, Brush foreground, Brush background) + { + string normalizedContent = NormalizeToolTipLineEndings(content); + + if (string.IsNullOrWhiteSpace(normalizedContent)) + return CreatePlainToolTipContent(string.Empty, foreground); + + return MarkdownToolTipRenderer.CreateContent(normalizedContent, foreground, background); + } + + private static object WrapToolTipContent(UIElement content) + => new ScrollViewer + { + Content = content, + MaxHeight = ToolTipMaxHeight, + MaxWidth = ToolTipMaxWidth, + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, + CanContentScroll = true + }; + + private static TextBlock CreateToolTipTextBlock(string content, Brush foreground) + { + var textBlock = CreateBaseToolTipTextBlock(foreground); + textBlock.Text = content ?? string.Empty; + return textBlock; + } + + private static TextBlock CreateBaseToolTipTextBlock(Brush foreground) + => new TextBlock + { + Foreground = foreground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = ToolTipTextFontSize, + TextWrapping = TextWrapping.Wrap, + MaxWidth = ToolTipTextMaxWidth, + Margin = new Thickness(0.0, 0.0, 0.0, 6.0) + }; + + private static string NormalizeToolTipLineEndings(string text) + => (text ?? string.Empty) + .Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n'); + + private static SolidColorBrush CreateFrozenBrush(Color color) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + return brush; + } + + private List CollectBookmarkedLines() + { + var bookmarkedLines = new List(); + var invalidAnchors = new List(); + var seenLineNumbers = new HashSet(); + + foreach (TextAnchor anchor in _bookmarkAnchors) + { + DocumentLine line = GetBookmarkedLine(anchor); + + if (line is null) + { + invalidAnchors.Add(anchor); + continue; + } + + if (seenLineNumbers.Add(line.LineNumber)) + bookmarkedLines.Add(line); + } + + foreach (TextAnchor anchor in invalidAnchors) + _bookmarkAnchors.Remove(anchor); + + bookmarkedLines.Sort((left, right) => left.LineNumber.CompareTo(right.LineNumber)); + return bookmarkedLines; + } + + internal IReadOnlyList GetBookmarkedLines() + => CollectBookmarkedLines(); + + private void AddBookmark(DocumentLine line) + { + if (line is null) + return; + + var anchor = Document.CreateAnchor(line.Offset); + anchor.MovementType = AnchorMovementType.BeforeInsertion; + anchor.SurviveDeletion = true; + _bookmarkAnchors.Add(anchor); + } + + private TextAnchor FindBookmarkAnchor(DocumentLine line) + { + if (line is null) + return null; + + foreach (TextAnchor anchor in _bookmarkAnchors) + { + DocumentLine bookmarkedLine = GetBookmarkedLine(anchor); + + if (bookmarkedLine is not null && bookmarkedLine.LineNumber == line.LineNumber) + return anchor; + } + + return null; + } + + private DocumentLine GetBookmarkedLine(TextAnchor anchor) + { + if (anchor is null || anchor.IsDeleted || Document.LineCount == 0) + return null; + + int offset = Math.Max(0, Math.Min(anchor.Offset, Document.TextLength)); + return Document.GetLineByOffset(offset); + } + + private List GetDiagnosticsAtOffset(int offset) + => _diagnostics + .Where(diagnostic => diagnostic.ContainsOffset(offset)) + .ToList(); + + private List GetDiagnosticsForLine(DocumentLine line) + { + if (line is null || _diagnostics.Count == 0) + return new List(); + + int endOffset = Math.Max(line.EndOffset, line.Offset + 1); + + return _diagnostics + .Where(diagnostic => diagnostic.Intersects(line.Offset, endOffset)) + .ToList(); + } + + private static string FormatDiagnosticMessage(TextEditorDiagnostic diagnostic) + { + if (diagnostic is null) + return string.Empty; + + if (IsSeverityPrefixed(diagnostic.Message)) + return diagnostic.Message; + + return diagnostic.Severity.GetLabel() + ":\n" + diagnostic.Message; + } + + private static void GetDiagnosticToolTipColors(TextEditorDiagnosticSeverity severity, + out SolidColorBrush border, out SolidColorBrush background) + { + switch (severity) + { + case TextEditorDiagnosticSeverity.Warning: + border = WarningToolTipBorder; + background = WarningToolTipBackground; + break; + + case TextEditorDiagnosticSeverity.Information: + border = InformationToolTipBorder; + background = InformationToolTipBackground; + break; + + case TextEditorDiagnosticSeverity.Hint: + border = HintToolTipBorder; + background = HintToolTipBackground; + break; + + default: + border = ErrorToolTipBorder; + background = ErrorToolTipBackground; + break; + } + } + public virtual void UpdateSettings(ConfigurationBase configuration) { var config = configuration as TextEditorConfigBase; diff --git a/TombLib/TombLib.Scripting/Interfaces/IErrorDetector.cs b/TombLib/TombLib.Scripting/Interfaces/IErrorDetector.cs index 8ef77a6e20..205e221be8 100644 --- a/TombLib/TombLib.Scripting/Interfaces/IErrorDetector.cs +++ b/TombLib/TombLib.Scripting/Interfaces/IErrorDetector.cs @@ -1,9 +1,11 @@ using System; +using System.Collections.Generic; +using TombLib.Scripting.Objects; namespace TombLib.Scripting.Interfaces { public interface IErrorDetector { - object FindErrors(string editorContent, Version engineVersion); + IReadOnlyList FindErrors(string editorContent, Version engineVersion); } } diff --git a/TombLib/TombLib.Scripting/Objects/TextEditorDiagnostic.cs b/TombLib/TombLib.Scripting/Objects/TextEditorDiagnostic.cs new file mode 100644 index 0000000000..b1855a6ecb --- /dev/null +++ b/TombLib/TombLib.Scripting/Objects/TextEditorDiagnostic.cs @@ -0,0 +1,26 @@ +using System; + +namespace TombLib.Scripting.Objects +{ + public sealed class TextEditorDiagnostic + { + public TextEditorDiagnostic(TextEditorDiagnosticSeverity severity, string message, int startOffset, int endOffset) + { + Severity = severity; + Message = message ?? throw new ArgumentNullException(nameof(message)); + StartOffset = Math.Max(0, startOffset); + EndOffset = Math.Max(StartOffset + 1, endOffset); + } + + public TextEditorDiagnosticSeverity Severity { get; } + public string Message { get; } + public int StartOffset { get; } + public int EndOffset { get; } + + public bool ContainsOffset(int offset) + => offset >= StartOffset && offset < EndOffset; + + public bool Intersects(int startOffset, int endOffset) + => endOffset > startOffset && EndOffset > startOffset && StartOffset < endOffset; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Objects/TextEditorDiagnosticSeverity.cs b/TombLib/TombLib.Scripting/Objects/TextEditorDiagnosticSeverity.cs new file mode 100644 index 0000000000..653a6e06aa --- /dev/null +++ b/TombLib/TombLib.Scripting/Objects/TextEditorDiagnosticSeverity.cs @@ -0,0 +1,23 @@ +namespace TombLib.Scripting.Objects +{ + public enum TextEditorDiagnosticSeverity + { + Error = 1, + Warning = 2, + Information = 3, + Hint = 4 + } + + public static class TextEditorDiagnosticSeverityExtensions + { + public static string GetLabel(this TextEditorDiagnosticSeverity severity) + => severity switch + { + TextEditorDiagnosticSeverity.Error => "Error", + TextEditorDiagnosticSeverity.Warning => "Warning", + TextEditorDiagnosticSeverity.Information => "Information", + TextEditorDiagnosticSeverity.Hint => "Hint", + _ => "Diagnostic" + }; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs b/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs index fdf78ad5d1..a910b3764e 100644 --- a/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs @@ -23,16 +23,16 @@ public BookmarkRenderer(TextEditorBase e) public void Draw(TextView textView, DrawingContext drawingContext) { - foreach (DocumentLine line in _editor.Document.Lines) - if (line.IsBookmarked) - { - var segment = new TextSegment { StartOffset = line.Offset, EndOffset = line.EndOffset }; - var background = new SolidColorBrush(Color.FromArgb(40, 128, 128, 255)); // Light blue - var border = new Pen(Brushes.Transparent, 0); - - foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment, true)) - drawingContext.DrawRectangle(background, border, new Rect(rect.Location, new Size(textView.ActualWidth, rect.Height))); - } + var background = new SolidColorBrush(Color.FromArgb(40, 128, 128, 255)); + var border = new Pen(Brushes.Transparent, 0); + + foreach (DocumentLine line in _editor.GetBookmarkedLines()) + { + var segment = new TextSegment { StartOffset = line.Offset, EndOffset = line.EndOffset }; + + foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment, true)) + drawingContext.DrawRectangle(background, border, new Rect(rect.Location, new Size(textView.ActualWidth, rect.Height))); + } } #endregion Drawing diff --git a/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs b/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs index e10f32566c..48192defe4 100644 --- a/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs @@ -1,13 +1,23 @@ using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; +using System; using System.Windows; using System.Windows.Media; using TombLib.Scripting.Bases; +using TombLib.Scripting.Objects; namespace TombLib.Scripting.Rendering { public sealed class ErrorRenderer : IBackgroundRenderer { + private static readonly Brush ErrorBrush = CreateBrush(Color.FromArgb(224, 220, 76, 60)); + private static readonly Brush WarningBrush = CreateBrush(Color.FromArgb(224, 226, 165, 44)); + private static readonly Brush InformationBrush = CreateBrush(Color.FromArgb(224, 88, 170, 255)); + private static readonly Brush HintBrush = CreateBrush(Color.FromArgb(192, 166, 166, 166)); + private static readonly Pen WarningPen = CreatePen(WarningBrush, new double[] { 1.0, 2.0 }); + private static readonly Pen InformationPen = CreatePen(InformationBrush, new double[] { 2.0, 2.0 }); + private static readonly Pen HintPen = CreatePen(HintBrush, new double[] { 1.0, 3.0 }); + private TextEditorBase _editor; #region Construction @@ -23,35 +33,116 @@ public ErrorRenderer(TextEditorBase e) public void Draw(TextView textView, DrawingContext drawingContext) { - foreach (DocumentLine line in _editor.Document.Lines) + if (!_editor.LiveErrorUnderlining || _editor.Diagnostics.Count == 0) + return; + + foreach (TextEditorDiagnostic diagnostic in _editor.Diagnostics) { - if (!line.HasError) + if (!TryCreateSegment(textView.Document, diagnostic, out TextSegment segment)) continue; - string lineText = _editor.Document.GetText(line.Offset, line.Length); + foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment, false)) + { + if (rect.Width <= 0.0) + continue; - int matchIndex = lineText.IndexOf(line.Error.ErrorSegmentText); + switch (diagnostic.Severity) + { + case TextEditorDiagnosticSeverity.Warning: + DrawStraightUnderline(drawingContext, rect, WarningPen); + break; - if (matchIndex == -1) - continue; + case TextEditorDiagnosticSeverity.Information: + DrawStraightUnderline(drawingContext, rect, InformationPen); + break; - var segment = new TextSegment - { - StartOffset = line.Offset + matchIndex, - Length = line.Error.ErrorSegmentText.Length - }; + case TextEditorDiagnosticSeverity.Hint: + DrawStraightUnderline(drawingContext, rect, HintPen); + break; - foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment)) - { - ImageSource underlining = TextRendering.CreateZigZagUnderlining((int)rect.Width, System.Drawing.Color.FromArgb(192, 255, 0, 0)); + default: + DrawErrorUnderline(drawingContext, rect); + break; + } + } + } + } - if (underlining == null) - continue; + private static bool TryCreateSegment(TextDocument document, TextEditorDiagnostic diagnostic, out TextSegment segment) + { + segment = null; + + if (document is null || diagnostic is null || document.TextLength == 0) + return false; + + int startOffset = Math.Max(0, Math.Min(diagnostic.StartOffset, document.TextLength - 1)); + int endOffset = Math.Max(startOffset + 1, Math.Min(diagnostic.EndOffset, document.TextLength)); + + if (endOffset <= startOffset) + return false; + + segment = new TextSegment + { + StartOffset = startOffset, + EndOffset = endOffset + }; + + return true; + } - drawingContext.DrawImage(underlining, - new Rect(new Point(rect.Location.X, rect.Location.Y + rect.Height - 2), new Size(rect.Width, 4))); + private static void DrawErrorUnderline(DrawingContext drawingContext, Rect rect) + { + double baseline = rect.Bottom - 1.0; + double amplitude = 1.6; + double step = 4.0; + + var geometry = new StreamGeometry(); + + using (StreamGeometryContext context = geometry.Open()) + { + bool goingUp = true; + context.BeginFigure(new Point(rect.Left, baseline), false, false); + + for (double x = rect.Left; x < rect.Right; x += step) + { + double nextX = Math.Min(x + step / 2.0, rect.Right); + double y = baseline + (goingUp ? -amplitude : amplitude); + context.LineTo(new Point(nextX, y), true, false); + goingUp = !goingUp; + + nextX = Math.Min(x + step, rect.Right); + context.LineTo(new Point(nextX, baseline), true, false); } } + + geometry.Freeze(); + drawingContext.DrawGeometry(null, new Pen(ErrorBrush, 1.4), geometry); + } + + private static void DrawStraightUnderline(DrawingContext drawingContext, Rect rect, Pen pen) + { + double y = rect.Bottom - 1.0; + drawingContext.DrawLine(pen, new Point(rect.Left, y), new Point(rect.Right, y)); + } + + private static Brush CreateBrush(Color color) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + return brush; + } + + private static Pen CreatePen(Brush brush, double[] dashPattern) + { + var pen = new Pen(brush, 1.5) + { + DashStyle = new DashStyle(dashPattern, 0.0), + StartLineCap = PenLineCap.Round, + EndLineCap = PenLineCap.Round + }; + + pen.Freeze(); + return pen; } #endregion Drawing diff --git a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs new file mode 100644 index 0000000000..b8813afe1c --- /dev/null +++ b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs @@ -0,0 +1,479 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Text.RegularExpressions; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; +using System.Xml; +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.AvalonEdit.Highlighting.Xshd; +using MdXaml; +using TombLib.Scripting.Resources; + +namespace TombLib.Scripting.Rendering +{ + public static class MarkdownToolTipRenderer + { + private const int MaxVisibleCodeBlockLines = 14; + private const double ToolTipMaxHeight = 420.0; + private const double ToolTipMaxWidth = 540.0; + private const double ToolTipTextMaxWidth = 500.0; + private static readonly Regex FencedCodeBlockPattern = new Regex( + @"(?ms)(^|\n)(?`{3,}|~{3,})[ \t]*(?[^\n]*)\n(?.*?)(?:\n)\k[ \t]*(?=\n|$)", + RegexOptions.Compiled); + private static readonly FontFamily BodyFontFamily = SystemFonts.MessageFontFamily; + private static readonly FontFamily CodeFontFamily = new FontFamily(TextEditorBaseDefaults.FontFamily); + private static readonly double BodyFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); + private static readonly double CodeFontSize = Math.Max(BodyFontSize - 1.0, 13.0); + private static readonly Brush DefaultForeground = CreateFrozenBrush(Colors.Gainsboro); + private static readonly Brush DefaultBackground = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); + private static readonly Lazy LuaHighlighting = new Lazy(LoadLuaHighlighting); + + public static FrameworkElement CreateContent(string content, Brush foreground, Brush background) + { + string normalizedContent = NormalizeLineEndings(content); + string originalContent = normalizedContent; + + if (string.IsNullOrWhiteSpace(normalizedContent)) + return CreateFallbackContent(string.Empty, foreground); + + try + { + List fencedCodeBlocks = ExtractFencedCodeBlocks(ref normalizedContent); + + var markdown = new Markdown + { + DisabledContextMenu = true + }; + + FlowDocument document = markdown.Transform(normalizedContent); + ApplyDocumentTheme(document, foreground); + ReplaceCodeBlocks(document, fencedCodeBlocks, foreground, background); + ApplyInlineCodeTheme(document, foreground, background); + + return new FlowDocumentScrollViewer + { + Document = document, + Background = Brushes.Transparent, + BorderThickness = new Thickness(0.0), + Padding = new Thickness(0.0), + Margin = new Thickness(0.0), + IsToolBarVisible = false, + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, + HorizontalAlignment = HorizontalAlignment.Left, + Focusable = false, + MaxHeight = ToolTipMaxHeight, + MaxWidth = ToolTipMaxWidth + }; + } + catch (Exception exception) + { + Debug.WriteLine($"[MarkdownToolTipRenderer] Failed to render markdown tooltip: {exception}"); + return CreateFallbackContent(originalContent, foreground); + } + } + + private static void ApplyDocumentTheme(FlowDocument document, Brush foreground) + { + document.FontFamily = BodyFontFamily; + document.FontSize = BodyFontSize; + document.Foreground = foreground ?? DefaultForeground; + document.Background = Brushes.Transparent; + document.PagePadding = new Thickness(0.0); + document.ColumnWidth = ToolTipTextMaxWidth; + } + + private static void ApplyInlineCodeTheme(FlowDocument document, Brush foreground, Brush background) + { + Brush codeBackground = CreateCodeBackground(background); + var codeSpanElements = new List(); + + foreach (TextElement element in EnumerateTextElements(document)) + { + if (!string.Equals(element.Tag as string, "CodeSpan", StringComparison.Ordinal)) + continue; + + codeSpanElements.Add(element); + } + + foreach (TextElement element in codeSpanElements) + { + + string inlineText = NormalizeLineEndings(new TextRange(element.ContentStart, element.ContentEnd).Text).TrimEnd('\n'); + + if (element is Span span) + { + span.Inlines.Clear(); + span.Inlines.Add(new Run(" " + inlineText + " ")); + } + else if (element is Run run) + { + run.Text = " " + inlineText + " "; + } + + element.SetValue(TextElement.FontFamilyProperty, CodeFontFamily); + element.SetValue(TextElement.ForegroundProperty, foreground ?? DefaultForeground); + element.SetValue(TextElement.BackgroundProperty, codeBackground); + } + } + + private static List ExtractFencedCodeBlocks(ref string content) + { + var codeBlocks = new List(); + int index = 0; + + content = FencedCodeBlockPattern.Replace(content, match => + { + string placeholder = $"__TOMBIDE_MD_CODE_BLOCK_{index++}__"; + codeBlocks.Add(new CodeBlockInfo(placeholder, match.Groups["lang"].Value.Trim(), match.Groups["code"].Value)); + return match.Groups[1].Value + placeholder; + }); + + return codeBlocks; + } + + private static void ReplaceCodeBlocks(FlowDocument document, IReadOnlyList fencedCodeBlocks, Brush foreground, Brush background) + { + var codeBlockLookup = new Dictionary(StringComparer.Ordinal); + + foreach (CodeBlockInfo codeBlock in fencedCodeBlocks) + codeBlockLookup[codeBlock.Placeholder] = codeBlock; + + ReplaceCodeBlocks(document.Blocks, codeBlockLookup, foreground, background); + } + + private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background) + { + Block currentBlock = blocks.FirstBlock; + + while (currentBlock is not null) + { + Block nextBlock = currentBlock.NextBlock; + + if (TryCreateReplacementBlock(currentBlock, fencedCodeBlocks, foreground, background, out Block replacementBlock)) + { + blocks.InsertBefore(currentBlock, replacementBlock); + blocks.Remove(currentBlock); + } + else + { + switch (currentBlock) + { + case Section section: + ReplaceCodeBlocks(section.Blocks, fencedCodeBlocks, foreground, background); + break; + + case List list: + foreach (ListItem item in list.ListItems) + ReplaceCodeBlocks(item.Blocks, fencedCodeBlocks, foreground, background); + break; + + case Table table: + foreach (TableRowGroup rowGroup in table.RowGroups) + foreach (TableRow row in rowGroup.Rows) + foreach (TableCell cell in row.Cells) + ReplaceCodeBlocks(cell.Blocks, fencedCodeBlocks, foreground, background); + break; + } + } + + currentBlock = nextBlock; + } + } + + private static bool TryCreateReplacementBlock(Block block, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background, out Block replacementBlock) + { + replacementBlock = null; + + if (block is not Paragraph paragraph) + return false; + + string rawText = NormalizeLineEndings(new TextRange(paragraph.ContentStart, paragraph.ContentEnd).Text); + string normalizedText = rawText.Trim(); + + if (fencedCodeBlocks.TryGetValue(normalizedText, out CodeBlockInfo fencedCodeBlock)) + { + replacementBlock = new BlockUIContainer(CreateCodeBlockElement(fencedCodeBlock.Language, fencedCodeBlock.Code, foreground, background)); + return true; + } + + if (!string.Equals(paragraph.Tag as string, "CodeBlock", StringComparison.Ordinal)) + return false; + + replacementBlock = new BlockUIContainer(CreateCodeBlockElement(null, rawText.TrimEnd('\n'), foreground, background)); + return true; + } + + private static FrameworkElement CreateCodeBlockElement(string language, string code, Brush foreground, Brush background) + { + string normalizedCode = NormalizeCodeBlockText(code); + + var editor = new TextEditor + { + Text = normalizedCode, + IsReadOnly = true, + Background = Brushes.Transparent, + Foreground = foreground ?? DefaultForeground, + BorderThickness = new Thickness(0.0), + Margin = new Thickness(0.0), + Padding = new Thickness(0.0), + HorizontalAlignment = HorizontalAlignment.Stretch, + HorizontalScrollBarVisibility = ScrollBarVisibility.Auto, + FontFamily = CodeFontFamily, + FontSize = CodeFontSize, + ShowLineNumbers = false, + WordWrap = false + }; + + editor.Options.AllowScrollBelowDocument = false; + editor.Options.EnableHyperlinks = false; + editor.Options.EnableEmailHyperlinks = false; + editor.Options.HighlightCurrentLine = false; + editor.Options.ShowBoxForControlCharacters = false; + editor.TextArea.Margin = new Thickness(0.0); + editor.SyntaxHighlighting = ResolveHighlighting(language); + + int lineCount = Math.Max(1, editor.Document.LineCount); + double lineHeight = GetEditorLineHeight(editor); + double visibleLineCount = Math.Min(lineCount, MaxVisibleCodeBlockLines); + + editor.Height = Math.Max(lineHeight + 4.0, Math.Ceiling(visibleLineCount * lineHeight) + 2.0); + editor.VerticalScrollBarVisibility = lineCount > MaxVisibleCodeBlockLines + ? ScrollBarVisibility.Auto + : ScrollBarVisibility.Hidden; + + return new Border + { + Background = CreateCodeBackground(background), + BorderBrush = CreateCodeBorder(background), + BorderThickness = new Thickness(1.0), + CornerRadius = new CornerRadius(3.0), + Padding = new Thickness(8.0, 6.0, 8.0, 6.0), + Margin = new Thickness(0.0, 4.0, 0.0, 6.0), + Child = editor + }; + } + + private static double GetEditorLineHeight(TextEditor editor) + { + double lineHeight = editor.TextArea.TextView.DefaultLineHeight; + + if (!double.IsNaN(lineHeight) && lineHeight > 0.0) + return Math.Ceiling(lineHeight); + + var typeface = new Typeface(editor.FontFamily, editor.FontStyle, editor.FontWeight, editor.FontStretch); + var formattedText = new FormattedText( + "Ag", + CultureInfo.CurrentCulture, + FlowDirection.LeftToRight, + typeface, + editor.FontSize, + Brushes.Transparent, + 1.0); + + return Math.Ceiling(Math.Max(1.0, formattedText.Height)); + } + + private static string NormalizeCodeBlockText(string code) + { + string normalizedCode = NormalizeLineEndings(code); + + if (string.IsNullOrEmpty(normalizedCode)) + return string.Empty; + + string[] lines = normalizedCode.Split('\n'); + int lastContentLineIndex = lines.Length - 1; + + while (lastContentLineIndex >= 0 && string.IsNullOrWhiteSpace(lines[lastContentLineIndex])) + lastContentLineIndex--; + + if (lastContentLineIndex < 0) + return string.Empty; + + return string.Join(Environment.NewLine, lines, 0, lastContentLineIndex + 1); + } + + private static IEnumerable EnumerateTextElements(FlowDocument document) + { + foreach (Block block in document.Blocks) + foreach (TextElement element in EnumerateBlock(block)) + yield return element; + } + + private static IEnumerable EnumerateBlock(Block block) + { + yield return block; + + switch (block) + { + case Paragraph paragraph: + foreach (Inline inline in paragraph.Inlines) + foreach (TextElement element in EnumerateInline(inline)) + yield return element; + break; + + case Section section: + foreach (Block childBlock in section.Blocks) + foreach (TextElement element in EnumerateBlock(childBlock)) + yield return element; + break; + + case List list: + foreach (ListItem item in list.ListItems) + { + yield return item; + foreach (Block childBlock in item.Blocks) + foreach (TextElement element in EnumerateBlock(childBlock)) + yield return element; + } + break; + + case Table table: + foreach (TableRowGroup rowGroup in table.RowGroups) + { + yield return rowGroup; + foreach (TableRow row in rowGroup.Rows) + { + yield return row; + foreach (TableCell cell in row.Cells) + { + yield return cell; + foreach (Block childBlock in cell.Blocks) + foreach (TextElement element in EnumerateBlock(childBlock)) + yield return element; + } + } + } + break; + } + } + + private static IEnumerable EnumerateInline(Inline inline) + { + yield return inline; + + if (inline is Span span) + foreach (Inline childInline in span.Inlines) + foreach (TextElement element in EnumerateInline(childInline)) + yield return element; + } + + private static FrameworkElement CreateFallbackContent(string content, Brush foreground) + => new TextBlock + { + Foreground = foreground ?? DefaultForeground, + Text = content ?? string.Empty, + TextWrapping = TextWrapping.Wrap, + FontFamily = BodyFontFamily, + FontSize = BodyFontSize, + MaxWidth = ToolTipTextMaxWidth + }; + + private static string NormalizeLineEndings(string text) + => (text ?? string.Empty) + .Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n'); + + private static IHighlightingDefinition ResolveHighlighting(string language) + { + if (string.IsNullOrWhiteSpace(language)) + return null; + + string normalizedLanguage = language.Trim().ToLowerInvariant(); + + if (normalizedLanguage == "lua") + return LuaHighlighting.Value; + + IHighlightingDefinition definition = HighlightingManager.Instance.GetDefinition(normalizedLanguage); + + if (definition is not null) + return definition; + + definition = HighlightingManager.Instance.GetDefinitionByExtension(normalizedLanguage.StartsWith(".", StringComparison.Ordinal) + ? normalizedLanguage + : "." + normalizedLanguage); + + if (definition is not null) + return definition; + + return normalizedLanguage switch + { + "cs" => HighlightingManager.Instance.GetDefinitionByExtension(".cs"), + "csharp" => HighlightingManager.Instance.GetDefinitionByExtension(".cs"), + "js" => HighlightingManager.Instance.GetDefinitionByExtension(".js"), + "ts" => HighlightingManager.Instance.GetDefinitionByExtension(".ts"), + "json5" => HighlightingManager.Instance.GetDefinitionByExtension(".json"), + _ => null + }; + } + + private static IHighlightingDefinition LoadLuaHighlighting() + { + string xmlFilePath = Path.Combine(AppContext.BaseDirectory, "Configs", "TextEditors", "ColorSchemes", "Lua", "Default.xml"); + + if (!File.Exists(xmlFilePath)) + return null; + + using var stream = new FileStream(xmlFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using var reader = new XmlTextReader(stream); + return HighlightingLoader.Load(reader, HighlightingManager.Instance); + } + + private static Brush CreateCodeBackground(Brush background) + { + Color baseColor = background is SolidColorBrush solidBrush + ? solidBrush.Color + : ((SolidColorBrush)DefaultBackground).Color; + + return CreateFrozenBrush(Blend(baseColor, Colors.Black, 0.32)); + } + + private static Brush CreateCodeBorder(Brush background) + { + Color baseColor = background is SolidColorBrush solidBrush + ? solidBrush.Color + : ((SolidColorBrush)DefaultBackground).Color; + + return CreateFrozenBrush(Blend(baseColor, Colors.White, 0.18)); + } + + private static Color Blend(Color first, Color second, double ratio) + { + double clampedRatio = Math.Max(0.0, Math.Min(1.0, ratio)); + double inverseRatio = 1.0 - clampedRatio; + + return Color.FromArgb( + (byte)Math.Round(first.A * inverseRatio + second.A * clampedRatio), + (byte)Math.Round(first.R * inverseRatio + second.R * clampedRatio), + (byte)Math.Round(first.G * inverseRatio + second.G * clampedRatio), + (byte)Math.Round(first.B * inverseRatio + second.B * clampedRatio)); + } + + private static SolidColorBrush CreateFrozenBrush(Color color) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + return brush; + } + + private sealed class CodeBlockInfo + { + public CodeBlockInfo(string placeholder, string language, string code) + { + Placeholder = placeholder; + Language = language; + Code = code; + } + + public string Placeholder { get; } + public string Language { get; } + public string Code { get; } + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Rendering/TextRendering.cs b/TombLib/TombLib.Scripting/Rendering/TextRendering.cs deleted file mode 100644 index 2c085f10e2..0000000000 --- a/TombLib/TombLib.Scripting/Rendering/TextRendering.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Windows; -using System.Windows.Interop; -using System.Windows.Media.Imaging; - -namespace TombLib.Scripting.Rendering -{ - public static class TextRendering - { - public static System.Windows.Media.ImageSource CreateZigZagUnderlining(int textWidth, Color color) - { - if (textWidth < 3) - return null; - - List zigZagPoints = GenerateZigZagPatternPoints(textWidth); - - var bitmap = new Bitmap(textWidth, 4); - DrawPatternLines(bitmap, zigZagPoints, color); - - IntPtr handle = bitmap.GetHbitmap(); - - try { return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } - finally { NativeMethods.DeleteObject(handle); } - } - - private static List GenerateZigZagPatternPoints(int textWidth) - { - var zigZagPoints = new List(); - - bool toggle = false; - - for (int i = 0; i <= textWidth; i += 3) - { - float x = i; - float y = toggle ? 0 : 3; - - zigZagPoints.Add(new PointF(x, y)); - toggle = !toggle; - } - - return zigZagPoints; - } - - private static void DrawPatternLines(Bitmap bitmap, List points, Color color) - { - using (var graphics = System.Drawing.Graphics.FromImage(bitmap)) - { - graphics.SmoothingMode = SmoothingMode.HighSpeed; - graphics.DrawLines(new Pen(color, 2), points.ToArray()); - } - } - } -} diff --git a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj index 50f9d1c001..645c5d4252 100644 --- a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj +++ b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj @@ -24,10 +24,8 @@ x86 - - False - ..\..\Libs\ICSharpCode.AvalonEdit.dll - + + diff --git a/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs b/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs index 3e7bfc3944..bebc8be6db 100644 --- a/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs +++ b/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs @@ -1,8 +1,8 @@ using System; -using System.Collections.Generic; using System.ComponentModel; using System.Windows.Threading; using TombLib.Scripting.Interfaces; +using TombLib.Scripting.Objects; namespace TombLib.Scripting.Workers { @@ -53,10 +53,14 @@ protected override void OnDoWork(DoWorkEventArgs e) { base.OnDoWork(e); - var errorDetector = (e.Argument as List)[0] as IErrorDetector; - string editorContent = (e.Argument as List)[1].ToString(); + if (ErrorDetector is null) + { + e.Result = Array.Empty(); + return; + } - e.Result = errorDetector.FindErrors(editorContent, EngineVersion); + string editorContent = e.Argument as string ?? string.Empty; + e.Result = ErrorDetector.FindErrors(editorContent, EngineVersion); } #endregion Override methods @@ -77,13 +81,7 @@ public void CheckForErrorsAsync(string editorContent) if (ErrorDetector == null) return; - var args = new List - { - ErrorDetector, - editorContent - }; - - base.RunWorkerAsync(args); + base.RunWorkerAsync(editorContent ?? string.Empty); } #endregion Public methods diff --git a/TombLib/TombLib.Test/TombLib.Test.csproj b/TombLib/TombLib.Test/TombLib.Test.csproj index 1e714767f0..f96c3a483c 100644 --- a/TombLib/TombLib.Test/TombLib.Test.csproj +++ b/TombLib/TombLib.Test/TombLib.Test.csproj @@ -23,10 +23,7 @@ - - False - ..\..\Libs\ICSharpCode.AvalonEdit.dll - + From 2a4128111d3617b4d97feeae95cdb0e86d876680 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sat, 11 Apr 2026 19:34:57 +0100 Subject: [PATCH 02/34] Progress report --- ExternalResources.md | 1 + .../LuaStudio.Intellisense.cs | 22 + .../LuaIntellisenseDocumentManager.cs | 30 + .../LuaLanguageServerClient.cs | 72 +- .../LuaLanguageServerIntellisenseProvider.cs | 71 +- .../LuaLanguageServerResponseParser.cs | 202 +++- .../LuaLanguageServerSemanticTokensParser.cs | 89 ++ .../LuaLanguageServerSettingsFactory.cs | 7 + .../TombLib.Forms/Forms/FormAbout.designer.cs | 44 +- .../TextEditors/ColorSchemes/Lua/Default.xml | 192 ++-- .../Grammars/Lua/lua.tmLanguage.json | 978 ++++++++++++++++++ .../LuaSemanticTokensColorizer.cs | 188 ++++ .../LuaEditor.Intellisense.cs | 238 ++++- .../LuaEditor.SemanticHighlighting.cs | 31 + TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 20 +- .../Objects/LuaCompletionData.cs | 115 +- .../Objects/LuaCompletionIconFactory.cs | 144 +++ .../Objects/LuaCompletionIconKind.cs | 18 + .../Objects/LuaCompletionItem.cs | 25 +- .../Objects/LuaCompletionItemKind.cs | 31 + .../Objects/LuaCompletionWindowStyle.cs | 90 ++ .../Objects/LuaSemanticToken.cs | 37 + .../Services/ILuaIntellisenseProvider.cs | 4 +- .../TombLib.Scripting.Lua.csproj | 3 + .../TombLib.Scripting/Bases/TextEditorBase.cs | 8 +- .../LuaTextMateSyntaxHighlighting.cs | 102 ++ .../TextMateColorizingTransformer.cs | 106 ++ .../Highlighting/TextMateDocumentLineList.cs | 167 +++ .../Highlighting/TextMateHighlightingStyle.cs | 34 + .../TextMateThemeStyleResolver.cs | 103 ++ .../Rendering/MarkdownToolTipRenderer.cs | 8 +- .../TombLib.Scripting.csproj | 2 + 32 files changed, 3014 insertions(+), 168 deletions(-) create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json create mode 100644 TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs create mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs create mode 100644 TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs create mode 100644 TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs create mode 100644 TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs create mode 100644 TombLib/TombLib.Scripting/Highlighting/TextMateHighlightingStyle.cs create mode 100644 TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs diff --git a/ExternalResources.md b/ExternalResources.md index c3625bdab6..81a50f0d4c 100644 --- a/ExternalResources.md +++ b/ExternalResources.md @@ -25,3 +25,4 @@ A big thank you to all the authors for making their work publicly available and ### Icons Icons and graphics used under CC-BY ND 3.0 license from http://icons8.com + A subset of Codicons icon geometry used for Lua completion symbols is vendored from https://github.com/microsoft/vscode-codicons under the MIT license. diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 23eb687372..5689f753bc 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -26,12 +26,15 @@ private void HookLuaIntellisense() _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; _intellisenseProvider.DiagnosticsUpdated += IntellisenseProvider_DiagnosticsUpdated; + _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; + _intellisenseProvider.SemanticTokensUpdated += IntellisenseProvider_SemanticTokensUpdated; } private void DisposeLuaIntellisense() { EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; + _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; _intellisenseProvider.Dispose(); } @@ -55,6 +58,7 @@ private void EditorTabControl_LuaFileOpened(object sender, EventArgs e) _intellisenseProvider.OpenDocument(editor.FilePath, editor.Text); ApplyDiagnosticsToEditor(editor, _intellisenseProvider.GetDiagnostics(editor.FilePath)); + ApplySemanticTokensToEditor(editor, _intellisenseProvider.GetSemanticTokens(editor.FilePath)); } private void LuaEditor_TextChangedDelayed(object sender, EventArgs e) @@ -85,6 +89,21 @@ private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyL Debug.WriteLine($"[LuaLS] DiagnosticsUpdated for '{filePath}': {diagnostics?.Count ?? 0} items, tab matched={matched}."); } + private void IntellisenseProvider_SemanticTokensUpdated(string filePath, IReadOnlyList semanticTokens) + { + if (InvokeRequired) + { + BeginInvoke(new Action>(IntellisenseProvider_SemanticTokensUpdated), filePath, semanticTokens); + return; + } + + foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) + { + if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) + ApplySemanticTokensToEditor(editor, semanticTokens); + } + } + private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) { if (definitionLocation is null || string.IsNullOrWhiteSpace(definitionLocation.FilePath) || !File.Exists(definitionLocation.FilePath)) @@ -113,5 +132,8 @@ private static void ApplyDiagnosticsToEditor(LuaEditor editor, IReadOnlyList()); } + + private static void ApplySemanticTokensToEditor(LuaEditor editor, IReadOnlyList semanticTokens) + => editor.SetSemanticTokens(semanticTokens ?? Array.Empty()); } } \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs index aa03dae5d4..2fcb82e0f3 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Objects; namespace TombIDE.ScriptingStudio.Services.LuaIntellisense @@ -19,6 +20,8 @@ private sealed class DocumentState private readonly Dictionary _documents = new(StringComparer.OrdinalIgnoreCase); private readonly Dictionary> _diagnosticsByFilePath = new(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _diagnosticsVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _semanticTokensByFilePath = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _semanticTokensVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); public IReadOnlyList GetDiagnostics(string filePath) { @@ -28,6 +31,14 @@ public IReadOnlyList GetDiagnostics(string filePath) : Array.Empty(); } + public IReadOnlyList GetSemanticTokens(string filePath) + { + lock (_syncRoot) + return _semanticTokensByFilePath.TryGetValue(filePath, out IReadOnlyList semanticTokens) + ? semanticTokens + : Array.Empty(); + } + public LuaDocumentSynchronizationRequest Synchronize(string filePath, string content) { string safeContent = content ?? string.Empty; @@ -123,6 +134,25 @@ public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) } } + public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList semanticTokens) + { + lock (_syncRoot) + { + if (version > 0 + && _semanticTokensVersionByFilePath.TryGetValue(filePath, out int currentVersion) + && version < currentVersion) + { + return false; + } + + if (version > 0) + _semanticTokensVersionByFilePath[filePath] = version; + + _semanticTokensByFilePath[filePath] = semanticTokens ?? Array.Empty(); + return true; + } + } + private static LuaDocumentSnapshot CreateSnapshot(DocumentState state) => new LuaDocumentSnapshot(state.FilePath, state.Uri, state.Content, state.Version); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index 7ffa0d104f..7a9908353f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -19,6 +19,18 @@ internal sealed class LuaLanguageServerClient : IDisposable private readonly SemaphoreSlim _startLock = new(1, 1); private readonly SemaphoreSlim _writeLock = new(1, 1); private readonly ConcurrentDictionary> _pendingRequests = new(); + private static readonly string[] SupportedSemanticTokenTypes = + { + "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", + "parameter", "variable", "property", "enumMember", "event", "function", "method", + "macro", "keyword", "modifier", "comment", "string", "number", "regexp", + "operator", "decorator" + }; + private static readonly string[] SupportedSemanticTokenModifiers = + { + "declaration", "definition", "readonly", "static", "deprecated", "abstract", + "async", "modification", "documentation", "defaultLibrary", "global" + }; private long _requestId; private bool _isDisposed; @@ -28,8 +40,12 @@ internal sealed class LuaLanguageServerClient : IDisposable private Stream _outputStream; private Task _readLoopTask; private Task _stderrLoopTask; + private string[] _semanticTokenTypes = Array.Empty(); + private string[] _semanticTokenModifiers = Array.Empty(); public bool IsReady { get; private set; } + public IReadOnlyList SemanticTokenTypes => _semanticTokenTypes; + public IReadOnlyList SemanticTokenModifiers => _semanticTokenModifiers; public event Action DiagnosticsPublished; @@ -81,7 +97,8 @@ public async Task StartAsync(CancellationToken cancellationToken) using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); - await SendRequestAsync("initialize", BuildInitializeParams(), initializeTimeout.Token).ConfigureAwait(false); + JsonElement initializeResponse = await SendRequestAsync("initialize", BuildInitializeParams(), initializeTimeout.Token).ConfigureAwait(false); + CaptureSemanticTokenLegend(initializeResponse); IsReady = true; @@ -131,6 +148,13 @@ private object BuildInitializeParams() => new { processId = Process.GetCurrentProcess().Id, + initializationOptions = new + { + changeConfiguration = true, + viewDocument = true, + trustByClient = true, + useSemanticByRange = true + }, rootUri = CreateFileUri(_workspaceRootDirectoryPath), workspaceFolders = new[] { @@ -151,6 +175,7 @@ private object BuildInitializeParams() { completion = new { + contextSupport = true, completionItem = new { snippetSupport = false, @@ -180,11 +205,56 @@ private object BuildInitializeParams() } }, contextSupport = true + }, + semanticTokens = new + { + requests = new + { + range = true + }, + tokenTypes = SupportedSemanticTokenTypes, + tokenModifiers = SupportedSemanticTokenModifiers, + formats = new[] { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = false, + augmentsSyntaxTokens = true } } } }; + private void CaptureSemanticTokenLegend(JsonElement initializeResponse) + { + _semanticTokenTypes = Array.Empty(); + _semanticTokenModifiers = Array.Empty(); + + if (!initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities) + || !capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider) + || !semanticTokensProvider.TryGetProperty("legend", out JsonElement legend)) + { + return; + } + + _semanticTokenTypes = ReadStringArray(legend, "tokenTypes"); + _semanticTokenModifiers = ReadStringArray(legend, "tokenModifiers"); + } + + private static string[] ReadStringArray(JsonElement parent, string propertyName) + { + if (!parent.TryGetProperty(propertyName, out JsonElement property) || property.ValueKind != JsonValueKind.Array) + return Array.Empty(); + + var values = new List(); + + foreach (JsonElement item in property.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.String) + values.Add(item.GetString()); + } + + return values.ToArray(); + } + private async Task ReadLoopAsync() { try diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index 5b3ea9a978..a4fb6dd2e6 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -22,6 +22,7 @@ internal sealed class LuaLanguageServerIntellisenseProvider : ILuaIntellisensePr public bool IsAvailable => !_isDisposed && _client is not null; public event Action> DiagnosticsUpdated; + public event Action> SemanticTokensUpdated; public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string serverExecutablePath) { @@ -47,6 +48,17 @@ public IReadOnlyList GetDiagnostics(string filePath) return _documents.GetDiagnostics(normalizedFilePath); } + public IReadOnlyList GetSemanticTokens(string filePath) + { + if (_isDisposed) + return Array.Empty(); + + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return Array.Empty(); + + return _documents.GetSemanticTokens(normalizedFilePath); + } + public void OpenDocument(string filePath, string content) => _ = TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None); @@ -65,7 +77,7 @@ public void CloseDocument(string filePath) } public async Task> GetCompletionItemsAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default) + int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) { if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) @@ -78,12 +90,17 @@ public async Task> GetCompletionItemsAsync(stri { textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, position = new { line, character = column }, - context = new { triggerKind = 1 } + context = BuildCompletionContext(triggerCharacter) }, cancellationToken).ConfigureAwait(false); return LuaLanguageServerResponseParser.ParseCompletionItems(response); } + private static object BuildCompletionContext(char? triggerCharacter) + => triggerCharacter is null + ? new { triggerKind = 1 } + : new { triggerKind = 2, triggerCharacter = triggerCharacter.ToString() }; + public async Task GetHoverAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { @@ -228,9 +245,59 @@ await _client.SendNotificationAsync("textDocument/didChange", }, cancellationToken).ConfigureAwait(false); } + await RefreshSemanticTokensAsync(request.Document, cancellationToken).ConfigureAwait(false); + return true; } + private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) + { + if (_client is null || document is null || _client.SemanticTokenTypes.Count == 0) + return; + + try + { + JsonElement response = await _client.SendRequestAsync("textDocument/semanticTokens/range", + new + { + textDocument = new { uri = document.Uri }, + range = BuildDocumentRange(document.Content) + }, cancellationToken).ConfigureAwait(false); + + IReadOnlyList semanticTokens = LuaLanguageServerSemanticTokensParser.Parse( + response, + document, + _client.SemanticTokenTypes, + _client.SemanticTokenModifiers); + + if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, semanticTokens)) + return; + + SemanticTokensUpdated?.Invoke(document.FilePath, semanticTokens); + } + catch + { + // Ignore semantic token failures and fall back to TextMate syntax highlighting. + } + } + + private static object BuildDocumentRange(string content) + { + string normalizedContent = (content ?? string.Empty) + .Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n'); + + string[] lines = normalizedContent.Split('\n'); + int endLine = Math.Max(0, lines.Length - 1); + int endCharacter = lines.Length == 0 ? 0 : lines[endLine].Length; + + return new + { + start = new { line = 0, character = 0 }, + end = new { line = endLine, character = endCharacter } + }; + } + private async Task CloseDocumentAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) { if (_client is null) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs index 64ac8cb6dc..06a2a1595a 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -32,6 +32,7 @@ public static IReadOnlyList ParseCompletionItems(JsonElement return Array.Empty(); var items = new List(); + int itemIndex = 0; foreach (JsonElement itemElement in itemsElement.EnumerateArray()) { @@ -52,8 +53,29 @@ public static IReadOnlyList ParseCompletionItems(JsonElement insertText = StripSnippetPlaceholders(insertText); } - string description = BuildCompletionDescription(itemElement); - items.Add(new LuaCompletionItem(label, insertText, description)); + string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) + ? filterTextElement.GetString() + : label; + + LuaCompletionItemKind kind = TryReadCompletionKind(itemElement, out LuaCompletionItemKind completionKind) + ? completionKind + : LuaCompletionItemKind.Text; + + string detail = BuildCompletionDetail(itemElement); + MarkupContent description = BuildCompletionDescription(itemElement); + string searchableDescription = NormalizeMarkupText(description.Text); + items.Add(new LuaCompletionItem( + label, + insertText, + detail, + description.Text, + filterText, + BuildCompletionPriority(itemElement, detail, searchableDescription, itemIndex), + kind, + BuildCompletionIconKind(kind, detail), + description.IsMarkdown)); + + itemIndex++; } return items @@ -62,6 +84,123 @@ public static IReadOnlyList ParseCompletionItems(JsonElement .ToList(); } + private static double BuildCompletionPriority(JsonElement itemElement, string detail, string description, int itemIndex) + { + const double responseOrderWeight = 100000.0; + double priority = responseOrderWeight - itemIndex; + string searchableText = CombineCompletionText(detail, description); + + if (itemElement.TryGetProperty("preselect", out JsonElement preselectElement) + && preselectElement.ValueKind == JsonValueKind.True) + { + priority += 1000000.0; + } + + if (itemElement.TryGetProperty("kind", out JsonElement kindElement) + && kindElement.TryGetInt32(out int completionKind)) + { + priority += completionKind switch + { + 6 => 10000.0, + 5 => 9000.0, + 10 => 9000.0, + 2 => 7000.0, + 3 => 7000.0, + 14 => -5000.0, + _ => 0.0 + }; + } + + if (!string.IsNullOrWhiteSpace(searchableText)) + { + if (CompletionTextContains(searchableText, "local")) + priority += 20000.0; + + if (CompletionTextContains(searchableText, "upvalue") + || CompletionTextContains(searchableText, "parameter")) + { + priority += 15000.0; + } + } + + return priority; + } + + private static bool TryReadCompletionKind(JsonElement itemElement, out LuaCompletionItemKind kind) + { + kind = LuaCompletionItemKind.Text; + + if (!itemElement.TryGetProperty("kind", out JsonElement kindElement) + || !kindElement.TryGetInt32(out int rawKind) + || !Enum.IsDefined(typeof(LuaCompletionItemKind), rawKind)) + { + return false; + } + + kind = (LuaCompletionItemKind)rawKind; + return true; + } + + private static LuaCompletionIconKind BuildCompletionIconKind(LuaCompletionItemKind kind, string detail) + { + if (CompletionTextContains(detail, "parameter")) + return LuaCompletionIconKind.Parameter; + + if (CompletionTextContains(detail, "module") || CompletionTextContains(detail, "namespace")) + return LuaCompletionIconKind.Namespace; + + if (CompletionTextContains(detail, "method") || CompletionTextContains(detail, "function")) + return LuaCompletionIconKind.Method; + + if (CompletionTextContains(detail, "field")) + return LuaCompletionIconKind.Field; + + if (CompletionTextContains(detail, "property") || CompletionTextContains(detail, "global") + || CompletionTextContains(detail, "default library")) + { + return LuaCompletionIconKind.Property; + } + + if (CompletionTextContains(detail, "constant")) + return LuaCompletionIconKind.Constant; + + if (CompletionTextContains(detail, "keyword")) + return LuaCompletionIconKind.Keyword; + + if (CompletionTextContains(detail, "class") || CompletionTextContains(detail, "interface") + || CompletionTextContains(detail, "enum") || CompletionTextContains(detail, "struct")) + { + return LuaCompletionIconKind.Class; + } + + return kind switch + { + LuaCompletionItemKind.Method => LuaCompletionIconKind.Method, + LuaCompletionItemKind.Function => LuaCompletionIconKind.Method, + LuaCompletionItemKind.Constructor => LuaCompletionIconKind.Method, + LuaCompletionItemKind.Field => LuaCompletionIconKind.Field, + LuaCompletionItemKind.Variable => LuaCompletionIconKind.Variable, + LuaCompletionItemKind.Class => LuaCompletionIconKind.Class, + LuaCompletionItemKind.Interface => LuaCompletionIconKind.Class, + LuaCompletionItemKind.Module => LuaCompletionIconKind.Namespace, + LuaCompletionItemKind.Property => LuaCompletionIconKind.Property, + LuaCompletionItemKind.Value => LuaCompletionIconKind.Variable, + LuaCompletionItemKind.Enum => LuaCompletionIconKind.Class, + LuaCompletionItemKind.Keyword => LuaCompletionIconKind.Keyword, + LuaCompletionItemKind.Snippet => LuaCompletionIconKind.Keyword, + LuaCompletionItemKind.File => LuaCompletionIconKind.File, + LuaCompletionItemKind.Reference => LuaCompletionIconKind.Variable, + LuaCompletionItemKind.Folder => LuaCompletionIconKind.Folder, + LuaCompletionItemKind.EnumMember => LuaCompletionIconKind.Constant, + LuaCompletionItemKind.Constant => LuaCompletionIconKind.Constant, + LuaCompletionItemKind.Struct => LuaCompletionIconKind.Class, + LuaCompletionItemKind.Event => LuaCompletionIconKind.Method, + LuaCompletionItemKind.Operator => LuaCompletionIconKind.Keyword, + LuaCompletionItemKind.TypeParameter => LuaCompletionIconKind.Class, + _ => LuaCompletionIconKind.Misc + }; + } + public static LuaHoverInfo ParseHoverInfo(JsonElement response) { if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) @@ -195,34 +334,48 @@ public static LuaSignatureInfo ParseSignatureHelp(JsonElement response) return new LuaSignatureInfo(label, documentation, parameters, activeParameter); } - private static string BuildCompletionDescription(JsonElement itemElement) + private static string BuildCompletionDetail(JsonElement itemElement) { - var descriptionBuilder = new StringBuilder(); + if (!itemElement.TryGetProperty("detail", out JsonElement detailElement)) + return null; - if (itemElement.TryGetProperty("detail", out JsonElement detailElement)) - { - string detail = detailElement.GetString(); + string detail = detailElement.GetString(); + return string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); + } - if (!string.IsNullOrWhiteSpace(detail)) - descriptionBuilder.AppendLine(detail.Trim()); - } + private static MarkupContent BuildCompletionDescription(JsonElement itemElement) + { + if (!itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) + return default; - if (itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) - { - string documentation = ExtractMarkupText(documentationElement); + MarkupContent documentation = ExtractMarkupContent(documentationElement); - if (!string.IsNullOrWhiteSpace(documentation)) - { - if (descriptionBuilder.Length > 0) - descriptionBuilder.AppendLine(); + if (string.IsNullOrWhiteSpace(documentation.Text)) + return default; - descriptionBuilder.Append(documentation.Trim()); - } - } + string normalizedText = documentation.IsMarkdown + ? NormalizeMarkdownText(documentation.Text) + : NormalizeMarkupText(documentation.Text); - return descriptionBuilder.Length == 0 ? null : descriptionBuilder.ToString(); + return string.IsNullOrWhiteSpace(normalizedText) + ? default + : new MarkupContent(normalizedText, documentation.IsMarkdown); } + private static string CombineCompletionText(string detail, string description) + { + if (string.IsNullOrWhiteSpace(detail)) + return description; + + if (string.IsNullOrWhiteSpace(description)) + return detail; + + return detail + Environment.NewLine + description; + } + + private static bool CompletionTextContains(string text, string token) + => !string.IsNullOrWhiteSpace(text) && text.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; + private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, out string parameterLabel) { parameterLabel = null; @@ -312,6 +465,13 @@ private static string NormalizeMarkupText(string text) return string.Join(Environment.NewLine, lines).Trim(); } + private static string NormalizeMarkdownText(string text) + => string.IsNullOrWhiteSpace(text) + ? null + : text.Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n') + .Trim(); + private static string StripSnippetPlaceholders(string snippet) { if (string.IsNullOrWhiteSpace(snippet)) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs new file mode 100644 index 0000000000..2b4cf78ac4 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +{ + internal static class LuaLanguageServerSemanticTokensParser + { + public static IReadOnlyList Parse(JsonElement response, LuaDocumentSnapshot document, + IReadOnlyList tokenTypes, IReadOnlyList tokenModifiers) + { + if (document is null || tokenTypes is null || tokenTypes.Count == 0) + return Array.Empty(); + + if (!response.TryGetProperty("data", out JsonElement dataElement) || dataElement.ValueKind != JsonValueKind.Array) + return Array.Empty(); + + string[] lines = NormalizeLineEndings(document.Content).Split('\n'); + var semanticTokens = new List(); + var rawData = new List(); + + foreach (JsonElement item in dataElement.EnumerateArray()) + { + if (item.TryGetInt32(out int value)) + rawData.Add(value); + } + + int line = 0; + int character = 0; + + for (int i = 0; i + 4 < rawData.Count; i += 5) + { + int deltaLine = rawData[i]; + int deltaCharacter = rawData[i + 1]; + int length = rawData[i + 2]; + int tokenTypeIndex = rawData[i + 3]; + int modifierMask = rawData[i + 4]; + + line += deltaLine; + + if (deltaLine == 0) + character += deltaCharacter; + else + character = deltaCharacter; + + if (line < 0 || line >= lines.Length || tokenTypeIndex < 0 || tokenTypeIndex >= tokenTypes.Count) + continue; + + int lineLength = lines[line].Length; + int safeCharacter = Math.Max(0, Math.Min(character, lineLength)); + int safeLength = Math.Max(0, Math.Min(length, lineLength - safeCharacter)); + + if (safeLength == 0) + continue; + + semanticTokens.Add(new LuaSemanticToken( + line, + safeCharacter, + safeLength, + tokenTypes[tokenTypeIndex], + DecodeModifiers(modifierMask, tokenModifiers))); + } + + return semanticTokens; + } + + private static IReadOnlyList DecodeModifiers(int modifierMask, IReadOnlyList tokenModifiers) + { + if (modifierMask == 0 || tokenModifiers is null || tokenModifiers.Count == 0) + return Array.Empty(); + + var modifiers = new List(); + + for (int bitIndex = 0; bitIndex < tokenModifiers.Count; bitIndex++) + { + if ((modifierMask & (1 << bitIndex)) != 0) + modifiers.Add(tokenModifiers[bitIndex]); + } + + return modifiers; + } + + private static string NormalizeLineEndings(string content) + => (content ?? string.Empty) + .Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n'); + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs index 951aef8c7f..fadb330646 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs @@ -29,6 +29,13 @@ public static object Create(string workspaceRootDirectoryPath) { callSnippet = "Disable" }, + semantic = new + { + enable = true, + annotation = true, + variable = true, + keyword = false + }, diagnostics = new { disable = new[] { "duplicate-set-field" } diff --git a/TombLib/TombLib.Forms/Forms/FormAbout.designer.cs b/TombLib/TombLib.Forms/Forms/FormAbout.designer.cs index cbaa1bdcfa..bf3fdfce2f 100644 --- a/TombLib/TombLib.Forms/Forms/FormAbout.designer.cs +++ b/TombLib/TombLib.Forms/Forms/FormAbout.designer.cs @@ -44,6 +44,7 @@ private void InitializeComponent() linkLabel14 = new System.Windows.Forms.LinkLabel(); linkLabel13 = new System.Windows.Forms.LinkLabel(); linkLabel8 = new System.Windows.Forms.LinkLabel(); + linkLabel17 = new System.Windows.Forms.LinkLabel(); darkLabel13 = new DarkUI.Controls.DarkLabel(); linkLabel7 = new System.Windows.Forms.LinkLabel(); darkLabel12 = new DarkUI.Controls.DarkLabel(); @@ -57,6 +58,7 @@ private void InitializeComponent() darkLabel8 = new DarkUI.Controls.DarkLabel(); linkLabel3 = new System.Windows.Forms.LinkLabel(); darkLabel7 = new DarkUI.Controls.DarkLabel(); + darkLabel23 = new DarkUI.Controls.DarkLabel(); darkLabel16 = new DarkUI.Controls.DarkLabel(); linkLabel9 = new System.Windows.Forms.LinkLabel(); darkLabel14 = new DarkUI.Controls.DarkLabel(); @@ -76,7 +78,7 @@ private void InitializeComponent() tableLayoutPanel1.Controls.Add(butOk, 1, 0); tableLayoutPanel1.Controls.Add(darkLabel1, 0, 0); tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Bottom; - tableLayoutPanel1.Location = new System.Drawing.Point(0, 390); + tableLayoutPanel1.Location = new System.Drawing.Point(0, 403); tableLayoutPanel1.Name = "tableLayoutPanel1"; tableLayoutPanel1.RowCount = 1; tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); @@ -128,6 +130,7 @@ private void InitializeComponent() panel1.Controls.Add(linkLabel14); panel1.Controls.Add(linkLabel13); panel1.Controls.Add(linkLabel8); + panel1.Controls.Add(linkLabel17); panel1.Controls.Add(darkLabel13); panel1.Controls.Add(linkLabel7); panel1.Controls.Add(darkLabel12); @@ -141,6 +144,7 @@ private void InitializeComponent() panel1.Controls.Add(darkLabel8); panel1.Controls.Add(linkLabel3); panel1.Controls.Add(darkLabel7); + panel1.Controls.Add(darkLabel23); panel1.Controls.Add(darkLabel16); panel1.Controls.Add(linkLabel9); panel1.Controls.Add(darkLabel14); @@ -149,7 +153,7 @@ private void InitializeComponent() panel1.Dock = System.Windows.Forms.DockStyle.Top; panel1.Location = new System.Drawing.Point(0, 64); panel1.Name = "panel1"; - panel1.Size = new System.Drawing.Size(614, 326); + panel1.Size = new System.Drawing.Size(614, 339); panel1.TabIndex = 8; // // tableLayoutPanel2 @@ -283,6 +287,21 @@ private void InitializeComponent() linkLabel8.VisitedLinkColor = System.Drawing.Color.FromArgb(184, 163, 233); linkLabel8.Click += btnLink_Click; // + // linkLabel17 + // + linkLabel17.ActiveLinkColor = System.Drawing.Color.FromArgb(184, 163, 233); + linkLabel17.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; + linkLabel17.AutoEllipsis = true; + linkLabel17.LinkColor = System.Drawing.Color.FromArgb(184, 163, 233); + linkLabel17.Location = new System.Drawing.Point(319, 266); + linkLabel17.Name = "linkLabel17"; + linkLabel17.Size = new System.Drawing.Size(279, 13); + linkLabel17.TabIndex = 54; + linkLabel17.TabStop = true; + linkLabel17.Text = "github.com/microsoft/vscode-codicons"; + linkLabel17.VisitedLinkColor = System.Drawing.Color.FromArgb(184, 163, 233); + linkLabel17.Click += btnLink_Click; + // // darkLabel13 // darkLabel13.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; @@ -450,13 +469,24 @@ private void InitializeComponent() darkLabel7.TabIndex = 34; darkLabel7.Text = "NCalc is used under MIT license."; // + // darkLabel23 + // + darkLabel23.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; + darkLabel23.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); + darkLabel23.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); + darkLabel23.Location = new System.Drawing.Point(7, 266); + darkLabel23.Name = "darkLabel23"; + darkLabel23.Size = new System.Drawing.Size(267, 13); + darkLabel23.TabIndex = 55; + darkLabel23.Text = "Codicons are used under MIT license."; + // // darkLabel16 // darkLabel16.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; darkLabel16.AutoSize = true; darkLabel16.Font = new System.Drawing.Font("Segoe UI", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); darkLabel16.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel16.Location = new System.Drawing.Point(7, 290); + darkLabel16.Location = new System.Drawing.Point(7, 303); darkLabel16.Name = "darkLabel16"; darkLabel16.Size = new System.Drawing.Size(377, 24); darkLabel16.TabIndex = 28; @@ -468,7 +498,7 @@ private void InitializeComponent() linkLabel9.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left; linkLabel9.AutoSize = true; linkLabel9.LinkColor = System.Drawing.Color.FromArgb(184, 163, 233); - linkLabel9.Location = new System.Drawing.Point(364, 274); + linkLabel9.Location = new System.Drawing.Point(364, 287); linkLabel9.Name = "linkLabel9"; linkLabel9.Size = new System.Drawing.Size(64, 13); linkLabel9.TabIndex = 21; @@ -483,7 +513,7 @@ private void InitializeComponent() darkLabel14.AutoSize = true; darkLabel14.Font = new System.Drawing.Font("Segoe UI", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); darkLabel14.ForeColor = System.Drawing.Color.FromArgb(220, 220, 220); - darkLabel14.Location = new System.Drawing.Point(6, 274); + darkLabel14.Location = new System.Drawing.Point(6, 287); darkLabel14.Name = "darkLabel14"; darkLabel14.Size = new System.Drawing.Size(360, 13); darkLabel14.TabIndex = 20; @@ -517,7 +547,7 @@ private void InitializeComponent() AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; CancelButton = butOk; - ClientSize = new System.Drawing.Size(614, 422); + ClientSize = new System.Drawing.Size(614, 435); Controls.Add(panel1); Controls.Add(pictureBox); Controls.Add(tableLayoutPanel1); @@ -574,5 +604,7 @@ private void InitializeComponent() private System.Windows.Forms.LinkLabel linkLabel14; private DarkUI.Controls.DarkLabel darkLabel22; private System.Windows.Forms.LinkLabel linkLabel16; + private System.Windows.Forms.LinkLabel linkLabel17; + private DarkUI.Controls.DarkLabel darkLabel23; } } diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml index ffdc258cfd..ce37e26aed 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml @@ -1,38 +1,58 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - TODO - FIXME - - - HACK - UNDONE - + \b(?:TODO|FIXME|HACK|UNDONE)\b - - + + + + + + + @(?:alias|as|async|cast|class|deprecated|diagnostic|enum|field|generic|meta|module|nodiscard|operator|overload|package|param|private|protected|public|return|see|source|type|vararg) + (?<=@param\s)[A-Za-z_][A-Za-z0-9_]* + (?<=@field\s)[A-Za-z_][A-Za-z0-9_]* + (?<=@generic\s)[A-Za-z_][A-Za-z0-9_]* + (?<=@alias\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* + (?<=@class\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* + (?<=@enum\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* + (?<=@module\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* + (?<=@type\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* + (?<=@return\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* + \b(?:any|boolean|function|integer|lightuserdata|nil|number|string|table|thread|unknown|userdata|void)\b + + \b\d+(?:\.\d+)?\b + + - - --- - - - - + + + --- @@ -44,128 +64,86 @@ -- - + " " - - - - - + ' ' - - - - - \[[=]*\[ + \[[=]*\[ \][=]*] - + (?<=::)[A-Za-z_][A-Za-z0-9_]*(?=::) + (?<=\bgoto\s)[A-Za-z_][A-Za-z0-9_]* + + <(?:const|close)> + + \.\.\. + + + self + _ENV + + + true false + nil - + and break + continue do else elseif end - false for function + goto if in local - not or repeat return then - true until - while using - continue + while - - break - return - + (?<=\bfunction\s)(?:[A-Za-z_][A-Za-z0-9_]*(?:[.:][A-Za-z_][A-Za-z0-9_]*)*) + (?<=\blocal\s)[A-Za-z_][A-Za-z0-9_]*(?=\s*=\s*function\b) - - local - + \b(?:_G|_VERSION|bit32|coroutine|debug|Effects|Inventory|io|jit|Logic|math|Misc|Objects|os|package|string|Strings|table|TEN|utf8)\b - - nil - + \b(?:assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|loadstring|module|next|pairs|pcall|print|rawequal|rawget|rawlen|rawset|require|select|setfenv|setmetatable|tonumber|tostring|type|unpack|warn|xpcall)\b(?=\s*(?:\(|\{|"|'|\[=*\[)) - - TEN - Logic - Objects - Strings - Inventory - Misc - Effects - + (?<=\.)[A-Za-z_][A-Za-z0-9_]*(?=\s*(?:\(|\{|"|'|\[=*\[)) + (?<=:)[A-Za-z_][A-Za-z0-9_]*(?=\s*(?:\(|\{|"|'|\[=*\[)) + \b[A-Za-z_][A-Za-z0-9_]*(?=\s*(?:\(|\{|"|'|\[=*\[)) - - - \b - [\d\w_]+ # an identifier - (?=\s*\() # followed by ( - - - \b - [\d\w_]+ # an identifier - (?=\s*\") # followed by " - - - \b - [\d\w_]+ # an identifier - (?=\s*\') # followed by ' - - - \b - [\d\w_]+ # an identifier - (?=\s*\{) # followed by { - - - \b - [\d\w_]+ # an identifier - (?=\s*\[) # followed by [ - + (?<=\.)[A-Za-z_][A-Za-z0-9_]* + (?<=:)[A-Za-z_][A-Za-z0-9_]* - - \b0[xX][0-9a-fA-F]+ # hex number + \b0[xX](?:[0-9a-fA-F]+(?:\.[0-9a-fA-F]*)?|\.[0-9a-fA-F]+)(?:[pP][+\-]?\d+)?\b | - ( \b\d+(\.[0-9]+)? #number with optional floating point - | \.[0-9]+ #or just starting with floating point - ) - ([eE][+-]?[0-9]+)? # optional exponent - - - - \b - [\d\w_]+ # an identifier - (?=\s*\.) # followed by . + \b\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?\b + | + \B\.\d+(?:[eE][+\-]?\d+)?\b - - [?,.;()\[\]{}+\-/%*<>^+~!|&]+ - + \.\.?|//|==|~=|<=|>=|<<|>>|[=+\-*/%^#<>~&|] + ::|[.,;:()\[\]{}] diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json new file mode 100644 index 0000000000..a2c41e611a --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json @@ -0,0 +1,978 @@ +{ + "name": "Lua", + "scopeName": "source.lua", + "patterns": [ + { + "begin": "\\b(?:(local)\\s+)?(function)\\b(?![,:])", + "beginCaptures": { + "1": { + "name": "keyword.local.lua" + }, + "2": { + "name": "keyword.control.lua" + } + }, + "end": "(?<=[\\)\\-{}\\[\\]\"'])", + "name": "meta.function.lua", + "patterns": [ + { + "include": "#comment" + }, + { + "begin": "(\\()", + "beginCaptures": { + "1": { + "name": "punctuation.definition.parameters.begin.lua" + } + }, + "end": "(\\))|(?=[\\-{}\\[\\]\"'])|(?", + "captures": { + "0": { + "name": "storage.type.attribute.lua" + } + } + }, + { + "match": "\\<[a-zA-Z_\\*][a-zA-Z0-9_\\.\\*\\-]*\\>", + "name": "storage.type.generic.lua" + }, + { + "match": "\\b(break|do|else|for|if|elseif|goto|return|then|repeat|while|until|end|in)\\b", + "name": "keyword.control.lua" + }, + { + "match": "\\b(local)\\b", + "name": "keyword.local.lua" + }, + { + "match": "^\\s*(global)\\b(?!\\s*=)", + "captures": { + "1": { + "name": "keyword.global.lua" + } + } + }, + { + "match": "\\b(function)\\b(?![,:])", + "name": "keyword.control.lua" + }, + { + "match": "(?=?|(?|\\<", + "name": "keyword.operator.lua" + } + ] + }, + { + "begin": "(?<=---)[ \\t]*@see", + "beginCaptures": { + "0": { + "name": "storage.type.annotation.lua" + } + }, + "end": "(?=[\\n@#])", + "patterns": [ + { + "match": "\\b([a-zA-Z_\\*][a-zA-Z0-9_\\.\\*\\-]*)", + "name": "support.class.lua" + }, + { + "match": "#", + "name": "keyword.operator.lua" + } + ] + }, + { + "begin": "(?<=---)[ \\t]*@diagnostic", + "beginCaptures": { + "0": { + "name": "storage.type.annotation.lua" + } + }, + "end": "(?=[\\n@#])", + "patterns": [ + { + "begin": "([a-zA-Z_\\-0-9]+)[ \\t]*(:)?", + "beginCaptures": { + "1": { + "name": "keyword.other.unit" + }, + "2": { + "name": "keyword.operator.unit" + } + }, + "end": "(?=\\n)", + "patterns": [ + { + "match": "\\b([a-zA-Z_\\*][a-zA-Z0-9_\\-]*)", + "name": "support.class.lua" + }, + { + "match": ",", + "name": "keyword.operator.lua" + } + ] + } + ] + }, + { + "begin": "(?<=---)[ \\t]*@module", + "beginCaptures": { + "0": { + "name": "storage.type.annotation.lua" + } + }, + "end": "(?=[\\n@#])", + "patterns": [ + { + "include": "#string" + } + ] + }, + { + "match": "(?<=---)[ \\t]*@(async|nodiscard)", + "name": "storage.type.annotation.lua" + }, + { + "begin": "(?<=---)\\|\\s*[\\>\\+]?", + "beginCaptures": { + "0": { + "name": "storage.type.annotation.lua" + } + }, + "end": "(?=[\\n@#])", + "patterns": [ + { + "include": "#string" + } + ] + } + ] + }, + "emmydoc.type": { + "patterns": [ + { + "begin": "\\bfun\\b", + "beginCaptures": { + "0": { + "name": "keyword.control.lua" + } + }, + "end": "(?=[\\s#])", + "patterns": [ + { + "match": "[\\(\\),\\:\\?\\[\\]\\<\\>][ \\t]*", + "name": "keyword.operator.lua" + }, + { + "match": "([a-zA-Z_][a-zA-Z0-9_\\.\\*\\-]*)(?", + "name": "storage.type.generic.lua" + }, + { + "match": "\\basync\\b", + "name": "entity.name.tag.lua" + }, + { + "match": "[\\{\\}\\:\\,\\?\\|\\`][ \\t]*", + "name": "keyword.operator.lua" + }, + { + "begin": "(?=[a-zA-Z_\\.\\*\"'\\[])", + "end": "(?=[\\s\\)\\,\\?\\:\\}\\|#])", + "patterns": [ + { + "match": "([a-zA-Z0-9_\\.\\*\\[\\]\\<\\>\\,\\-]+)(?> EmptyTokensByLine = + new Dictionary>(); + + private readonly TextView _textView; + private IReadOnlyDictionary> _tokensByLine = EmptyTokensByLine; + + public LuaSemanticTokensColorizer(TextView textView) + => _textView = textView ?? throw new ArgumentNullException(nameof(textView)); + + public void SetTokens(IReadOnlyList tokens) + { + if (tokens is null || tokens.Count == 0) + { + ClearTokens(); + return; + } + + var groupedTokens = new Dictionary>(); + + for (int i = 0; i < tokens.Count; i++) + { + LuaSemanticToken token = tokens[i]; + + if (!groupedTokens.TryGetValue(token.Line, out List lineTokens)) + { + lineTokens = new List(); + groupedTokens[token.Line] = lineTokens; + } + + lineTokens.Add(token); + } + + var frozenMap = new Dictionary>(groupedTokens.Count); + + foreach (KeyValuePair> pair in groupedTokens) + frozenMap[pair.Key] = pair.Value; + + _tokensByLine = frozenMap; + _textView.Redraw(); + } + + public void ClearTokens() + { + if (_tokensByLine.Count == 0) + return; + + _tokensByLine = EmptyTokensByLine; + _textView.Redraw(); + } + + protected override void ColorizeLine(DocumentLine line) + { + if (!_tokensByLine.TryGetValue(line.LineNumber - 1, out IReadOnlyList tokens)) + return; + + int lineLength = line.Length; + + for (int i = 0; i < tokens.Count; i++) + { + LuaSemanticToken token = tokens[i]; + LuaSemanticTokenStyle style = ResolveStyle(token); + + if (!style.HasFormatting) + continue; + + int startIndex = Math.Max(0, Math.Min(token.Character, lineLength)); + int endIndex = Math.Max(startIndex, Math.Min(token.Character + token.Length, lineLength)); + + if (endIndex <= startIndex) + continue; + + ChangeLinePart(line.Offset + startIndex, line.Offset + endIndex, element => ApplyStyle(element, style)); + } + } + + private static LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) + { + Brush foreground = token.Type switch + { + "namespace" => token.HasModifier("defaultLibrary") ? DefaultLibraryBrush : TypeBrush, + "type" => TypeBrush, + "class" => TypeBrush, + "enum" => TypeBrush, + "interface" => TypeBrush, + "struct" => TypeBrush, + "typeParameter" => TypeBrush, + "function" => token.HasModifier("defaultLibrary") ? DefaultLibraryBrush : FunctionBrush, + "method" => token.HasModifier("defaultLibrary") ? DefaultLibraryBrush : FunctionBrush, + "parameter" => ParameterBrush, + "property" => PropertyBrush, + "event" => PropertyBrush, + "enumMember" => EnumMemberBrush, + "decorator" => DecoratorBrush, + "macro" => MacroBrush, + "variable" => ResolveVariableBrush(token), + _ => null + }; + + return new LuaSemanticTokenStyle( + foreground, + token.HasModifier("declaration") && (token.Type == "function" || token.Type == "method"), + null, + token.HasModifier("deprecated") ? DeprecatedDecorations : null); + } + + private static Brush ResolveVariableBrush(LuaSemanticToken token) + { + if (token.HasModifier("defaultLibrary")) + return DefaultLibraryBrush; + + if (token.HasModifier("global")) + return GlobalVariableBrush; + + return null; + } + + private static void ApplyStyle(VisualLineElement element, LuaSemanticTokenStyle style) + { + VisualLineElementTextRunProperties properties = element.TextRunProperties; + + if (style.Foreground is not null) + properties.SetForegroundBrush(style.Foreground); + + if (style.IsBold) + { + Typeface typeface = properties.Typeface; + properties.SetTypeface(new Typeface(typeface.FontFamily, typeface.Style, FontWeights.Bold, typeface.Stretch)); + } + + if (style.TextDecorations is not null) + properties.SetTextDecorations(style.TextDecorations); + } + + private static Brush CreateFrozenBrush(string colorValue) + { + var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); + brush.Freeze(); + return brush; + } + + private static TextDecorationCollection CreateTextDecorations(TextDecorationCollection source) + { + var clone = source.Clone(); + clone.Freeze(); + return clone; + } + + private readonly struct LuaSemanticTokenStyle + { + public LuaSemanticTokenStyle(Brush foreground, bool isBold, Brush background, TextDecorationCollection textDecorations) + { + Foreground = foreground; + IsBold = isBold; + Background = background; + TextDecorations = textDecorations; + } + + public Brush Foreground { get; } + public bool IsBold { get; } + public Brush Background { get; } + public TextDecorationCollection TextDecorations { get; } + + public bool HasFormatting => Foreground is not null || Background is not null || IsBold || TextDecorations is not null; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index f9b79ee6c1..e82884ecb3 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -1,17 +1,27 @@ -using ICSharpCode.AvalonEdit.Document; using System; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using System.Windows; +using System.Windows.Controls; using System.Windows.Input; +using System.Windows.Interop; +using System.Windows.Threading; +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; using TombLib.Scripting.Lua.Objects; namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { + private static readonly FieldInfo CompletionToolTipField = + typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); + private CancellationTokenSource _hoverCancellationTokenSource; + private CancellationTokenSource _completionCancellationTokenSource; private CancellationTokenSource _signatureCancellationTokenSource; + private int _completionRequestToken; private int _hoverRequestToken; private Window _hostWindow; @@ -57,10 +67,17 @@ private void HostWindow_Deactivated(object sender, EventArgs e) private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) { + _textMateHighlighting?.Dispose(); + _textMateHighlighting = null; + _hoverCancellationTokenSource?.Cancel(); _hoverCancellationTokenSource?.Dispose(); _hoverCancellationTokenSource = null; + _completionCancellationTokenSource?.Cancel(); + _completionCancellationTokenSource?.Dispose(); + _completionCancellationTokenSource = null; + _signatureCancellationTokenSource?.Cancel(); _signatureCancellationTokenSource?.Dispose(); _signatureCancellationTokenSource = null; @@ -72,6 +89,7 @@ private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) DismissSignatureHelp(); ClearDiagnostics(); + ClearSemanticTokens(); IntellisenseProvider?.CloseDocument(FilePath); } @@ -85,7 +103,7 @@ private async void TextArea_TextEntering(object sender, TextCompositionEventArgs { e.Handled = true; - await RequestCompletionAsync(CaretOffset).ConfigureAwait(true); + await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); } } @@ -108,17 +126,22 @@ private async void TextArea_TextEntered(object sender, TextCompositionEventArgs return; } - if (_completionWindow is not null && !ShouldKeepCompletionWindowOpen(e.Text)) + if (_completionWindow is not null) { - CloseCompletionWindow(); - return; + if (!ShouldKeepCompletionWindowOpen(e.Text)) + CloseCompletionWindow(); + else + { + ScheduleCloseIfEmpty(); + return; + } } if (!AutocompleteEnabled) return; - if (ShouldTriggerAutocomplete(e.Text)) - await RequestCompletionAsync(CaretOffset).ConfigureAwait(true); + if (TryGetCompletionTrigger(e.Text, out char? triggerCharacter) && IsValidAutocompleteContext(CaretOffset, triggerCharacter)) + await RequestCompletionAsync(CaretOffset, triggerCharacter).ConfigureAwait(true); } protected override async void HandleMouseHover(MouseEventArgs e) @@ -175,8 +198,23 @@ protected override async void HandleMouseHover(MouseEventArgs e) private bool IsIntellisenseAvailable() => IntellisenseProvider is not null && IntellisenseProvider.IsAvailable && !string.IsNullOrWhiteSpace(FilePath); - private static bool ShouldTriggerAutocomplete(string inputText) - => inputText == "." || inputText == ":"; + private static bool TryGetCompletionTrigger(string inputText, out char? triggerCharacter) + { + triggerCharacter = null; + + if (string.IsNullOrEmpty(inputText) || inputText.Length != 1) + return false; + + char typedChar = inputText[0]; + + if (typedChar == '.' || typedChar == ':') + { + triggerCharacter = typedChar; + return true; + } + + return IsIdentifierTriggerCharacter(typedChar); + } private static bool ShouldKeepCompletionWindowOpen(string inputText) => inputText?.Length == 1 && (char.IsLetterOrDigit(inputText[0]) || inputText[0] == '_'); @@ -190,8 +228,23 @@ private void CloseCompletionWindow() _completionWindow = null; } - private async Task RequestCompletionAsync(int offset) + private void InitializeLuaCompletionWindow() + { + InitializeCompletionWindow(420, 320); + LuaCompletionWindowStyle.Apply(_completionWindow); + StyleCompletionTooltip(); + MakeCompletionWindowNonActivatable(); + } + + private async Task RequestCompletionAsync(int offset, char? triggerCharacter) { + _completionCancellationTokenSource?.Cancel(); + _completionCancellationTokenSource?.Dispose(); + _completionCancellationTokenSource = new CancellationTokenSource(); + + CancellationToken cancellationToken = _completionCancellationTokenSource.Token; + int requestToken = ++_completionRequestToken; + try { if (!IsIntellisenseAvailable()) @@ -199,9 +252,12 @@ private async Task RequestCompletionAsync(int offset) (int line, int column) = GetPositionFromOffset(offset); var items = await IntellisenseProvider - .GetCompletionItemsAsync(FilePath, Text, line, column, CancellationToken.None) + .GetCompletionItemsAsync(FilePath, Text, line, column, triggerCharacter, cancellationToken) .ConfigureAwait(true); + if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + return; + if (items is null || items.Count == 0) { CloseCompletionWindow(); @@ -210,14 +266,17 @@ private async Task RequestCompletionAsync(int offset) CloseCompletionWindow(); - InitializeCompletionWindow(); + InitializeLuaCompletionWindow(); SetCompletionWindowOffsets(offset); foreach (LuaCompletionItem item in items) _completionWindow.CompletionList.CompletionData.Add(new LuaCompletionData(item)); if (_completionWindow.CompletionList.CompletionData.Count > 0) + { ShowCompletionWindow(); + ScheduleInitialSelection(); + } } catch { @@ -226,6 +285,161 @@ private async Task RequestCompletionAsync(int offset) } } + private bool IsValidAutocompleteContext(int offset, char? triggerCharacter) + { + if (offset <= 0 || Document is null) + return false; + + if (IsInsideCommentOrString(offset)) + return false; + + if (triggerCharacter is '.' || triggerCharacter is ':') + return true; + + char typedCharacter = Document.GetCharAt(offset - 1); + + if (!IsIdentifierCharacter(typedCharacter)) + return false; + + if (offset >= 2) + { + char previousCharacter = Document.GetCharAt(offset - 2); + + if (previousCharacter == '.') + return false; + } + + return true; + } + + private bool IsInsideCommentOrString(int offset) + { + DocumentLine currentLine = Document.GetLineByOffset(Math.Max(0, Math.Min(offset, Document.TextLength))); + int lineStart = currentLine.Offset; + int inspectedLength = Math.Max(0, Math.Min(offset, currentLine.EndOffset) - lineStart); + string lineText = Document.GetText(lineStart, inspectedLength); + + bool isInsideSingleQuotedString = false; + bool isInsideDoubleQuotedString = false; + bool isEscaped = false; + + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; + + if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && currentChar == '-' + && i + 1 < lineText.Length && lineText[i + 1] == '-') + { + return true; + } + + if (isEscaped) + { + isEscaped = false; + continue; + } + + if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\') + { + isEscaped = true; + continue; + } + + if (!isInsideDoubleQuotedString && currentChar == '\'') + isInsideSingleQuotedString = !isInsideSingleQuotedString; + else if (!isInsideSingleQuotedString && currentChar == '"') + isInsideDoubleQuotedString = !isInsideDoubleQuotedString; + } + + return isInsideSingleQuotedString || isInsideDoubleQuotedString; + } + + private static bool IsIdentifierCharacter(char character) + => char.IsLetterOrDigit(character) || character == '_'; + + private static bool IsIdentifierTriggerCharacter(char character) + => char.IsLetter(character) || character == '_'; + + private void StyleCompletionTooltip() + { + if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) + return; + + tooltip.Background = DefaultToolTipBackground; + tooltip.BorderBrush = DefaultToolTipBorder; + tooltip.BorderThickness = new Thickness(0.0); + tooltip.Padding = new Thickness(0.0); + } + + private void ScheduleCloseIfEmpty() + => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); + + private void ScheduleInitialSelection() + => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.ContextIdle); + + private void SelectInitialItem() + { + if (_completionWindow is null) + return; + + _completionWindow.CompletionList.SelectItem(GetCompletionWindowQuery()); + CloseCompletionWindowIfEmpty(); + } + + // AvalonEdit's CompletionWindowBase does not set WS_EX_NOACTIVATE, so clicking the + // completion list activates the popup window and steals keyboard focus from the editor. + // This hook returns MA_NOACTIVATE to prevent that while still allowing clicks through. + + private void MakeCompletionWindowNonActivatable() + { + _completionWindow.SourceInitialized += (s, e) => + { + if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) + source.AddHook(CompletionWindowWndProc); + }; + } + + private static IntPtr CompletionWindowWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + const int WM_MOUSEACTIVATE = 0x0021; + const int MA_NOACTIVATE = 3; + + if (msg == WM_MOUSEACTIVATE) + { + handled = true; + return new IntPtr(MA_NOACTIVATE); + } + + return IntPtr.Zero; + } + + private bool CloseCompletionWindowIfEmpty() + { + if (_completionWindow is null) + return false; + + var listBox = _completionWindow.CompletionList.ListBox; + + if (listBox is null || listBox.HasItems) + return false; + + CloseCompletionWindow(); + return true; + } + + private string GetCompletionWindowQuery() + { + if (_completionWindow is null || Document is null) + return string.Empty; + + int startOffset = Math.Max(0, Math.Min(_completionWindow.StartOffset, Document.TextLength)); + int endOffset = Math.Max(startOffset, Math.Min(_completionWindow.EndOffset, Document.TextLength)); + + return endOffset > startOffset + ? Document.GetText(startOffset, endOffset - startOffset) + : string.Empty; + } + private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) { if (!IsIntellisenseAvailable()) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs new file mode 100644 index 0000000000..76901fa95e --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs @@ -0,0 +1,31 @@ +using System.Collections.Generic; +using TombLib.Scripting.Lua.Highlighting; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua +{ + public sealed partial class LuaEditor + { + private LuaSemanticTokensColorizer _semanticTokensColorizer; + + public void SetSemanticTokens(IReadOnlyList tokens) + { + EnsureSemanticTokensColorizerAttached(); + _semanticTokensColorizer.SetTokens(tokens); + } + + public void ClearSemanticTokens() + => _semanticTokensColorizer?.ClearTokens(); + + private void EnsureSemanticTokensColorizerAttached() + { + if (_semanticTokensColorizer is null) + _semanticTokensColorizer = new LuaSemanticTokensColorizer(TextArea.TextView); + + if (TextArea.TextView.LineTransformers.Contains(_semanticTokensColorizer)) + TextArea.TextView.LineTransformers.Remove(_semanticTokensColorizer); + + TextArea.TextView.LineTransformers.Add(_semanticTokensColorizer); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index ea15cb1edc..2ae2eb9c97 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -5,6 +5,7 @@ using System.Windows.Media; using System.Xml; using TombLib.Scripting.Bases; +using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; @@ -14,6 +15,8 @@ public sealed partial class LuaEditor : TextEditorBase { public override string DefaultFileExtension => ".lua"; + private LuaTextMateInstallation _textMateHighlighting; + public ILuaIntellisenseProvider IntellisenseProvider { get; set; } public Action DefinitionNavigationRequested { get; set; } @@ -29,10 +32,21 @@ public override void UpdateSettings(Bases.ConfigurationBase configuration) var config = configuration as LuaEditorConfiguration; string xmlFile = Path.Combine(DefaultPaths.LuaColorConfigsDirectory, "Default.xml"); + _textMateHighlighting?.Dispose(); + _textMateHighlighting = null; + + if (!LuaTextMateSyntaxHighlighting.TryInstall(this, out _textMateHighlighting)) + { + using (var stream = new FileStream(xmlFile, FileMode.Open, FileAccess.Read)) + using (var reader = new XmlTextReader(stream)) + SyntaxHighlighting = HighlightingLoader.Load(reader, HighlightingManager.Instance); + } + else + { + SyntaxHighlighting = null; + } - using (var stream = new FileStream(xmlFile, FileMode.Open, FileAccess.Read)) - using (var reader = new XmlTextReader(stream)) - SyntaxHighlighting = HighlightingLoader.Load(reader, HighlightingManager.Instance); + EnsureSemanticTokensColorizerAttached(); Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#202020")); Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("White")); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index 30861220eb..b0ad117771 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -1,25 +1,124 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; -using System; -using System.Windows.Media; +using TombLib.Scripting.Rendering; namespace TombLib.Scripting.Lua.Objects { public sealed class LuaCompletionData : ICompletionData { + private const double DescriptionMaxWidth = 540.0; + private const double DescriptionTextMaxWidth = 500.0; + private static readonly SolidColorBrush DescriptionBorderBrush = CreateFrozenBrush(Color.FromRgb(96, 96, 96)); + private static readonly SolidColorBrush DescriptionBackgroundBrush = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); + private static readonly SolidColorBrush DescriptionForegroundBrush = CreateFrozenBrush(Colors.Gainsboro); private readonly LuaCompletionItem _item; + private readonly string _displayDetail; + private object _cachedDescription; public LuaCompletionData(LuaCompletionItem item) - => _item = item ?? throw new ArgumentNullException(nameof(item)); + { + _item = item ?? throw new ArgumentNullException(nameof(item)); + _displayDetail = FlattenSingleLineText(_item.Detail); + } - public ImageSource Image => null; - public string Text => _item.Label; - public object Content => _item.Label; - public object Description => _item.Description; - public double Priority => 0; + public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind); + public string Text => _item.FilterText; + public string DisplayText => _item.Label; + public string DisplayDetail => _displayDetail; + public Visibility DetailVisibility => string.IsNullOrEmpty(_displayDetail) ? Visibility.Collapsed : Visibility.Visible; + public object Content => DisplayText; + public object Description => _cachedDescription ??= BuildDescriptionContent(); + public double Priority => _item.Priority; public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) => textArea.Document.Replace(completionSegment, _item.InsertText); + + private static string FlattenSingleLineText(string text) + { + if (string.IsNullOrWhiteSpace(text)) + return null; + + string[] lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + return lines.Length == 0 ? null : string.Join(" ", lines).Trim(); + } + + private object BuildDescriptionContent() + { + bool hasDetail = !string.IsNullOrWhiteSpace(_item.Detail); + bool hasDescription = !string.IsNullOrWhiteSpace(_item.Description); + + if (!hasDetail && !hasDescription) + return null; + + var panel = new StackPanel + { + MaxWidth = DescriptionMaxWidth + }; + + if (hasDetail) + { + panel.Children.Add(new TextBlock + { + Text = _item.Detail, + Foreground = DescriptionForegroundBrush, + TextWrapping = TextWrapping.Wrap, + MaxWidth = DescriptionTextMaxWidth, + FontWeight = FontWeights.SemiBold, + Margin = hasDescription + ? new Thickness(0.0, 0.0, 0.0, 8.0) + : new Thickness(0.0) + }); + } + + if (hasDescription) + { + panel.Children.Add(_item.IsDescriptionMarkdown + ? MarkdownToolTipRenderer.CreateContent(_item.Description, DescriptionForegroundBrush, DescriptionBackgroundBrush) + : CreatePlainDescriptionContent(_item.Description)); + } + + return new Border + { + Background = DescriptionBackgroundBrush, + BorderBrush = DescriptionBorderBrush, + BorderThickness = new Thickness(1.0), + Padding = new Thickness(8.0, 6.0, 8.0, 6.0), + Child = panel, + MaxWidth = DescriptionMaxWidth + }; + } + + private static FrameworkElement CreatePlainDescriptionContent(string text) + { + var textBlock = new TextBlock + { + Text = text, + Foreground = DescriptionForegroundBrush, + TextWrapping = TextWrapping.Wrap, + MaxWidth = DescriptionTextMaxWidth + }; + + return new ScrollViewer + { + Content = textBlock, + MaxHeight = 420.0, + MaxWidth = DescriptionMaxWidth, + VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, + CanContentScroll = true + }; + } + + private static SolidColorBrush CreateFrozenBrush(Color color) + { + var brush = new SolidColorBrush(color); + brush.Freeze(); + return brush; + } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs new file mode 100644 index 0000000000..023bb6a7b9 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -0,0 +1,144 @@ +using System.Collections.Generic; +using System.Windows.Media; + +namespace TombLib.Scripting.Lua.Objects +{ + // Geometry paths below are vendored from microsoft/vscode-codicons under the MIT license. + internal static class LuaCompletionIconFactory + { + private static readonly Brush MiscBrush = CreateFrozenBrush("#C8C8C8"); + private static readonly Brush MethodBrush = CreateFrozenBrush("#DCDCAA"); + private static readonly Brush VariableBrush = CreateFrozenBrush("#9CDCFE"); + private static readonly Brush PropertyBrush = CreateFrozenBrush("#4FC1FF"); + private static readonly Brush TypeBrush = CreateFrozenBrush("#4EC9B0"); + private static readonly Brush KeywordBrush = CreateFrozenBrush("#C586C0"); + private static readonly Brush ConstantBrush = CreateFrozenBrush("#B5CEA8"); + private static readonly Brush FileBrush = CreateFrozenBrush("#D7BA7D"); + private static readonly Dictionary Cache = new Dictionary(); + + public static ImageSource GetIcon(LuaCompletionIconKind kind) + { + lock (Cache) + { + if (Cache.TryGetValue(kind, out ImageSource image)) + return image; + + image = CreateIcon(kind); + Cache[kind] = image; + return image; + } + } + + private static ImageSource CreateIcon(LuaCompletionIconKind kind) + { + var drawingGroup = new DrawingGroup(); + + foreach (string pathData in GetPathData(kind)) + drawingGroup.Children.Add(CreatePathDrawing(GetBrush(kind), pathData)); + + drawingGroup.Freeze(); + + var image = new DrawingImage(drawingGroup); + image.Freeze(); + return image; + } + + private static GeometryDrawing CreatePathDrawing(Brush brush, string pathData) + { + Geometry geometry = Geometry.Parse(pathData); + geometry.Freeze(); + return new GeometryDrawing(brush, null, geometry); + } + + private static Brush GetBrush(LuaCompletionIconKind kind) + { + return kind switch + { + LuaCompletionIconKind.Variable => VariableBrush, + LuaCompletionIconKind.Field => PropertyBrush, + LuaCompletionIconKind.Method => MethodBrush, + LuaCompletionIconKind.Property => PropertyBrush, + LuaCompletionIconKind.Class => TypeBrush, + LuaCompletionIconKind.Keyword => KeywordBrush, + LuaCompletionIconKind.Constant => ConstantBrush, + LuaCompletionIconKind.Parameter => VariableBrush, + LuaCompletionIconKind.Namespace => TypeBrush, + LuaCompletionIconKind.File => FileBrush, + LuaCompletionIconKind.Folder => FileBrush, + _ => MiscBrush + }; + } + + private static string[] GetPathData(LuaCompletionIconKind kind) + { + return kind switch + { + LuaCompletionIconKind.Variable => new[] + { + "M11.279 5.78975L8.799 5.06575C8.59 5.00575 8.372 5.01475 8.168 5.08975L4.648 6.40975C4.26 6.55575 4 6.93175 4 7.34675V9.13975C4 9.57075 4.274 9.95175 4.684 10.0877L7.165 10.9147C7.268 10.9497 7.376 10.9667 7.483 10.9667C7.611 10.9667 7.739 10.9427 7.859 10.8937L11.376 9.46475C11.755 9.31175 12 8.94775 12 8.53875V6.74975C12 6.30775 11.703 5.91275 11.279 5.78975ZM11 8.53875L7.483 9.96775L5 9.13975V7.34675L8.521 6.02675L11 6.75075V8.53975V8.53875ZM7.48 7.46675L8.807 6.91375C9.06 6.80875 9.355 6.92775 9.461 7.18275C9.566 7.43775 9.446 7.73075 9.191 7.83675L7.999 8.33375V8.62575C7.999 8.90175 7.775 9.12575 7.499 9.12575C7.223 9.12575 6.999 8.90175 6.999 8.62575V8.36075L6.591 8.22475C6.329 8.13775 6.188 7.85475 6.275 7.59275C6.364 7.33075 6.647 7.19175 6.908 7.27675L7.48 7.46675Z", + "M12.5 14H11.5C11.224 14 11 13.776 11 13.5C11 13.224 11.224 13 11.5 13H12.5C12.776 13 13 12.775 13 12.5V3.5C13 3.225 12.776 3 12.5 3H11.5C11.224 3 11 2.776 11 2.5C11 2.224 11.224 2 11.5 2H12.5C13.327 2 14 2.673 14 3.5V12.5C14 13.327 13.327 14 12.5 14ZM5 13.5C5 13.224 4.776 13 4.5 13H3.5C3.224 13 3 12.775 3 12.5V3.5C3 3.225 3.224 3 3.5 3H4.5C4.776 3 5 2.776 5 2.5C5 2.224 4.776 2 4.5 2H3.5C2.673 2 2 2.673 2 3.5V12.5C2 13.327 2.673 14 3.5 14H4.5C4.776 14 5 13.776 5 13.5Z" + }, + LuaCompletionIconKind.Field => new[] + { + "M11.967 6.08899C11.9907 6.15031 12.0021 6.2157 12.0005 6.28143C11.9989 6.34715 11.9843 6.41191 11.9577 6.47201C11.931 6.5321 11.8928 6.58635 11.8451 6.63165C11.7975 6.67695 11.7414 6.7124 11.68 6.73599L7.5 8.34399V10.02C7.5 10.1526 7.44732 10.2798 7.35355 10.3735C7.25979 10.4673 7.13261 10.52 7 10.52C6.86739 10.52 6.74021 10.4673 6.64645 10.3735C6.55268 10.2798 6.5 10.1526 6.5 10.02V8.34299L4.32 7.50499C4.25874 7.48135 4.20273 7.44588 4.15518 7.40059C4.10763 7.35531 4.06946 7.30111 4.04286 7.24107C4.01625 7.18104 4.00173 7.11635 4.00013 7.05071C3.99852 6.98507 4.00986 6.91975 4.0335 6.85849C4.05714 6.79722 4.09261 6.74122 4.13789 6.69367C4.18318 6.64611 4.23738 6.60795 4.29741 6.58134C4.35745 6.55474 4.42213 6.54022 4.48778 6.53861C4.55342 6.53701 4.61874 6.54835 4.68 6.57199L7 7.46399L11.32 5.79999C11.3814 5.77634 11.447 5.76505 11.5128 5.76678C11.5786 5.76852 11.6434 5.78323 11.7035 5.81008C11.7636 5.83694 11.8179 5.8754 11.8631 5.92326C11.9083 5.97112 11.9436 6.02744 11.967 6.08899ZM15 5.79999V9.42899C14.9986 9.73191 14.9061 10.0274 14.7345 10.2771C14.563 10.5268 14.3203 10.7191 14.038 10.829L7.538 13.329C7.19108 13.4626 6.80692 13.4626 6.46 13.329L1.961 11.6C1.67891 11.4899 1.43643 11.2975 1.26506 11.0479C1.09369 10.7982 1.00134 10.5028 1 10.2V6.57099C1.00155 6.26809 1.0941 5.97265 1.26565 5.72301C1.43719 5.47336 1.6798 5.28104 1.962 5.17099L8.462 2.67099C8.80902 2.53798 9.19298 2.53798 9.54 2.67099L14.04 4.40199C14.3215 4.51223 14.5635 4.70438 14.7346 4.95361C14.9058 5.20283 14.9982 5.49766 15 5.79999ZM14 5.79999C14 5.69881 13.9694 5.6 13.912 5.51662C13.8547 5.43324 13.7735 5.36921 13.679 5.33299L9.179 3.60299C9.06398 3.55763 8.93602 3.55763 8.821 3.60299L2.321 6.10299C2.22637 6.13927 2.145 6.20345 2.08767 6.28703C2.03034 6.37061 1.99977 6.46964 2 6.57099V10.2C2.0001 10.3009 2.03071 10.3994 2.08782 10.4825C2.14494 10.5657 2.22587 10.6297 2.32 10.666L6.82 12.398C6.93524 12.4422 7.06276 12.4422 7.178 12.398L13.678 9.89799C13.773 9.8618 13.8547 9.79754 13.9122 9.71375C13.9697 9.62996 14.0004 9.53062 14 9.42899V5.79999Z" + }, + LuaCompletionIconKind.Method => new[] + { + "M4.69684 5.04043C4.44303 4.93166 4.14909 5.04923 4.04031 5.30305C3.93153 5.55686 4.04911 5.8508 4.30292 5.95958L7.49988 7.3297V10.5C7.49988 10.7761 7.72374 11 7.99988 11C8.27603 11 8.49988 10.7761 8.49988 10.5V7.3297L11.6968 5.95958C11.9507 5.8508 12.0682 5.55686 11.9595 5.30305C11.8507 5.04923 11.5567 4.93166 11.3029 5.04043L7.99988 6.45602L4.69684 5.04043ZM9.07694 1.37855C8.38373 1.11193 7.61627 1.11193 6.92306 1.37855L1.96153 3.28683C1.38224 3.50964 1 4.06619 1 4.68685V11.3133C1 11.9339 1.38224 12.4905 1.96153 12.7133L6.92306 14.6216C7.61627 14.8882 8.38373 14.8882 9.07694 14.6216L14.0385 12.7133C14.6178 12.4905 15 11.9339 15 11.3133V4.68685C15 4.06619 14.6178 3.50964 14.0385 3.28683L9.07694 1.37855ZM7.28204 2.3119C7.74418 2.13415 8.25582 2.13415 8.71796 2.3119L13.6795 4.22018C13.8726 4.29445 14 4.47997 14 4.68685V11.3133C14 11.5201 13.8726 11.7057 13.6795 11.7799L8.71796 13.6882C8.25582 13.866 7.74418 13.866 7.28204 13.6882L2.32051 11.7799C2.12741 11.7057 2 11.5201 2 11.3133V4.68685C2 4.47997 2.12741 4.29445 2.32051 4.22018L7.28204 2.3119Z" + }, + LuaCompletionIconKind.Property => new[] + { + "M6.99989 5C6.99989 2.79086 8.79075 1 10.9999 1C11.5087 1 11.9964 1.09524 12.4454 1.26931C12.603 1.3304 12.719 1.46698 12.7539 1.63235C12.7888 1.79773 12.7377 1.96953 12.6182 2.08904L10.7072 4.00012L12.0001 5.29302L13.911 3.38207C14.0305 3.26254 14.2023 3.2115 14.3677 3.24637C14.5331 3.28125 14.6697 3.39732 14.7307 3.55493C14.9047 4.0038 14.9999 4.49138 14.9999 5C14.9999 7.20914 13.209 9 10.9999 9C10.6198 9 10.2514 8.94684 9.90215 8.84736L4.89566 13.9192C4.18171 14.6425 3.03692 14.7101 2.24289 14.0757C1.32876 13.3455 1.24088 11.9872 2.05327 11.1453L7.10411 5.91061C7.03588 5.61771 6.99989 5.31279 6.99989 5ZM10.9999 2C9.34303 2 7.99989 3.34315 7.99989 5C7.99989 5.31548 8.04841 5.61868 8.13805 5.90305C8.19313 6.07781 8.14821 6.26869 8.02099 6.40054L2.7729 11.8396C2.3696 12.2576 2.41323 12.9319 2.86703 13.2944C3.26123 13.6093 3.82955 13.5758 4.18398 13.2167L9.40817 7.9243C9.54702 7.78364 9.75569 7.73797 9.9406 7.80777C10.2693 7.93186 10.6261 8 10.9999 8C12.6567 8 13.9999 6.65685 13.9999 5C13.9999 4.9056 13.9955 4.81228 13.987 4.72023L12.3537 6.35368C12.2599 6.44745 12.1327 6.50013 12.0001 6.50013C11.8675 6.50013 11.7403 6.44745 11.6466 6.35368L9.64655 4.35368C9.45129 4.15842 9.45129 3.84185 9.64655 3.64658L11.2802 2.01289C11.188 2.00436 11.0945 2 10.9999 2Z" + }, + LuaCompletionIconKind.Class => new[] + { + "M13.2069 10.4999C13.0194 10.3125 12.7651 10.2072 12.4999 10.2072C12.2348 10.2072 11.9805 10.3125 11.7929 10.4999L11.2929 10.9999H8.99994V6.99994H10.3629C10.2479 7.1876 10.1989 7.40832 10.2238 7.62701C10.2486 7.84571 10.3458 8.04983 10.4999 8.20694L11.2929 8.99994C11.4805 9.18741 11.7348 9.29273 11.9999 9.29273C12.2651 9.29273 12.5194 9.18741 12.7069 8.99994L13.9999 7.70694C14.1874 7.51941 14.2927 7.2651 14.2927 6.99994C14.2927 6.73478 14.1874 6.48047 13.9999 6.29294L13.2069 5.49994C13.0194 5.31247 12.7651 5.20715 12.4999 5.20715C12.2348 5.20715 11.9805 5.31247 11.7929 5.49994L11.2929 5.99994H6.70694L7.49994 5.20694C7.68741 5.01941 7.79273 4.7651 7.79273 4.49994C7.79273 4.23478 7.68741 3.98047 7.49994 3.79294L6.20694 2.49994C6.01941 2.31247 5.7651 2.20715 5.49994 2.20715C5.23478 2.20715 4.98047 2.31247 4.79294 2.49994L1.49994 5.79294C1.31247 5.98047 1.20715 6.23478 1.20715 6.49994C1.20715 6.7651 1.31247 7.01941 1.49994 7.20694L2.79294 8.49994C2.98047 8.68741 3.23478 8.79273 3.49994 8.79273C3.7651 8.79273 4.01941 8.68741 4.20694 8.49994L5.70694 6.99994H7.99994V11.4999C7.99994 11.6325 8.05262 11.7597 8.14639 11.8535C8.24015 11.9473 8.36733 11.9999 8.49994 11.9999H10.3629C10.2479 12.1876 10.1989 12.4083 10.2238 12.627C10.2486 12.8457 10.3458 13.0498 10.4999 13.2069L11.2929 13.9999C11.4805 14.1874 11.7348 14.2927 11.9999 14.2927C12.2651 14.2927 12.5194 14.1874 12.7069 13.9999L13.9999 12.7069C14.1874 12.5194 14.2927 12.2651 14.2927 11.9999C14.2927 11.7348 14.1874 11.4805 13.9999 11.2929L13.2069 10.4999ZM3.49994 7.79294L2.20694 6.49994L5.49994 3.20694L6.79294 4.49994L3.49994 7.79294ZM13.2929 6.99994L11.9999 8.29294L11.2069 7.49994L12.4999 6.20694L13.2929 6.99994ZM11.9999 13.2929L11.2069 12.4999L12.4999 11.2069L13.2929 11.9999L11.9999 13.2929Z" + }, + LuaCompletionIconKind.Keyword => new[] + { + "M9.5 14C9.77614 14 10 14.2239 10 14.5C10 14.7761 9.77614 15 9.5 15H2.5C2.22386 15 2 14.7761 2 14.5C2 14.2239 2.22386 14 2.5 14H9.5Z", + "M6.5 11C6.77614 11 7 11.2239 7 11.5C7 11.7761 6.77614 12 6.5 12H2.5C2.22386 12 2 11.7761 2 11.5C2 11.2239 2.22386 11 2.5 11H6.5Z", + "M13.5 11C13.7761 11 14 11.2239 14 11.5C14 11.7761 13.7761 12 13.5 12H8.5C8.22386 12 8 11.7761 8 11.5C8 11.2239 8.22386 11 8.5 11H13.5Z", + "M8.5 8C8.77614 8 9 8.22386 9 8.5C9 8.77614 8.77614 9 8.5 9H2.5C2.22386 9 2 8.77614 2 8.5C2 8.22386 2.22386 8 2.5 8H8.5Z", + "M13.5 8C13.7761 8 14 8.22386 14 8.5C14 8.77614 13.7761 9 13.5 9H10.5C10.2239 9 10 8.77614 10 8.5C10 8.22386 10.2239 8 10.5 8H13.5Z", + "M9 2C9.55228 2 10 2.44772 10 3V5C10 5.55228 9.55228 6 9 6H3C2.44772 6 2 5.55228 2 5V3C2 2.44772 2.44772 2 3 2H9ZM3 5H9V3H3V5Z", + "M13.5 4C13.7761 4 14 4.22386 14 4.5C14 4.77614 13.7761 5 13.5 5H11.5C11.2239 5 11 4.77614 11 4.5C11 4.22386 11.2239 4 11.5 4H13.5Z" + }, + LuaCompletionIconKind.Constant => new[] + { + "M4.5 2C3.83696 2 3.20107 2.26339 2.73223 2.73223C2.26339 3.20107 2 3.83696 2 4.5V11.5C2 12.163 2.26339 12.7989 2.73223 13.2678C3.20107 13.7366 3.83696 14 4.5 14H11.5C12.163 14 12.7989 13.7366 13.2678 13.2678C13.7366 12.7989 14 12.163 14 11.5V4.5C14 3.83696 13.7366 3.20107 13.2678 2.73223C12.7989 2.26339 12.163 2 11.5 2H4.5ZM3 4.5C3 4.10218 3.15804 3.72064 3.43934 3.43934C3.72064 3.15804 4.10218 3 4.5 3H11.5C11.8978 3 12.2794 3.15804 12.5607 3.43934C12.842 3.72064 13 4.10218 13 4.5V11.5C13 11.8978 12.842 12.2794 12.5607 12.5607C12.2794 12.842 11.8978 13 11.5 13H4.5C4.10218 13 3.72064 12.842 3.43934 12.5607C3.15804 12.2794 3 11.8978 3 11.5V4.5Z", + "M5 6.5C5 6.36739 5.05268 6.24021 5.14645 6.14645C5.24021 6.05268 5.36739 6 5.5 6H10.5C10.6326 6 10.7598 6.05268 10.8536 6.14645C10.9473 6.24021 11 6.36739 11 6.5C11 6.63261 10.9473 6.75979 10.8536 6.85355C10.7598 6.94732 10.6326 7 10.5 7H5.5C5.36739 7 5.24021 6.94732 5.14645 6.85355C5.05268 6.75979 5 6.63261 5 6.5ZM10.5 9H5.5C5.36739 9 5.24021 9.05268 5.14645 9.14645C5.05268 9.24021 5 9.36739 5 9.5C5 9.63261 5.05268 9.75979 5.14645 9.85355C5.24021 9.94732 5.36739 10 5.5 10H10.5C10.6326 10 10.7598 9.94732 10.8536 9.85355C10.9473 9.75979 11 9.63261 11 9.5C11 9.36739 10.9473 9.24021 10.8536 9.14645C10.7598 9.05268 10.6326 9 10.5 9Z" + }, + LuaCompletionIconKind.Parameter => new[] + { + "M4 3.5C4 3.22386 4.22386 3 4.5 3H11.5C11.7761 3 12 3.22386 12 3.5V4.5C12 4.77614 11.7761 5 11.5 5C11.2239 5 11 4.77614 11 4.5V4H8.5V12H9C9.27614 12 9.5 12.2239 9.5 12.5C9.5 12.7761 9.27614 13 9 13H7C6.72386 13 6.5 12.7761 6.5 12.5C6.5 12.2239 6.72386 12 7 12H7.5V4H5V4.5C5 4.77614 4.77614 5 4.5 5C4.22386 5 4 4.77614 4 4.5V3.5ZM4.35355 6.64645C4.54882 6.84171 4.54882 7.15829 4.35355 7.35355L2.20711 9.5L4.35355 11.6464C4.54882 11.8417 4.54882 12.1583 4.35355 12.3536C4.15829 12.5488 3.84171 12.5488 3.64645 12.3536L1.14645 9.85355C0.951184 9.65829 0.951184 9.34171 1.14645 9.14645L3.64645 6.64645C3.84171 6.45118 4.15829 6.45118 4.35355 6.64645ZM14.8536 9.14645L12.3536 6.64645C12.1583 6.45118 11.8417 6.45118 11.6464 6.64645C11.4512 6.84171 11.4512 7.15829 11.6464 7.35355L13.7929 9.5L11.6464 11.6464C11.4512 11.8417 11.4512 12.1583 11.6464 12.3536C11.8417 12.5488 12.1583 12.5488 12.3536 12.3536L14.8536 9.85355C15.0488 9.65829 15.0488 9.34171 14.8536 9.14645Z" + }, + LuaCompletionIconKind.Namespace => new[] + { + "M5 2C3.89543 2 3 2.89543 3 4V6.00469C3 6.53494 2.99231 6.79889 2.91088 7.00209C2.84826 7.15835 2.71576 7.33309 2.2764 7.55276C2.10701 7.63745 2 7.81058 2 7.99997C2 8.18935 2.10699 8.36249 2.27638 8.44719C2.71569 8.66685 2.84809 8.84151 2.91076 8.99819C2.99233 9.20211 3 9.46732 3 10L3 12C3 13.1046 3.89543 14 5 14C5.27614 14 5.5 13.7761 5.5 13.5C5.5 13.2239 5.27614 13 5 13C4.44772 13 4 12.5523 4 12L4.00003 9.94145C4.00033 9.49235 4.00065 9.03033 3.83924 8.6268C3.74212 8.384 3.59654 8.17962 3.40072 8.00002C3.59646 7.82057 3.74199 7.61645 3.83912 7.37408C4.00065 6.971 4.00033 6.51001 4.00003 6.063L4 4C4 3.44772 4.44772 3 5 3C5.27614 3 5.5 2.77614 5.5 2.5C5.5 2.22386 5.27614 2 5 2ZM11 2C12.1046 2 13 2.89543 13 4V6.00469C13 6.53494 13.0077 6.79889 13.0891 7.00209C13.1517 7.15835 13.2842 7.33309 13.7236 7.55276C13.893 7.63745 14 7.81058 14 7.99997C14 8.18935 13.893 8.36249 13.7236 8.44719C13.2843 8.66685 13.1519 8.84151 13.0892 8.99819C13.0077 9.20211 13 9.46732 13 10V12C13 13.1046 12.1046 14 11 14C10.7239 14 10.5 13.7761 10.5 13.5C10.5 13.2239 10.7239 13 11 13C11.5523 13 12 12.5523 12 12L12 9.94145C11.9997 9.49235 11.9994 9.03033 12.1608 8.6268C12.2579 8.384 12.4035 8.17962 12.5993 8.00002C12.4035 7.82057 12.258 7.61645 12.1609 7.37408C11.9993 6.971 11.9997 6.51001 12 6.063L12 4C12 3.44772 11.5523 3 11 3C10.7239 3 10.5 2.77614 10.5 2.5C10.5 2.22386 10.7239 2 11 2Z" + }, + LuaCompletionIconKind.File => new[] + { + "M5 1C3.89543 1 3 1.89543 3 3V13C3 14.1046 3.89543 15 5 15H11C12.1046 15 13 14.1046 13 13V5.41421C13 5.01639 12.842 4.63486 12.5607 4.35355L9.64645 1.43934C9.36514 1.15804 8.98361 1 8.58579 1H5ZM4 3C4 2.44772 4.44772 2 5 2H8V4.5C8 5.32843 8.67157 6 9.5 6H12V13C12 13.5523 11.5523 14 11 14H5C4.44772 14 4 13.5523 4 13V3ZM11.7929 5H9.5C9.22386 5 9 4.77614 9 4.5V2.20711L11.7929 5Z" + }, + LuaCompletionIconKind.Folder => new[] + { + "M2 4.5V6H5.58579C5.71839 6 5.84557 5.94732 5.93934 5.85355L7.29289 4.5L5.93934 3.14645C5.84557 3.05268 5.71839 3 5.58579 3H3.5C2.67157 3 2 3.67157 2 4.5ZM1 4.5C1 3.11929 2.11929 2 3.5 2H5.58579C5.98361 2 6.36514 2.15804 6.64645 2.43934L8.20711 4H12.5C13.8807 4 15 5.11929 15 6.5V11.5C15 12.8807 13.8807 14 12.5 14H3.5C2.11929 14 1 12.8807 1 11.5V4.5ZM2 7V11.5C2 12.3284 2.67157 13 3.5 13H12.5C13.3284 13 14 12.3284 14 11.5V6.5C14 5.67157 13.3284 5 12.5 5H8.20711L6.64645 6.56066C6.36514 6.84197 5.98361 7 5.58579 7H2Z" + }, + _ => new[] + { + "M11.9999 3C10.1399 3 8.56988 4.27 8.12988 6H9.17988C9.58988 4.84 10.6999 4 11.9999 4C13.6499 4 14.9999 5.35 14.9999 7C14.9999 8.3 14.1599 9.41 12.9999 9.82V10.87C14.7299 10.43 15.9999 8.86 15.9999 7C15.9999 4.79 14.2099 3 11.9999 3Z", + "M10.5 15H5.5C4.673 15 4 14.327 4 13.5V8.5C4 7.673 4.673 7 5.5 7H10.5C11.327 7 12 7.673 12 8.5V13.5C12 14.327 11.327 15 10.5 15ZM5.5 8C5.224 8 5 8.225 5 8.5V13.5C5 13.775 5.224 14 5.5 14H10.5C10.776 14 11 13.775 11 13.5V8.5C11 8.225 10.776 8 10.5 8H5.5Z", + "M4.42973 2.25008C4.24973 1.94008 3.74973 1.94008 3.56973 2.25008L0.0997266 8.25008C0.00972656 8.40008 0.00972656 8.60008 0.0997266 8.75008C0.189727 8.90008 0.359727 9.00008 0.539727 9.00008H2.99973V8.50008C2.99973 8.33008 3.01973 8.16008 3.04973 8.00008H1.39973L3.99973 3.50008L5.44973 6.00008H6.59973L4.42973 2.25008Z" + } + }; + } + + private static SolidColorBrush CreateFrozenBrush(string colorValue) + { + var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); + brush.Freeze(); + return brush; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs new file mode 100644 index 0000000000..b524cc3f0f --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs @@ -0,0 +1,18 @@ +namespace TombLib.Scripting.Lua.Objects +{ + public enum LuaCompletionIconKind + { + Misc, + Variable, + Field, + Method, + Property, + Class, + Keyword, + Constant, + Parameter, + Namespace, + File, + Folder + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index 08bf9bc2a7..13367fdaa5 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -4,15 +4,36 @@ namespace TombLib.Scripting.Lua.Objects { public sealed class LuaCompletionItem { - public LuaCompletionItem(string label, string insertText = null, string description = null) + public LuaCompletionItem( + string label, + string insertText = null, + string detail = null, + string description = null, + string filterText = null, + double priority = 0.0, + LuaCompletionItemKind kind = LuaCompletionItemKind.Text, + LuaCompletionIconKind iconKind = LuaCompletionIconKind.Misc, + bool isDescriptionMarkdown = false) { Label = label ?? throw new ArgumentNullException(nameof(label)); InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; - Description = description; + Detail = string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); + Description = string.IsNullOrWhiteSpace(description) ? null : description.Trim(); + FilterText = string.IsNullOrWhiteSpace(filterText) ? label : filterText; + Priority = priority; + Kind = kind; + IconKind = iconKind; + IsDescriptionMarkdown = isDescriptionMarkdown; } public string Label { get; } public string InsertText { get; } + public string Detail { get; } public string Description { get; } + public string FilterText { get; } + public double Priority { get; } + public LuaCompletionItemKind Kind { get; } + public LuaCompletionIconKind IconKind { get; } + public bool IsDescriptionMarkdown { get; } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs new file mode 100644 index 0000000000..cacd86e4b4 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs @@ -0,0 +1,31 @@ +namespace TombLib.Scripting.Lua.Objects +{ + public enum LuaCompletionItemKind + { + Text = 1, + Method = 2, + Function = 3, + Constructor = 4, + Field = 5, + Variable = 6, + Class = 7, + Interface = 8, + Module = 9, + Property = 10, + Unit = 11, + Value = 12, + Enum = 13, + Keyword = 14, + Snippet = 15, + Color = 16, + File = 17, + Reference = 18, + Folder = 19, + EnumMember = 20, + Constant = 21, + Struct = 22, + Event = 23, + Operator = 24, + TypeParameter = 25 + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs new file mode 100644 index 0000000000..0ced1c67cd --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs @@ -0,0 +1,90 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; +using ICSharpCode.AvalonEdit.CodeCompletion; + +namespace TombLib.Scripting.Lua.Objects +{ + internal static class LuaCompletionWindowStyle + { + private static readonly Brush DetailBrush = CreateFrozenBrush("#8C8C8C"); + private static readonly DataTemplate ItemTemplate = CreateItemTemplate(); + private static readonly Style ItemContainerStyle = CreateItemContainerStyle(); + + public static void Apply(CompletionWindow window) + { + if (window is null) + return; + + window.FontFamily = window.TextArea.FontFamily; + window.FontSize = window.TextArea.FontSize; + window.CompletionList.HorizontalContentAlignment = HorizontalAlignment.Stretch; + window.CompletionList.ListBox.HorizontalContentAlignment = HorizontalAlignment.Stretch; + window.CompletionList.ListBox.BorderThickness = new Thickness(0.0); + window.CompletionList.ListBox.Focusable = false; + window.CompletionList.ListBox.IsTabStop = false; + window.CompletionList.ListBox.FontFamily = window.TextArea.FontFamily; + window.CompletionList.ListBox.FontSize = window.TextArea.FontSize; + window.CompletionList.ListBox.ItemTemplate = ItemTemplate; + window.CompletionList.ListBox.ItemContainerStyle = ItemContainerStyle; + window.Width = 420.0; + window.Height = 320.0; + } + + private static DataTemplate CreateItemTemplate() + { + var template = new DataTemplate(typeof(LuaCompletionData)); + + var panel = new FrameworkElementFactory(typeof(DockPanel)); + panel.SetValue(DockPanel.LastChildFillProperty, true); + + var icon = new FrameworkElementFactory(typeof(Image)); + icon.SetValue(DockPanel.DockProperty, Dock.Left); + icon.SetValue(FrameworkElement.WidthProperty, 16.0); + icon.SetValue(FrameworkElement.HeightProperty, 16.0); + icon.SetValue(FrameworkElement.MarginProperty, new Thickness(0.0, 0.0, 8.0, 0.0)); + icon.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); + icon.SetBinding(Image.SourceProperty, new Binding(nameof(LuaCompletionData.Image))); + + var detail = new FrameworkElementFactory(typeof(TextBlock)); + detail.SetValue(DockPanel.DockProperty, Dock.Right); + detail.SetValue(TextBlock.ForegroundProperty, DetailBrush); + detail.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); + detail.SetValue(FrameworkElement.MaxWidthProperty, 220.0); + detail.SetValue(FrameworkElement.MarginProperty, new Thickness(12.0, 0.0, 0.0, 0.0)); + detail.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); + detail.SetBinding(TextBlock.TextProperty, new Binding(nameof(LuaCompletionData.DisplayDetail))); + detail.SetBinding(UIElement.VisibilityProperty, new Binding(nameof(LuaCompletionData.DetailVisibility))); + + var label = new FrameworkElementFactory(typeof(TextBlock)); + label.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); + label.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); + label.SetBinding(TextBlock.TextProperty, new Binding(nameof(LuaCompletionData.DisplayText))); + + panel.AppendChild(icon); + panel.AppendChild(detail); + panel.AppendChild(label); + + template.VisualTree = panel; + return template; + } + + private static Style CreateItemContainerStyle() + { + var style = new Style(typeof(ListBoxItem)); + style.Setters.Add(new Setter(UIElement.FocusableProperty, false)); + style.Setters.Add(new Setter(Control.PaddingProperty, new Thickness(8.0, 3.0, 8.0, 3.0))); + style.Setters.Add(new Setter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)); + style.Setters.Add(new Setter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Center)); + return style; + } + + private static SolidColorBrush CreateFrozenBrush(string colorValue) + { + var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); + brush.Freeze(); + return brush; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs new file mode 100644 index 0000000000..e92f84e034 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; + +namespace TombLib.Scripting.Lua.Objects +{ + public sealed class LuaSemanticToken + { + public LuaSemanticToken(int line, int character, int length, string type, IReadOnlyList modifiers) + { + Line = Math.Max(0, line); + Character = Math.Max(0, character); + Length = Math.Max(0, length); + Type = type ?? string.Empty; + Modifiers = modifiers ?? Array.Empty(); + } + + public int Line { get; } + public int Character { get; } + public int Length { get; } + public string Type { get; } + public IReadOnlyList Modifiers { get; } + + public bool HasModifier(string modifier) + { + if (string.IsNullOrWhiteSpace(modifier) || Modifiers.Count == 0) + return false; + + for (int i = 0; i < Modifiers.Count; i++) + { + if (string.Equals(Modifiers[i], modifier, StringComparison.Ordinal)) + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs index efe42780ed..15931cdd9a 100644 --- a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs +++ b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs @@ -11,15 +11,17 @@ public interface ILuaIntellisenseProvider : IDisposable { bool IsAvailable { get; } event Action> DiagnosticsUpdated; + event Action> SemanticTokensUpdated; IReadOnlyList GetDiagnostics(string filePath); + IReadOnlyList GetSemanticTokens(string filePath); void OpenDocument(string filePath, string content); void UpdateDocument(string filePath, string content); void CloseDocument(string filePath); Task> GetCompletionItemsAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default); + int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default); Task GetHoverAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index 0adc84feb0..fc2b3c5eee 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -41,5 +41,8 @@ PreserveNewest + + PreserveNewest + \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 6a2cd460b1..63d1f30173 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -783,10 +783,10 @@ public void InitializeCompletionWindow(int width = 300, int height = 300) { WindowStyle = WindowStyle.None, ResizeMode = ResizeMode.NoResize, - BorderThickness = new Thickness(2), - Background = new SolidColorBrush(Color.FromRgb(69, 69, 69)), - Foreground = Brushes.White, - BorderBrush = Brushes.Black, + BorderThickness = new Thickness(1.0), + Background = DefaultToolTipBackground, + Foreground = ToolTipForeground, + BorderBrush = DefaultToolTipBorder, Width = width, Height = height }; diff --git a/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs new file mode 100644 index 0000000000..e79c7b2a18 --- /dev/null +++ b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.IO; +using ICSharpCode.AvalonEdit; +using TextMateSharp.Grammars; +using TextMateSharp.Model; +using TextMateSharp.Registry; +using TextMateSharp.Themes; + +namespace TombLib.Scripting.Highlighting +{ + public static class LuaTextMateSyntaxHighlighting + { + private static readonly Lazy GrammarState = new Lazy(LoadGrammarState); + + public static bool TryInstall(TextEditor editor, out LuaTextMateInstallation installation) + { + installation = null; + + if (editor?.Document is null) + return false; + + LuaTextMateGrammarState grammarState = GrammarState.Value; + + if (grammarState?.Grammar is null || grammarState.Theme is null) + return false; + + var documentLines = new TextMateDocumentLineList(editor.Document); + var model = new TMModel(documentLines); + model.SetGrammar(grammarState.Grammar); + var styleResolver = new TextMateThemeStyleResolver(grammarState.Theme); + var transformer = new TextMateColorizingTransformer(editor.TextArea.TextView, model, styleResolver); + + editor.TextArea.TextView.LineTransformers.Add(transformer); + installation = new LuaTextMateInstallation(editor, documentLines, model, transformer); + return true; + } + + private static LuaTextMateGrammarState LoadGrammarState() + { + string grammarFilePath = Path.Combine(AppContext.BaseDirectory, "Configs", "TextEditors", "Grammars", "Lua", "lua.tmLanguage.json"); + + if (!File.Exists(grammarFilePath)) + return null; + + var registry = new Registry(new RegistryOptions(ThemeName.DarkPlus)); + IGrammar grammar = registry.LoadGrammarFromPathSync(grammarFilePath, 0, new Dictionary()); + Theme theme = registry.GetTheme(); + + return grammar is null || theme is null + ? null + : new LuaTextMateGrammarState(grammar, theme); + } + + private sealed class LuaTextMateGrammarState + { + public LuaTextMateGrammarState(IGrammar grammar, Theme theme) + { + Grammar = grammar; + Theme = theme; + } + + public IGrammar Grammar { get; } + public Theme Theme { get; } + } + } + + public sealed class LuaTextMateInstallation : IDisposable + { + private readonly TextEditor _editor; + private readonly TextMateDocumentLineList _documentLines; + private readonly TextMateColorizingTransformer _transformer; + private bool _isDisposed; + + internal LuaTextMateInstallation(TextEditor editor, TextMateDocumentLineList documentLines, TMModel model, + TextMateColorizingTransformer transformer) + { + _editor = editor; + _documentLines = documentLines; + _transformer = transformer; + Model = model; + } + + public TMModel Model { get; } + + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + + _transformer.Dispose(); + + if (_editor.TextArea.TextView.LineTransformers.Contains(_transformer)) + _editor.TextArea.TextView.LineTransformers.Remove(_transformer); + + Model.Dispose(); + _documentLines.Dispose(); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs new file mode 100644 index 0000000000..9c46788086 --- /dev/null +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Media; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Rendering; +using TextMateSharp.Model; + +namespace TombLib.Scripting.Highlighting +{ + internal sealed class TextMateColorizingTransformer : DocumentColorizingTransformer, IDisposable, IModelTokensChangedListener + { + private readonly TextView _textView; + private readonly TMModel _model; + private readonly TextMateThemeStyleResolver _styleResolver; + private bool _isDisposed; + + public TextMateColorizingTransformer(TextView textView, TMModel model, TextMateThemeStyleResolver styleResolver) + { + _textView = textView ?? throw new ArgumentNullException(nameof(textView)); + _model = model ?? throw new ArgumentNullException(nameof(model)); + _styleResolver = styleResolver ?? throw new ArgumentNullException(nameof(styleResolver)); + + _model.AddModelTokensChangedListener(this); + } + + protected override void ColorizeLine(DocumentLine line) + { + if (_isDisposed || line is null) + return; + + int lineIndex = Math.Max(0, line.LineNumber - 1); + List tokens = _model.GetLineTokens(lineIndex); + + if (tokens is null || _model.IsLineInvalid(lineIndex)) + { + _model.ForceTokenization(lineIndex); + tokens = _model.GetLineTokens(lineIndex); + } + + if (tokens is null || tokens.Count == 0) + return; + + int lineLength = line.Length; + + for (int i = 0; i < tokens.Count; i++) + { + TMToken token = tokens[i]; + int startIndex = ClampToLine(token.StartIndex, lineLength); + int endIndex = i + 1 < tokens.Count + ? ClampToLine(tokens[i + 1].StartIndex, lineLength) + : lineLength; + + if (endIndex <= startIndex) + continue; + + TextMateHighlightingStyle style = _styleResolver.Resolve(token.Scopes); + + if (!style.HasFormatting) + continue; + + int startOffset = line.Offset + startIndex; + int endOffset = line.Offset + endIndex; + + ChangeLinePart(startOffset, endOffset, element => ApplyStyle(element, style)); + } + } + + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + _model.RemoveModelTokensChangedListener(this); + } + + void IModelTokensChangedListener.ModelTokensChanged(ModelTokensChangedEvent e) + { + if (_isDisposed) + return; + + if (_textView.Dispatcher.CheckAccess()) + _textView.Redraw(); + else + _textView.Dispatcher.BeginInvoke(new Action(_textView.Redraw)); + } + + private static int ClampToLine(int index, int lineLength) + => Math.Max(0, Math.Min(index, lineLength)); + + private static void ApplyStyle(VisualLineElement element, TextMateHighlightingStyle style) + { + VisualLineElementTextRunProperties properties = element.TextRunProperties; + + if (style.Foreground is not null) + properties.SetForegroundBrush(style.Foreground); + + if (style.IsBold || style.IsItalic) + properties.SetTypeface(style.CreateTypeface(properties.Typeface)); + + if (style.TextDecorations is not null) + properties.SetTextDecorations(style.TextDecorations); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs new file mode 100644 index 0000000000..c57296e732 --- /dev/null +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using ICSharpCode.AvalonEdit.Document; +using TextMateSharp.Grammars; +using TextMateSharp.Model; + +namespace TombLib.Scripting.Highlighting +{ + internal sealed class TextMateDocumentLineList : AbstractLineList + { + private readonly TextDocument _document; + private readonly object _syncRoot = new object(); + private readonly List _lineTexts = new List(); + + public TextMateDocumentLineList(TextDocument document) + { + _document = document ?? throw new ArgumentNullException(nameof(document)); + + InitializeSnapshot(); + + _document.Changed += Document_Changed; + } + + public override void UpdateLine(int lineIndex) + => InvalidateLineRange(lineIndex, Math.Max(lineIndex, GetNumberOfLines() - 1)); + + public override int GetNumberOfLines() + { + lock (_syncRoot) + return _lineTexts.Count; + } + + public override LineText GetLineTextIncludingTerminators(int lineIndex) + { + lock (_syncRoot) + { + if (lineIndex < 0 || lineIndex >= _lineTexts.Count) + return new LineText(string.Empty); + + return new LineText(_lineTexts[lineIndex]); + } + } + + public override int GetLineLength(int lineIndex) + { + lock (_syncRoot) + { + if (lineIndex < 0 || lineIndex >= _lineTexts.Count) + return 0; + + return _lineTexts[lineIndex].Length; + } + } + + public override void Dispose() + => _document.Changed -= Document_Changed; + + private void Document_Changed(object sender, DocumentChangeEventArgs e) + { + int startLineIndex = GetStartLineIndex(e.Offset); + int removedLineCount = GetAffectedLineCount(e.RemovedText?.Text); + int insertedLineCount = GetAffectedLineCount(e.InsertedText?.Text); + int lineDelta = insertedLineCount - removedLineCount; + + lock (_syncRoot) + { + ReplaceSnapshotLines(startLineIndex, removedLineCount, insertedLineCount); + + if (lineDelta > 0) + { + for (int i = 0; i < lineDelta; i++) + AddLine(startLineIndex + 1 + i); + } + else if (lineDelta < 0) + { + for (int i = 0; i < -lineDelta; i++) + { + int removeIndex = Math.Min(startLineIndex + 1, GetNumberOfLines() - 1); + + if (removeIndex >= 0) + RemoveLine(removeIndex); + } + } + + UpdateLine(Math.Min(startLineIndex, Math.Max(0, GetNumberOfLines() - 1))); + } + } + + private void InitializeSnapshot() + { + lock (_syncRoot) + { + _lineTexts.Clear(); + + for (int i = 0; i < _document.LineCount; i++) + { + _lineTexts.Add(ReadDocumentLineText(i)); + AddLine(i); + } + } + } + + private void ReplaceSnapshotLines(int startLineIndex, int removedLineCount, int insertedLineCount) + { + int safeStartLineIndex = Math.Max(0, Math.Min(startLineIndex, _lineTexts.Count)); + int removableLineCount = Math.Max(0, Math.Min(removedLineCount, _lineTexts.Count - safeStartLineIndex)); + + if (removableLineCount > 0) + _lineTexts.RemoveRange(safeStartLineIndex, removableLineCount); + + _lineTexts.InsertRange(safeStartLineIndex, ReadDocumentLines(safeStartLineIndex, insertedLineCount)); + } + + private List ReadDocumentLines(int startLineIndex, int lineCount) + { + var lines = new List(); + + if (_document.LineCount == 0) + return lines; + + int safeStartLineIndex = Math.Max(0, Math.Min(startLineIndex, _document.LineCount - 1)); + int safeLineCount = Math.Max(1, Math.Min(lineCount, _document.LineCount - safeStartLineIndex)); + + for (int i = 0; i < safeLineCount; i++) + lines.Add(ReadDocumentLineText(safeStartLineIndex + i)); + + return lines; + } + + private string ReadDocumentLineText(int lineIndex) + { + DocumentLine line = _document.GetLineByNumber(Math.Max(1, lineIndex + 1)); + return _document.GetText(line.Offset, line.TotalLength); + } + + private int GetStartLineIndex(int offset) + { + if (_document.LineCount == 0) + return 0; + + int safeOffset = Math.Max(0, Math.Min(offset, _document.TextLength)); + DocumentLine line = _document.GetLineByOffset(safeOffset); + return Math.Max(0, line.LineNumber - 1); + } + + private static int CountLineBreaks(string text) + { + if (string.IsNullOrEmpty(text)) + return 0; + + int count = 0; + + for (int i = 0; i < text.Length; i++) + { + if (text[i] != '\n') + continue; + + count++; + } + + return count; + } + + private static int GetAffectedLineCount(string text) + => CountLineBreaks(text) + 1; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateHighlightingStyle.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateHighlightingStyle.cs new file mode 100644 index 0000000000..5174d50853 --- /dev/null +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateHighlightingStyle.cs @@ -0,0 +1,34 @@ +using System.Windows; +using System.Windows.Media; + +namespace TombLib.Scripting.Highlighting +{ + internal sealed class TextMateHighlightingStyle + { + public static readonly TextMateHighlightingStyle Empty = new TextMateHighlightingStyle(null, false, false, null); + + public TextMateHighlightingStyle(Brush foreground, bool isBold, bool isItalic, TextDecorationCollection textDecorations) + { + Foreground = foreground; + IsBold = isBold; + IsItalic = isItalic; + TextDecorations = textDecorations; + } + + public Brush Foreground { get; } + public bool IsBold { get; } + public bool IsItalic { get; } + public TextDecorationCollection TextDecorations { get; } + + public bool HasFormatting + => Foreground is not null || IsBold || IsItalic || TextDecorations is not null; + + public Typeface CreateTypeface(Typeface baseTypeface) + { + FontStyle fontStyle = IsItalic ? FontStyles.Italic : baseTypeface.Style; + FontWeight fontWeight = IsBold ? FontWeights.Bold : baseTypeface.Weight; + + return new Typeface(baseTypeface.FontFamily, fontStyle, fontWeight, baseTypeface.Stretch); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs new file mode 100644 index 0000000000..0406c64ef2 --- /dev/null +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Media; +using TextMateSharp.Themes; +using TextMateFontStyle = TextMateSharp.Themes.FontStyle; + +namespace TombLib.Scripting.Highlighting +{ + internal sealed class TextMateThemeStyleResolver + { + private static readonly TextDecorationCollection UnderlineDecorations = CreateTextDecorations(TextDecorations.Underline); + private static readonly TextDecorationCollection StrikethroughDecorations = CreateTextDecorations(TextDecorations.Strikethrough); + + private readonly Theme _theme; + private readonly Dictionary _cache = new Dictionary(StringComparer.Ordinal); + + public TextMateThemeStyleResolver(Theme theme) + => _theme = theme ?? throw new ArgumentNullException(nameof(theme)); + + public TextMateHighlightingStyle Resolve(IList scopes) + { + if (scopes is null || scopes.Count == 0) + return TextMateHighlightingStyle.Empty; + + string cacheKey = string.Join(" ", scopes); + + if (_cache.TryGetValue(cacheKey, out TextMateHighlightingStyle cachedStyle)) + return cachedStyle; + + int foreground = 0; + TextMateFontStyle fontStyle = TextMateFontStyle.NotSet; + TextDecorationCollection textDecorations = null; + + foreach (ThemeTrieElementRule rule in _theme.Match(scopes)) + { + if (foreground == 0 && rule.foreground > 0) + foreground = rule.foreground; + + if (fontStyle == TextMateFontStyle.NotSet && rule.fontStyle != TextMateFontStyle.NotSet) + fontStyle = rule.fontStyle; + + if (foreground > 0 && fontStyle != TextMateFontStyle.NotSet) + break; + } + + if (fontStyle == TextMateFontStyle.NotSet) + fontStyle = TextMateFontStyle.None; + + if ((fontStyle & TextMateFontStyle.Underline) == TextMateFontStyle.Underline + && (fontStyle & TextMateFontStyle.Strikethrough) == TextMateFontStyle.Strikethrough) + { + textDecorations = new TextDecorationCollection(); + + foreach (TextDecoration decoration in UnderlineDecorations) + textDecorations.Add(decoration); + + foreach (TextDecoration decoration in StrikethroughDecorations) + textDecorations.Add(decoration); + + textDecorations.Freeze(); + } + else if ((fontStyle & TextMateFontStyle.Underline) == TextMateFontStyle.Underline) + { + textDecorations = UnderlineDecorations; + } + else if ((fontStyle & TextMateFontStyle.Strikethrough) == TextMateFontStyle.Strikethrough) + { + textDecorations = StrikethroughDecorations; + } + + Brush brush = foreground > 0 + ? CreateFrozenBrush(_theme.GetColor(foreground)) + : null; + + TextMateHighlightingStyle style = new TextMateHighlightingStyle( + brush, + (fontStyle & TextMateFontStyle.Bold) == TextMateFontStyle.Bold, + (fontStyle & TextMateFontStyle.Italic) == TextMateFontStyle.Italic, + textDecorations); + + _cache[cacheKey] = style; + return style; + } + + private static Brush CreateFrozenBrush(string colorValue) + { + if (string.IsNullOrWhiteSpace(colorValue)) + return null; + + var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); + brush.Freeze(); + return brush; + } + + private static TextDecorationCollection CreateTextDecorations(TextDecorationCollection source) + { + var clone = source.Clone(); + clone.Freeze(); + return clone; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs index b8813afe1c..834941cd8f 100644 --- a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs @@ -13,6 +13,7 @@ using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting.Xshd; using MdXaml; +using TombLib.Scripting.Highlighting; using TombLib.Scripting.Resources; namespace TombLib.Scripting.Rendering @@ -237,7 +238,12 @@ private static FrameworkElement CreateCodeBlockElement(string language, string c editor.Options.HighlightCurrentLine = false; editor.Options.ShowBoxForControlCharacters = false; editor.TextArea.Margin = new Thickness(0.0); - editor.SyntaxHighlighting = ResolveHighlighting(language); + + if (!string.Equals(language?.Trim(), "lua", StringComparison.OrdinalIgnoreCase) + || !LuaTextMateSyntaxHighlighting.TryInstall(editor, out _)) + { + editor.SyntaxHighlighting = ResolveHighlighting(language); + } int lineCount = Math.Max(1, editor.Document.LineCount); double lineHeight = GetEditorLineHeight(editor); diff --git a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj index 645c5d4252..efc49f7ca1 100644 --- a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj +++ b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj @@ -26,6 +26,8 @@ + + From 5cca76711fd933937bbec1d1cb90b809a77e40e7 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 00:48:52 +0100 Subject: [PATCH 03/34] Fixes and adjustments --- .../LuaLanguageServerClient.cs | 25 +- .../LuaLanguageServerIntellisenseProvider.cs | 46 ++- .../LuaLanguageServerResponseParser.cs | 109 ++++--- .../LuaSemanticTokensColorizer.cs | 8 +- .../LuaEditor.Intellisense.cs | 212 +++++++++++++- .../LuaEditor.Navigation.cs | 35 +-- .../LuaEditor.SignatureHelp.cs | 1 + TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 7 - .../Objects/LuaCompletionData.cs | 93 ++++-- .../Objects/LuaCompletionIconFactory.cs | 7 +- .../Objects/LuaCompletionItem.cs | 14 +- .../Objects/LuaCompletionWindowStyle.cs | 7 +- .../TombLib.Scripting.Lua.csproj | 1 + .../TombLib.Scripting/Bases/TextEditorBase.cs | 71 ++--- .../TextMateColorizingTransformer.cs | 10 +- .../TextMateThemeStyleResolver.cs | 16 +- .../Rendering/ErrorRenderer.cs | 18 +- .../Rendering/MarkdownToolTipRenderer.cs | 268 ++++++++++++++---- .../TombLib.Scripting.csproj | 1 + TombLib/TombLib.WPF/BrushHelpers.cs | 9 +- .../TombLib.WPF/DependencyObjectExtensions.cs | 110 +++++++ 21 files changed, 807 insertions(+), 261 deletions(-) create mode 100644 TombLib/TombLib.WPF/DependencyObjectExtensions.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index 7a9908353f..79bc0d71d3 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -42,10 +42,12 @@ internal sealed class LuaLanguageServerClient : IDisposable private Task _stderrLoopTask; private string[] _semanticTokenTypes = Array.Empty(); private string[] _semanticTokenModifiers = Array.Empty(); + private bool _supportsCompletionResolve; public bool IsReady { get; private set; } public IReadOnlyList SemanticTokenTypes => _semanticTokenTypes; public IReadOnlyList SemanticTokenModifiers => _semanticTokenModifiers; + public bool SupportsCompletionResolve => _supportsCompletionResolve; public event Action DiagnosticsPublished; @@ -98,7 +100,7 @@ public async Task StartAsync(CancellationToken cancellationToken) initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); JsonElement initializeResponse = await SendRequestAsync("initialize", BuildInitializeParams(), initializeTimeout.Token).ConfigureAwait(false); - CaptureSemanticTokenLegend(initializeResponse); + CaptureServerCapabilities(initializeResponse); IsReady = true; @@ -179,7 +181,11 @@ private object BuildInitializeParams() completionItem = new { snippetSupport = false, - documentationFormat = new[] { "plaintext", "markdown" } + documentationFormat = new[] { "plaintext", "markdown" }, + resolveSupport = new + { + properties = new[] { "detail", "documentation" } + } } }, hover = new @@ -223,12 +229,20 @@ private object BuildInitializeParams() } }; - private void CaptureSemanticTokenLegend(JsonElement initializeResponse) + private void CaptureServerCapabilities(JsonElement initializeResponse) { + _supportsCompletionResolve = false; _semanticTokenTypes = Array.Empty(); _semanticTokenModifiers = Array.Empty(); - if (!initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities) + if (initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities) + && capabilities.TryGetProperty("completionProvider", out JsonElement completionProvider) + && completionProvider.TryGetProperty("resolveProvider", out JsonElement resolveProvider)) + { + _supportsCompletionResolve = resolveProvider.ValueKind == JsonValueKind.True; + } + + if (!initializeResponse.TryGetProperty("capabilities", out capabilities) || !capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider) || !semanticTokensProvider.TryGetProperty("legend", out JsonElement legend)) { @@ -619,6 +633,9 @@ private void ResetProcessState() _process = null; _readLoopTask = null; _stderrLoopTask = null; + _supportsCompletionResolve = false; + _semanticTokenTypes = Array.Empty(); + _semanticTokenModifiers = Array.Empty(); } private void ThrowIfDisposed() diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index a4fb6dd2e6..7c0d8d0b5b 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -93,7 +93,12 @@ public async Task> GetCompletionItemsAsync(stri context = BuildCompletionContext(triggerCharacter) }, cancellationToken).ConfigureAwait(false); - return LuaLanguageServerResponseParser.ParseCompletionItems(response); + IReadOnlyList itemElements = LuaLanguageServerResponseParser.ExtractCompletionItems(response); + + if (itemElements.Count == 0) + return Array.Empty(); + + return LuaLanguageServerResponseParser.ParseCompletionItems(itemElements, BuildCompletionItemResolveCallback); } private static object BuildCompletionContext(char? triggerCharacter) @@ -101,6 +106,45 @@ private static object BuildCompletionContext(char? triggerCharacter) ? new { triggerKind = 1 } : new { triggerKind = 2, triggerCharacter = triggerCharacter.ToString() }; + private Func> BuildCompletionItemResolveCallback(JsonElement itemElement, int itemIndex) + { + if (_client is null || !_client.SupportsCompletionResolve || !LuaLanguageServerResponseParser.CompletionItemNeedsResolve(itemElement)) + return null; + + return cancellationToken => ResolveCompletionItemAsync(itemElement, itemIndex, cancellationToken); + } + + private async Task ResolveCompletionItemAsync(JsonElement itemElement, int itemIndex, CancellationToken cancellationToken) + { + LuaCompletionItem unresolvedItem = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, itemIndex); + + if (_client is null || !_client.SupportsCompletionResolve) + return unresolvedItem; + + try + { + JsonElement resolvedItem = await _client.SendRequestAsync("completionItem/resolve", itemElement, cancellationToken).ConfigureAwait(false); + + if (resolvedItem.ValueKind == JsonValueKind.Object) + { + LuaCompletionItem parsedItem = LuaLanguageServerResponseParser.ParseCompletionItem(resolvedItem, itemIndex); + + if (parsedItem is not null) + return parsedItem; + } + } + catch (OperationCanceledException) + { + throw; + } + catch + { + // Ignore + } + + return unresolvedItem; + } + public async Task GetHoverAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs index 06a2a1595a..370f4957c1 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Text; using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; namespace TombIDE.ScriptingStudio.Services.LuaIntellisense @@ -22,6 +24,9 @@ public MarkupContent(string text, bool isMarkdown) } public static IReadOnlyList ParseCompletionItems(JsonElement response) + => ParseCompletionItems(ExtractCompletionItems(response)); + + public static IReadOnlyList ExtractCompletionItems(JsonElement response) { JsonElement itemsElement = response; @@ -29,51 +34,28 @@ public static IReadOnlyList ParseCompletionItems(JsonElement itemsElement = completionItemsElement; if (itemsElement.ValueKind != JsonValueKind.Array) - return Array.Empty(); + return Array.Empty(); - var items = new List(); - int itemIndex = 0; + var itemElements = new List(); foreach (JsonElement itemElement in itemsElement.EnumerateArray()) - { - if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) - continue; + itemElements.Add(itemElement.Clone()); - string label = labelElement.GetString(); - string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) - && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) - ? newTextElement.GetString() - : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) - ? insertTextElement.GetString() - : label; + return itemElements; + } - if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) - && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) - { - insertText = StripSnippetPlaceholders(insertText); - } + public static IReadOnlyList ParseCompletionItems(IEnumerable itemElements, + Func>> resolveFactory = null) + { + var items = new List(); + int itemIndex = 0; - string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) - ? filterTextElement.GetString() - : label; - - LuaCompletionItemKind kind = TryReadCompletionKind(itemElement, out LuaCompletionItemKind completionKind) - ? completionKind - : LuaCompletionItemKind.Text; - - string detail = BuildCompletionDetail(itemElement); - MarkupContent description = BuildCompletionDescription(itemElement); - string searchableDescription = NormalizeMarkupText(description.Text); - items.Add(new LuaCompletionItem( - label, - insertText, - detail, - description.Text, - filterText, - BuildCompletionPriority(itemElement, detail, searchableDescription, itemIndex), - kind, - BuildCompletionIconKind(kind, detail), - description.IsMarkdown)); + foreach (JsonElement itemElement in itemElements) + { + LuaCompletionItem item = ParseCompletionItem(itemElement, itemIndex, resolveFactory?.Invoke(itemElement, itemIndex)); + + if (item is not null) + items.Add(item); itemIndex++; } @@ -84,6 +66,55 @@ public static IReadOnlyList ParseCompletionItems(JsonElement .ToList(); } + public static bool CompletionItemNeedsResolve(JsonElement itemElement) + => string.IsNullOrWhiteSpace(BuildCompletionDetail(itemElement)) + || string.IsNullOrWhiteSpace(BuildCompletionDescription(itemElement).Text); + + public static LuaCompletionItem ParseCompletionItem(JsonElement itemElement, int itemIndex, + Func> resolveAsync = null) + { + if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) + return null; + + string label = labelElement.GetString(); + string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) + && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) + ? newTextElement.GetString() + : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) + ? insertTextElement.GetString() + : label; + + if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) + && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) + { + insertText = StripSnippetPlaceholders(insertText); + } + + string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) + ? filterTextElement.GetString() + : label; + + LuaCompletionItemKind kind = TryReadCompletionKind(itemElement, out LuaCompletionItemKind completionKind) + ? completionKind + : LuaCompletionItemKind.Text; + + string detail = BuildCompletionDetail(itemElement); + MarkupContent description = BuildCompletionDescription(itemElement); + string searchableDescription = NormalizeMarkupText(description.Text); + + return new LuaCompletionItem( + label, + insertText, + detail, + description.Text, + filterText, + BuildCompletionPriority(itemElement, detail, searchableDescription, itemIndex), + kind, + BuildCompletionIconKind(kind, detail), + description.IsMarkdown, + resolveAsync); + } + private static double BuildCompletionPriority(JsonElement itemElement, string detail, string description, int itemIndex) { const double responseOrderWeight = 100000.0; diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index fd91683db8..20979e16c9 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -5,6 +5,7 @@ using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using TombLib.Scripting.Lua.Objects; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Lua.Highlighting { @@ -153,13 +154,6 @@ private static void ApplyStyle(VisualLineElement element, LuaSemanticTokenStyle properties.SetTextDecorations(style.TextDecorations); } - private static Brush CreateFrozenBrush(string colorValue) - { - var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); - brush.Freeze(); - return brush; - } - private static TextDecorationCollection CreateTextDecorations(TextDecorationCollection source) { var clone = source.Clone(); diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index e82884ecb3..d4fc075273 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -4,12 +4,17 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Interop; +using System.Windows.Media; using System.Windows.Threading; using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Objects; +using TombLib.Scripting.Rendering; +using TombLib.WPF; namespace TombLib.Scripting.Lua { @@ -20,8 +25,10 @@ public sealed partial class LuaEditor private CancellationTokenSource _hoverCancellationTokenSource; private CancellationTokenSource _completionCancellationTokenSource; + private CancellationTokenSource _completionToolTipCancellationTokenSource; private CancellationTokenSource _signatureCancellationTokenSource; private int _completionRequestToken; + private int _completionToolTipUpdateToken; private int _hoverRequestToken; private Window _hostWindow; @@ -78,6 +85,8 @@ private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) _completionCancellationTokenSource?.Dispose(); _completionCancellationTokenSource = null; + CancelCompletionToolTipUpdate(); + _signatureCancellationTokenSource?.Cancel(); _signatureCancellationTokenSource?.Dispose(); _signatureCancellationTokenSource = null; @@ -151,16 +160,25 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (hoveredOffset == -1) return; - if (TryShowDiagnosticToolTip(hoveredOffset)) - return; + bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); if (!IsIntellisenseAvailable()) + { + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + return; + } string hoveredWord = GetWordFromOffset(hoveredOffset); if (string.IsNullOrWhiteSpace(hoveredWord)) + { + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + return; + } _hoverCancellationTokenSource?.Cancel(); _hoverCancellationTokenSource?.Dispose(); @@ -173,9 +191,6 @@ protected override async void HandleMouseHover(MouseEventArgs e) { LuaHoverInfo hoverInfo = await RequestHoverAsync(hoveredOffset, cancellationToken).ConfigureAwait(true); - if (hoverInfo is null || string.IsNullOrWhiteSpace(hoverInfo.Content)) - return; - if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) return; @@ -184,17 +199,65 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (currentHoveredOffset != hoveredOffset) return; - if (hoverInfo.IsMarkdown) - ShowMarkdownToolTip(hoverInfo.Content); - else - ShowToolTip(hoverInfo.Content); + bool hasHover = hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content); + + if (hasHover && hasDiagnostic) + ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); + else if (hasHover) + ShowHoverToolTip(hoverInfo); + else if (hasDiagnostic) + { + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + } } catch { - // Ignore hover failures and keep the editor responsive. + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); } } + private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) + { + GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); + + var panel = new StackPanel { MaxWidth = ToolTipTextMaxWidth }; + + panel.Children.Add(CreateHoverToolTipContent(hoverInfo)); + + panel.Children.Add(new Border + { + Background = diagnosticBackground, + BorderBrush = diagnosticBorder, + BorderThickness = new Thickness(1.0), + CornerRadius = new CornerRadius(3.0), + Padding = new Thickness(8.0, 4.0, 8.0, 4.0), + Margin = new Thickness(0.0, 6.0, 0.0, 0.0), + Child = new TextBlock + { + Text = diagnosticMessage, + Foreground = ToolTipForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = ToolTipTextFontSize, + TextWrapping = TextWrapping.Wrap, + MaxWidth = ToolTipTextMaxWidth + } + }); + + ShowToolTip(panel, DefaultToolTipBorder, DefaultToolTipBackground); + } + + private void ShowHoverToolTip(LuaHoverInfo hoverInfo) + => ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); + + private FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) + { + if (hoverInfo.IsMarkdown) + return MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground); + + return MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); + } + private bool IsIntellisenseAvailable() => IntellisenseProvider is not null && IntellisenseProvider.IsAvailable && !string.IsNullOrWhiteSpace(FilePath); @@ -221,9 +284,14 @@ private static bool ShouldKeepCompletionWindowOpen(string inputText) private void CloseCompletionWindow() { + CancelCompletionToolTipUpdate(); + if (_completionWindow is null) return; + if (CompletionToolTipField?.GetValue(_completionWindow) is ToolTip tooltip) + tooltip.IsOpen = false; + _completionWindow.Close(); _completionWindow = null; } @@ -264,13 +332,21 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) return; } + var completionDataItems = new LuaCompletionData[items.Count]; + + for (int i = 0; i < items.Count; i++) + completionDataItems[i] = new LuaCompletionData(items[i]); + + if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + return; + CloseCompletionWindow(); InitializeLuaCompletionWindow(); SetCompletionWindowOffsets(offset); - foreach (LuaCompletionItem item in items) - _completionWindow.CompletionList.CompletionData.Add(new LuaCompletionData(item)); + foreach (LuaCompletionData completionDataItem in completionDataItems) + _completionWindow.CompletionList.CompletionData.Add(completionDataItem); if (_completionWindow.CompletionList.CompletionData.Count > 0) { @@ -362,6 +438,9 @@ private static bool IsIdentifierTriggerCharacter(char character) private void StyleCompletionTooltip() { + if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; + if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) return; @@ -369,13 +448,120 @@ private void StyleCompletionTooltip() tooltip.BorderBrush = DefaultToolTipBorder; tooltip.BorderThickness = new Thickness(0.0); tooltip.Padding = new Thickness(0.0); + tooltip.PlacementTarget = listBox; + tooltip.Placement = PlacementMode.Right; + tooltip.HorizontalOffset = 10.0; + tooltip.StaysOpen = true; + + listBox.SelectionChanged += (s, e) => ScheduleCompletionTooltipUpdate(tooltip); + listBox.PreviewMouseLeftButtonUp += (s, e) => HandleCompletionListClick(listBox, tooltip, e); + } + + private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) + { + ListBoxItem listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); + + if (listBoxItem is null) + return; + + if (!ReferenceEquals(listBox.SelectedItem, listBoxItem.DataContext)) + listBox.SelectedItem = listBoxItem.DataContext; + + listBox.ScrollIntoView(listBoxItem.DataContext); + ScheduleCompletionTooltipUpdate(tooltip); + } + + private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) + { + _completionToolTipCancellationTokenSource?.Cancel(); + _completionToolTipCancellationTokenSource?.Dispose(); + _completionToolTipCancellationTokenSource = new CancellationTokenSource(); + + CancellationToken cancellationToken = _completionToolTipCancellationTokenSource.Token; + int updateToken = ++_completionToolTipUpdateToken; + + Dispatcher.BeginInvoke( + new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, cancellationToken, updateToken)), + DispatcherPriority.Background); + } + + private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationToken cancellationToken, int updateToken) + { + if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; + + ICompletionData item = listBox.SelectedItem as ICompletionData; + + if (item is null) + { + tooltip.IsOpen = false; + return; + } + + try + { + object description = item.Description; + + if (description is not null) + ApplyCompletionToolTipContent(tooltip, description); + else + tooltip.IsOpen = false; + + if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) + { + object resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested || updateToken != _completionToolTipUpdateToken) + return; + + if (_completionWindow?.CompletionList.ListBox is not ListBox currentListBox + || !ReferenceEquals(currentListBox, listBox) + || !ReferenceEquals(currentListBox.SelectedItem, item)) + { + return; + } + + if (resolvedDescription is not null) + ApplyCompletionToolTipContent(tooltip, resolvedDescription); + else + tooltip.IsOpen = false; + } + } + catch (OperationCanceledException) + { + } + catch + { + tooltip.IsOpen = false; + } + } + + private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) + { + tooltip.Content = content; + + if (!tooltip.IsOpen) + tooltip.IsOpen = true; + else + { + tooltip.InvalidateMeasure(); + tooltip.InvalidateVisual(); + } + } + + private void CancelCompletionToolTipUpdate() + { + _completionToolTipCancellationTokenSource?.Cancel(); + _completionToolTipCancellationTokenSource?.Dispose(); + _completionToolTipCancellationTokenSource = null; + _completionToolTipUpdateToken++; } private void ScheduleCloseIfEmpty() => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); private void ScheduleInitialSelection() - => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.ContextIdle); + => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.Background); private void SelectInitialItem() { diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index 3fa6aa17da..94769b8ebf 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; @@ -24,8 +23,6 @@ private async void TextEditor_KeyDown(object sender, KeyEventArgs e) if (e.Key == Key.F12) { - Debug.WriteLine("[LuaLS] F12 pressed, attempting definition navigation."); - if (await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true)) e.Handled = true; } @@ -47,8 +44,6 @@ private async void TextEditor_PreviewMouseLeftButtonDown(object sender, MouseBut if (hoveredOffset == -1) return; - Debug.WriteLine("[LuaLS] CTRL+Click detected, attempting definition navigation."); - if (await TryNavigateToDefinitionAsync(hoveredOffset, CancellationToken.None).ConfigureAwait(true)) e.Handled = true; } @@ -56,16 +51,12 @@ private async void TextEditor_PreviewMouseLeftButtonDown(object sender, MouseBut private async Task TryNavigateToDefinitionAsync(int offset, CancellationToken cancellationToken) { if (!IsIntellisenseAvailable()) - { - Debug.WriteLine("[LuaLS] Definition aborted: intellisense not available."); return false; - } + if (DefinitionNavigationRequested is null) - { - Debug.WriteLine("[LuaLS] Definition aborted: DefinitionNavigationRequested callback not set."); return false; - } + try { @@ -73,30 +64,23 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo { (int line, int column) = GetPositionFromOffset(candidateOffset); - Debug.WriteLine($"[LuaLS] Requesting definition at offset {candidateOffset} -> ({line},{column})."); - LuaDefinitionLocation definitionLocation = await IntellisenseProvider .GetDefinitionAsync(FilePath, Text, line, column, cancellationToken) .ConfigureAwait(true); if (definitionLocation is null) continue; - - Debug.WriteLine($"[LuaLS] Definition found: '{definitionLocation.FilePath}' L{definitionLocation.LineNumber}."); DefinitionNavigationRequested(definitionLocation); return true; } - - Debug.WriteLine("[LuaLS] Definition not found for any candidate offset."); return false; } catch (OperationCanceledException) { return false; } - catch (Exception exception) + catch { - Debug.WriteLine($"[LuaLS] Definition navigation failed: {exception.Message}"); return false; } } @@ -138,30 +122,27 @@ private bool TryGetDefinitionWordBounds(int offset, out int wordStart, out int w probeOffset = Document.TextLength - 1; if (probeOffset > 0 - && !IsDefinitionIdentifierCharacter(Document.GetCharAt(probeOffset)) - && IsDefinitionIdentifierCharacter(Document.GetCharAt(probeOffset - 1))) + && !IsIdentifierCharacter(Document.GetCharAt(probeOffset)) + && IsIdentifierCharacter(Document.GetCharAt(probeOffset - 1))) { probeOffset--; } - if (!IsDefinitionIdentifierCharacter(Document.GetCharAt(probeOffset))) + if (!IsIdentifierCharacter(Document.GetCharAt(probeOffset))) return false; wordStart = probeOffset; wordEnd = probeOffset + 1; - while (wordStart > 0 && IsDefinitionIdentifierCharacter(Document.GetCharAt(wordStart - 1))) + while (wordStart > 0 && IsIdentifierCharacter(Document.GetCharAt(wordStart - 1))) wordStart--; - while (wordEnd < Document.TextLength && IsDefinitionIdentifierCharacter(Document.GetCharAt(wordEnd))) + while (wordEnd < Document.TextLength && IsIdentifierCharacter(Document.GetCharAt(wordEnd))) wordEnd++; return wordEnd > wordStart; } - private static bool IsDefinitionIdentifierCharacter(char c) - => char.IsLetterOrDigit(c) || c == '_'; - private static void AddDefinitionCandidateOffset(ICollection offsets, int offset) { if (!offsets.Contains(offset)) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index 055484f9f9..2e42e16208 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -5,6 +5,7 @@ using System.Windows.Documents; using System.Windows.Media; using TombLib.Scripting.Lua.Objects; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Lua { diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index 2ae2eb9c97..bb8c9d59f3 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -54,12 +54,5 @@ public override void UpdateSettings(Bases.ConfigurationBase configuration) base.UpdateSettings(configuration); LiveErrorUnderlining = true; } - - private static SolidColorBrush CreateFrozenBrush(Color color) - { - var brush = new SolidColorBrush(color); - brush.Freeze(); - return brush; - } } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index b0ad117771..b364d69f4c 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -1,4 +1,8 @@ using System; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; @@ -6,19 +10,22 @@ using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using TombLib.Scripting.Rendering; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Lua.Objects { - public sealed class LuaCompletionData : ICompletionData + public sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged { private const double DescriptionMaxWidth = 540.0; private const double DescriptionTextMaxWidth = 500.0; private static readonly SolidColorBrush DescriptionBorderBrush = CreateFrozenBrush(Color.FromRgb(96, 96, 96)); private static readonly SolidColorBrush DescriptionBackgroundBrush = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); private static readonly SolidColorBrush DescriptionForegroundBrush = CreateFrozenBrush(Colors.Gainsboro); - private readonly LuaCompletionItem _item; - private readonly string _displayDetail; + private readonly object _resolveSync = new object(); + private LuaCompletionItem _item; + private string _displayDetail; private object _cachedDescription; + private Task _resolveTask; public LuaCompletionData(LuaCompletionItem item) { @@ -26,6 +33,8 @@ public LuaCompletionData(LuaCompletionItem item) _displayDetail = FlattenSingleLineText(_item.Detail); } + public event PropertyChangedEventHandler PropertyChanged; + public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind); public string Text => _item.FilterText; public string DisplayText => _item.Label; @@ -34,10 +43,47 @@ public LuaCompletionData(LuaCompletionItem item) public object Content => DisplayText; public object Description => _cachedDescription ??= BuildDescriptionContent(); public double Priority => _item.Priority; + public bool CanResolve => _item.CanResolve; public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) => textArea.Document.Replace(completionSegment, _item.InsertText); + public async Task GetDescriptionAsync(CancellationToken cancellationToken = default) + { + if (!CanResolve) + return Description; + + Task resolveTask; + + lock (_resolveSync) + { + if (!CanResolve) + return Description; + + if (_resolveTask is null || _resolveTask.IsCanceled || _resolveTask.IsFaulted) + _resolveTask = _item.ResolveAsync(cancellationToken); + + resolveTask = _resolveTask; + } + + try + { + LuaCompletionItem resolvedItem = await resolveTask.ConfigureAwait(true); + ApplyResolvedItem(resolvedItem); + return Description; + } + catch + { + lock (_resolveSync) + { + if (ReferenceEquals(_resolveTask, resolveTask)) + _resolveTask = null; + } + + throw; + } + } + private static string FlattenSingleLineText(string text) { if (string.IsNullOrWhiteSpace(text)) @@ -78,8 +124,8 @@ private object BuildDescriptionContent() if (hasDescription) { panel.Children.Add(_item.IsDescriptionMarkdown - ? MarkdownToolTipRenderer.CreateContent(_item.Description, DescriptionForegroundBrush, DescriptionBackgroundBrush) - : CreatePlainDescriptionContent(_item.Description)); + ? MarkdownToolTipRenderer.CreateContent(_item.Description, DescriptionForegroundBrush, DescriptionBackgroundBrush, false) + : MarkdownToolTipRenderer.CreatePlainTextContent(_item.Description, DescriptionForegroundBrush, false)); } return new Border @@ -93,32 +139,23 @@ private object BuildDescriptionContent() }; } - private static FrameworkElement CreatePlainDescriptionContent(string text) + private void ApplyResolvedItem(LuaCompletionItem resolvedItem) { - var textBlock = new TextBlock - { - Text = text, - Foreground = DescriptionForegroundBrush, - TextWrapping = TextWrapping.Wrap, - MaxWidth = DescriptionTextMaxWidth - }; + if (resolvedItem is null || ReferenceEquals(resolvedItem, _item)) + return; - return new ScrollViewer - { - Content = textBlock, - MaxHeight = 420.0, - MaxWidth = DescriptionMaxWidth, - VerticalScrollBarVisibility = ScrollBarVisibility.Auto, - HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, - CanContentScroll = true - }; - } + _item = resolvedItem; + _displayDetail = FlattenSingleLineText(_item.Detail); + _cachedDescription = null; - private static SolidColorBrush CreateFrozenBrush(Color color) - { - var brush = new SolidColorBrush(color); - brush.Freeze(); - return brush; + OnPropertyChanged(nameof(Image)); + OnPropertyChanged(nameof(DisplayDetail)); + OnPropertyChanged(nameof(DetailVisibility)); + OnPropertyChanged(nameof(Description)); } + + private void OnPropertyChanged([CallerMemberName] string propertyName = null) + => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs index 023bb6a7b9..123050880d 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Windows.Media; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Lua.Objects { @@ -134,11 +135,5 @@ private static string[] GetPathData(LuaCompletionIconKind kind) }; } - private static SolidColorBrush CreateFrozenBrush(string colorValue) - { - var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); - brush.Freeze(); - return brush; - } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index 13367fdaa5..98be1fa438 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -1,9 +1,13 @@ using System; +using System.Threading; +using System.Threading.Tasks; namespace TombLib.Scripting.Lua.Objects { public sealed class LuaCompletionItem { + private readonly Func> _resolveAsync; + public LuaCompletionItem( string label, string insertText = null, @@ -13,7 +17,8 @@ public LuaCompletionItem( double priority = 0.0, LuaCompletionItemKind kind = LuaCompletionItemKind.Text, LuaCompletionIconKind iconKind = LuaCompletionIconKind.Misc, - bool isDescriptionMarkdown = false) + bool isDescriptionMarkdown = false, + Func> resolveAsync = null) { Label = label ?? throw new ArgumentNullException(nameof(label)); InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; @@ -24,6 +29,7 @@ public LuaCompletionItem( Kind = kind; IconKind = iconKind; IsDescriptionMarkdown = isDescriptionMarkdown; + _resolveAsync = resolveAsync; } public string Label { get; } @@ -35,5 +41,11 @@ public LuaCompletionItem( public LuaCompletionItemKind Kind { get; } public LuaCompletionIconKind IconKind { get; } public bool IsDescriptionMarkdown { get; } + public bool CanResolve => _resolveAsync is not null; + + public Task ResolveAsync(CancellationToken cancellationToken = default) + => _resolveAsync is null + ? Task.FromResult(this) + : _resolveAsync(cancellationToken); } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs index 0ced1c67cd..55f81db78f 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs @@ -3,6 +3,7 @@ using System.Windows.Data; using System.Windows.Media; using ICSharpCode.AvalonEdit.CodeCompletion; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Lua.Objects { @@ -80,11 +81,5 @@ private static Style CreateItemContainerStyle() return style; } - private static SolidColorBrush CreateFrozenBrush(string colorValue) - { - var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); - brush.Freeze(); - return brush; - } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index fc2b3c5eee..ad64531840 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -36,6 +36,7 @@ + diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 63d1f30173..06b01d459a 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -23,6 +23,7 @@ using TombLib.Scripting.Resources; using TombLib.Scripting.Utils; using TombLib.Scripting.Workers; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Bases { @@ -30,8 +31,8 @@ public abstract class TextEditorBase : TextEditor, IEditorControl, ISupportsFind { private const double ToolTipMaxHeight = 420.0; private const double ToolTipMaxWidth = 540.0; - private const double ToolTipTextMaxWidth = 500.0; - private static readonly double ToolTipTextFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); + protected const double ToolTipTextMaxWidth = 500.0; + protected static readonly double ToolTipTextFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); protected static readonly SolidColorBrush DefaultToolTipBorder = CreateFrozenBrush(Color.FromRgb(96, 96, 96)); protected static readonly SolidColorBrush DefaultToolTipBackground = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); private static readonly SolidColorBrush ErrorToolTipBorder = CreateFrozenBrush(Color.FromRgb(128, 86, 86)); @@ -42,7 +43,7 @@ public abstract class TextEditorBase : TextEditor, IEditorControl, ISupportsFind private static readonly SolidColorBrush InformationToolTipBackground = CreateFrozenBrush(Color.FromRgb(46, 68, 104)); private static readonly SolidColorBrush HintToolTipBorder = CreateFrozenBrush(Color.FromRgb(108, 108, 108)); private static readonly SolidColorBrush HintToolTipBackground = CreateFrozenBrush(Color.FromRgb(58, 58, 58)); - private static readonly SolidColorBrush ToolTipForeground = CreateFrozenBrush(Colors.Gainsboro); + protected static readonly SolidColorBrush ToolTipForeground = CreateFrozenBrush(Colors.Gainsboro); public EditorType EditorType => EditorType.Text; public abstract string DefaultFileExtension { get; } @@ -192,7 +193,7 @@ private void InitializeTimers() private void InitializeToolTip() { _specialToolTip.AllowsTransparency = true; - _specialToolTip.PopupAnimation = PopupAnimation.Fade; + _specialToolTip.PopupAnimation = PopupAnimation.None; _specialToolTip.StaysOpen = true; _specialToolTip.Placement = PlacementMode.RelativePoint; @@ -507,8 +508,11 @@ private void HandleErrorToolTips(MouseEventArgs e) TryShowDiagnosticToolTip(hoveredOffset); } - protected bool TryShowDiagnosticToolTip(int hoveredOffset) + protected bool TryGetDiagnosticInfo(int hoveredOffset, out string message, out TextEditorDiagnosticSeverity severity) { + message = null; + severity = TextEditorDiagnosticSeverity.Error; + if (!LiveErrorUnderlining || _diagnostics.Count == 0) return false; @@ -520,20 +524,33 @@ protected bool TryShowDiagnosticToolTip(int hoveredOffset) if (hoveredDiagnostics.Count == 0) return false; - TextEditorDiagnosticSeverity severity = hoveredDiagnostics + severity = hoveredDiagnostics .OrderBy(diagnostic => diagnostic.Severity) .Select(diagnostic => diagnostic.Severity) .First(); - string message = string.Join(Environment.NewLine + Environment.NewLine, + message = string.Join(Environment.NewLine + Environment.NewLine, hoveredDiagnostics .OrderBy(diagnostic => diagnostic.Severity) .ThenBy(diagnostic => diagnostic.StartOffset) .Select(FormatDiagnosticMessage) .Distinct(StringComparer.Ordinal)); + return true; + } + + protected void ShowDiagnosticToolTip(string message, TextEditorDiagnosticSeverity severity) + { GetDiagnosticToolTipColors(severity, out SolidColorBrush border, out SolidColorBrush background); ShowToolTip(message, border, background, ToolTipForeground); + } + + protected bool TryShowDiagnosticToolTip(int hoveredOffset) + { + if (!TryGetDiagnosticInfo(hoveredOffset, out string message, out TextEditorDiagnosticSeverity severity)) + return false; + + ShowDiagnosticToolTip(message, severity); return true; } @@ -926,7 +943,7 @@ private static bool IsSeverityPrefixed(string message) || message.StartsWith("Diagnostic:", StringComparison.OrdinalIgnoreCase)); private static object CreatePlainToolTipContent(string content, Brush foreground) - => WrapToolTipContent(CreateToolTipTextBlock(content, foreground)); + => MarkdownToolTipRenderer.CreatePlainTextContent(content, foreground); private static object CreateMarkdownToolTipContent(string content, Brush foreground, Brush background) { @@ -938,47 +955,11 @@ private static object CreateMarkdownToolTipContent(string content, Brush foregro return MarkdownToolTipRenderer.CreateContent(normalizedContent, foreground, background); } - private static object WrapToolTipContent(UIElement content) - => new ScrollViewer - { - Content = content, - MaxHeight = ToolTipMaxHeight, - MaxWidth = ToolTipMaxWidth, - VerticalScrollBarVisibility = ScrollBarVisibility.Auto, - HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, - CanContentScroll = true - }; - - private static TextBlock CreateToolTipTextBlock(string content, Brush foreground) - { - var textBlock = CreateBaseToolTipTextBlock(foreground); - textBlock.Text = content ?? string.Empty; - return textBlock; - } - - private static TextBlock CreateBaseToolTipTextBlock(Brush foreground) - => new TextBlock - { - Foreground = foreground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = ToolTipTextFontSize, - TextWrapping = TextWrapping.Wrap, - MaxWidth = ToolTipTextMaxWidth, - Margin = new Thickness(0.0, 0.0, 0.0, 6.0) - }; - private static string NormalizeToolTipLineEndings(string text) => (text ?? string.Empty) .Replace("\r\n", "\n", StringComparison.Ordinal) .Replace('\r', '\n'); - private static SolidColorBrush CreateFrozenBrush(Color color) - { - var brush = new SolidColorBrush(color); - brush.Freeze(); - return brush; - } - private List CollectBookmarkedLines() { var bookmarkedLines = new List(); @@ -1073,7 +1054,7 @@ private static string FormatDiagnosticMessage(TextEditorDiagnostic diagnostic) return diagnostic.Severity.GetLabel() + ":\n" + diagnostic.Message; } - private static void GetDiagnosticToolTipColors(TextEditorDiagnosticSeverity severity, + protected static void GetDiagnosticToolTipColors(TextEditorDiagnosticSeverity severity, out SolidColorBrush border, out SolidColorBrush background) { switch (severity) diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs index 9c46788086..6723c424d3 100644 --- a/TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs @@ -80,10 +80,12 @@ void IModelTokensChangedListener.ModelTokensChanged(ModelTokensChangedEvent e) if (_isDisposed) return; - if (_textView.Dispatcher.CheckAccess()) - _textView.Redraw(); - else - _textView.Dispatcher.BeginInvoke(new Action(_textView.Redraw)); + // Always defer to avoid reentrancy during visual line construction. + _textView.Dispatcher.BeginInvoke(new Action(() => + { + if (!_isDisposed) + _textView.Redraw(); + })); } private static int ClampToLine(int index, int lineLength) diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs index 0406c64ef2..19a373302b 100644 --- a/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs @@ -4,6 +4,7 @@ using System.Windows.Media; using TextMateSharp.Themes; using TextMateFontStyle = TextMateSharp.Themes.FontStyle; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Highlighting { @@ -69,8 +70,9 @@ public TextMateHighlightingStyle Resolve(IList scopes) textDecorations = StrikethroughDecorations; } - Brush brush = foreground > 0 - ? CreateFrozenBrush(_theme.GetColor(foreground)) + string foregroundColor = foreground > 0 ? _theme.GetColor(foreground) : null; + Brush brush = !string.IsNullOrWhiteSpace(foregroundColor) + ? CreateFrozenBrush(foregroundColor) : null; TextMateHighlightingStyle style = new TextMateHighlightingStyle( @@ -83,16 +85,6 @@ public TextMateHighlightingStyle Resolve(IList scopes) return style; } - private static Brush CreateFrozenBrush(string colorValue) - { - if (string.IsNullOrWhiteSpace(colorValue)) - return null; - - var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); - brush.Freeze(); - return brush; - } - private static TextDecorationCollection CreateTextDecorations(TextDecorationCollection source) { var clone = source.Clone(); diff --git a/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs b/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs index 48192defe4..b98b34cd12 100644 --- a/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs @@ -5,15 +5,16 @@ using System.Windows.Media; using TombLib.Scripting.Bases; using TombLib.Scripting.Objects; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Rendering { public sealed class ErrorRenderer : IBackgroundRenderer { - private static readonly Brush ErrorBrush = CreateBrush(Color.FromArgb(224, 220, 76, 60)); - private static readonly Brush WarningBrush = CreateBrush(Color.FromArgb(224, 226, 165, 44)); - private static readonly Brush InformationBrush = CreateBrush(Color.FromArgb(224, 88, 170, 255)); - private static readonly Brush HintBrush = CreateBrush(Color.FromArgb(192, 166, 166, 166)); + private static readonly Brush ErrorBrush = CreateFrozenBrush(Color.FromArgb(224, 220, 76, 60)); + private static readonly Brush WarningBrush = CreateFrozenBrush(Color.FromArgb(224, 226, 165, 44)); + private static readonly Brush InformationBrush = CreateFrozenBrush(Color.FromArgb(224, 88, 170, 255)); + private static readonly Brush HintBrush = CreateFrozenBrush(Color.FromArgb(192, 166, 166, 166)); private static readonly Pen WarningPen = CreatePen(WarningBrush, new double[] { 1.0, 2.0 }); private static readonly Pen InformationPen = CreatePen(InformationBrush, new double[] { 2.0, 2.0 }); private static readonly Pen HintPen = CreatePen(HintBrush, new double[] { 1.0, 3.0 }); @@ -43,7 +44,7 @@ public void Draw(TextView textView, DrawingContext drawingContext) foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment, false)) { - if (rect.Width <= 0.0) + if (rect.Width < 2.0) continue; switch (diagnostic.Severity) @@ -125,13 +126,6 @@ private static void DrawStraightUnderline(DrawingContext drawingContext, Rect re drawingContext.DrawLine(pen, new Point(rect.Left, y), new Point(rect.Right, y)); } - private static Brush CreateBrush(Color color) - { - var brush = new SolidColorBrush(color); - brush.Freeze(); - return brush; - } - private static Pen CreatePen(Brush brush, double[] dashPattern) { var pen = new Pen(brush, 1.5) diff --git a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs index 834941cd8f..2d26e90be6 100644 --- a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs @@ -3,10 +3,12 @@ using System.Diagnostics; using System.Globalization; using System.IO; +using System.Text; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; +using System.Windows.Input; using System.Windows.Media; using System.Xml; using ICSharpCode.AvalonEdit; @@ -15,6 +17,8 @@ using MdXaml; using TombLib.Scripting.Highlighting; using TombLib.Scripting.Resources; +using TombLib.WPF; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Rendering { @@ -33,15 +37,21 @@ public static class MarkdownToolTipRenderer private static readonly double CodeFontSize = Math.Max(BodyFontSize - 1.0, 13.0); private static readonly Brush DefaultForeground = CreateFrozenBrush(Colors.Gainsboro); private static readonly Brush DefaultBackground = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); + private static readonly Brush DefaultLinkForeground = CreateFrozenBrush(Color.FromRgb(112, 192, 231)); + private static readonly HashSet SupportedHyperlinkSchemes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + Uri.UriSchemeHttp, + Uri.UriSchemeHttps + }; private static readonly Lazy LuaHighlighting = new Lazy(LoadLuaHighlighting); - public static FrameworkElement CreateContent(string content, Brush foreground, Brush background) + public static FrameworkElement CreateContent(string content, Brush foreground, Brush background, bool allowScrolling = true) { string normalizedContent = NormalizeLineEndings(content); string originalContent = normalizedContent; if (string.IsNullOrWhiteSpace(normalizedContent)) - return CreateFallbackContent(string.Empty, foreground); + return CreatePlainTextContent(string.Empty, foreground, allowScrolling); try { @@ -54,10 +64,11 @@ public static FrameworkElement CreateContent(string content, Brush foreground, B FlowDocument document = markdown.Transform(normalizedContent); ApplyDocumentTheme(document, foreground); - ReplaceCodeBlocks(document, fencedCodeBlocks, foreground, background); + ReplaceCodeBlocks(document, fencedCodeBlocks, foreground, background, allowScrolling); ApplyInlineCodeTheme(document, foreground, background); + ApplyHyperlinkTheme(document); - return new FlowDocumentScrollViewer + var viewer = new FlowDocumentScrollViewer { Document = document, Background = Brushes.Transparent, @@ -65,21 +76,33 @@ public static FrameworkElement CreateContent(string content, Brush foreground, B Padding = new Thickness(0.0), Margin = new Thickness(0.0), IsToolBarVisible = false, - VerticalScrollBarVisibility = ScrollBarVisibility.Auto, + VerticalScrollBarVisibility = allowScrolling + ? ScrollBarVisibility.Auto + : ScrollBarVisibility.Hidden, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, HorizontalAlignment = HorizontalAlignment.Left, + IsSelectionEnabled = false, Focusable = false, MaxHeight = ToolTipMaxHeight, MaxWidth = ToolTipMaxWidth }; + + if (allowScrolling) + viewer.PreviewMouseWheel += ScrollHost_PreviewMouseWheel; + + viewer.PreviewMouseLeftButtonUp += HyperlinkHost_PreviewMouseLeftButtonUp; + return viewer; } catch (Exception exception) { Debug.WriteLine($"[MarkdownToolTipRenderer] Failed to render markdown tooltip: {exception}"); - return CreateFallbackContent(originalContent, foreground); + return CreatePlainTextContent(originalContent, foreground, allowScrolling); } } + public static FrameworkElement CreatePlainTextContent(string content, Brush foreground, bool allowScrolling = true) + => CreateFallbackContent(content, foreground, allowScrolling); + private static void ApplyDocumentTheme(FlowDocument document, Brush foreground) { document.FontFamily = BodyFontFamily; @@ -93,34 +116,106 @@ private static void ApplyDocumentTheme(FlowDocument document, Brush foreground) private static void ApplyInlineCodeTheme(FlowDocument document, Brush foreground, Brush background) { Brush codeBackground = CreateCodeBackground(background); - var codeSpanElements = new List(); + Brush codeBorder = CreateCodeBorder(background); + var codeSpanElements = new List(); foreach (TextElement element in EnumerateTextElements(document)) { - if (!string.Equals(element.Tag as string, "CodeSpan", StringComparison.Ordinal)) + if (!string.Equals(element.Tag as string, "CodeSpan", StringComparison.Ordinal) + || element is not Inline inline) continue; - codeSpanElements.Add(element); + codeSpanElements.Add(inline); } - foreach (TextElement element in codeSpanElements) + foreach (Inline inline in codeSpanElements) { + string inlineText = NormalizeLineEndings(ExtractInlineText(inline)).TrimEnd('\n'); - string inlineText = NormalizeLineEndings(new TextRange(element.ContentStart, element.ContentEnd).Text).TrimEnd('\n'); + ReplaceInline(inline, CreateInlineCodeContainer(inlineText, foreground, codeBackground, codeBorder)); + } + } - if (element is Span span) - { - span.Inlines.Clear(); - span.Inlines.Add(new Run(" " + inlineText + " ")); - } - else if (element is Run run) + private static string ExtractInlineText(Inline inline) + { + if (inline is null) + return string.Empty; + + switch (inline) + { + case Run run: + return run.Text ?? string.Empty; + + case LineBreak: + return Environment.NewLine; + + case Span span: + var builder = new StringBuilder(); + + foreach (Inline childInline in span.Inlines) + builder.Append(ExtractInlineText(childInline)); + + return builder.ToString(); + + default: + return new TextRange(inline.ContentStart, inline.ContentEnd).Text; + } + } + + private static Inline CreateInlineCodeContainer(string text, Brush foreground, Brush background, Brush borderBrush) + => new InlineUIContainer( + new Border { - run.Text = " " + inlineText + " "; - } + Background = background, + BorderBrush = borderBrush, + BorderThickness = new Thickness(1.0), + CornerRadius = new CornerRadius(2.0), + Padding = new Thickness(4.0, 1.0, 4.0, 1.0), + Child = new TextBlock + { + Text = text ?? string.Empty, + Foreground = foreground ?? DefaultForeground, + FontFamily = CodeFontFamily, + FontSize = CodeFontSize, + TextWrapping = TextWrapping.NoWrap + } + }) + { + BaselineAlignment = BaselineAlignment.Center + }; - element.SetValue(TextElement.FontFamilyProperty, CodeFontFamily); - element.SetValue(TextElement.ForegroundProperty, foreground ?? DefaultForeground); - element.SetValue(TextElement.BackgroundProperty, codeBackground); + private static void ReplaceInline(Inline source, Inline replacement) + { + switch (source?.Parent) + { + case Paragraph paragraph: + paragraph.Inlines.InsertBefore(source, replacement); + paragraph.Inlines.Remove(source); + break; + + case Span span: + span.Inlines.InsertBefore(source, replacement); + span.Inlines.Remove(source); + break; + } + } + + private static void ApplyHyperlinkTheme(FlowDocument document) + { + foreach (TextElement element in EnumerateTextElements(document)) + { + if (element is not Hyperlink hyperlink) + continue; + + bool canOpen = IsSupportedHyperlink(hyperlink.NavigateUri); + + if (!canOpen) + hyperlink.NavigateUri = null; + + hyperlink.Foreground = DefaultLinkForeground; + hyperlink.TextDecorations = TextDecorations.Underline; + hyperlink.Cursor = canOpen ? Cursors.Hand : Cursors.Arrow; + hyperlink.Focusable = false; } } @@ -139,17 +234,17 @@ private static List ExtractFencedCodeBlocks(ref string content) return codeBlocks; } - private static void ReplaceCodeBlocks(FlowDocument document, IReadOnlyList fencedCodeBlocks, Brush foreground, Brush background) + private static void ReplaceCodeBlocks(FlowDocument document, IReadOnlyList fencedCodeBlocks, Brush foreground, Brush background, bool allowScrolling) { var codeBlockLookup = new Dictionary(StringComparer.Ordinal); foreach (CodeBlockInfo codeBlock in fencedCodeBlocks) codeBlockLookup[codeBlock.Placeholder] = codeBlock; - ReplaceCodeBlocks(document.Blocks, codeBlockLookup, foreground, background); + ReplaceCodeBlocks(document.Blocks, codeBlockLookup, foreground, background, allowScrolling); } - private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background) + private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background, bool allowScrolling) { Block currentBlock = blocks.FirstBlock; @@ -157,7 +252,7 @@ private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionar { Block nextBlock = currentBlock.NextBlock; - if (TryCreateReplacementBlock(currentBlock, fencedCodeBlocks, foreground, background, out Block replacementBlock)) + if (TryCreateReplacementBlock(currentBlock, fencedCodeBlocks, foreground, background, allowScrolling, out Block replacementBlock)) { blocks.InsertBefore(currentBlock, replacementBlock); blocks.Remove(currentBlock); @@ -167,19 +262,19 @@ private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionar switch (currentBlock) { case Section section: - ReplaceCodeBlocks(section.Blocks, fencedCodeBlocks, foreground, background); + ReplaceCodeBlocks(section.Blocks, fencedCodeBlocks, foreground, background, allowScrolling); break; case List list: foreach (ListItem item in list.ListItems) - ReplaceCodeBlocks(item.Blocks, fencedCodeBlocks, foreground, background); + ReplaceCodeBlocks(item.Blocks, fencedCodeBlocks, foreground, background, allowScrolling); break; case Table table: foreach (TableRowGroup rowGroup in table.RowGroups) foreach (TableRow row in rowGroup.Rows) foreach (TableCell cell in row.Cells) - ReplaceCodeBlocks(cell.Blocks, fencedCodeBlocks, foreground, background); + ReplaceCodeBlocks(cell.Blocks, fencedCodeBlocks, foreground, background, allowScrolling); break; } } @@ -188,7 +283,7 @@ private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionar } } - private static bool TryCreateReplacementBlock(Block block, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background, out Block replacementBlock) + private static bool TryCreateReplacementBlock(Block block, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background, bool allowScrolling, out Block replacementBlock) { replacementBlock = null; @@ -200,18 +295,18 @@ private static bool TryCreateReplacementBlock(Block block, IReadOnlyDictionary MaxVisibleCodeBlockLines + editor.Height = Math.Min(desiredHeight, maxVisibleHeight); + editor.VerticalScrollBarVisibility = allowScrolling && desiredHeight > maxVisibleHeight ? ScrollBarVisibility.Auto : ScrollBarVisibility.Hidden; + if (allowScrolling) + editor.PreviewMouseWheel += ScrollHost_PreviewMouseWheel; + return new Border { Background = CreateCodeBackground(background), @@ -262,6 +362,7 @@ private static FrameworkElement CreateCodeBlockElement(string language, string c CornerRadius = new CornerRadius(3.0), Padding = new Thickness(8.0, 6.0, 8.0, 6.0), Margin = new Thickness(0.0, 4.0, 0.0, 6.0), + MaxWidth = ToolTipTextMaxWidth, Child = editor }; } @@ -286,6 +387,21 @@ private static double GetEditorLineHeight(TextEditor editor) return Math.Ceiling(Math.Max(1.0, formattedText.Height)); } + private static double MeasureWrappedCodeHeight(string code, double width, double lineHeight) + { + var textBlock = new TextBlock + { + Text = string.IsNullOrEmpty(code) ? " " : code, + FontFamily = CodeFontFamily, + FontSize = CodeFontSize, + TextWrapping = TextWrapping.Wrap, + MaxWidth = width + }; + + textBlock.Measure(new Size(width, double.PositiveInfinity)); + return Math.Max(Math.Ceiling(textBlock.DesiredSize.Height) + 2.0, Math.Ceiling(lineHeight) + 4.0); + } + private static string NormalizeCodeBlockText(string code) { string normalizedCode = NormalizeLineEndings(code); @@ -370,8 +486,9 @@ private static IEnumerable EnumerateInline(Inline inline) yield return element; } - private static FrameworkElement CreateFallbackContent(string content, Brush foreground) - => new TextBlock + private static FrameworkElement CreateFallbackContent(string content, Brush foreground, bool allowScrolling) + { + var textBlock = new TextBlock { Foreground = foreground ?? DefaultForeground, Text = content ?? string.Empty, @@ -381,6 +498,68 @@ private static FrameworkElement CreateFallbackContent(string content, Brush fore MaxWidth = ToolTipTextMaxWidth }; + var scrollViewer = new ScrollViewer + { + Content = textBlock, + MaxHeight = ToolTipMaxHeight, + MaxWidth = ToolTipMaxWidth, + VerticalScrollBarVisibility = allowScrolling + ? ScrollBarVisibility.Auto + : ScrollBarVisibility.Hidden, + HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, + CanContentScroll = true + }; + + if (allowScrolling) + { + scrollViewer.PreviewMouseWheel += ScrollHost_PreviewMouseWheel; + } + + return scrollViewer; + } + + private static void HyperlinkHost_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + Hyperlink hyperlink = (e.OriginalSource as DependencyObject)?.FindAncestorOrSelf(); + + if (hyperlink is not null && TryOpenHyperlink(hyperlink.NavigateUri)) + e.Handled = true; + } + + private static bool TryOpenHyperlink(Uri uri) + { + if (!IsSupportedHyperlink(uri)) + return false; + + try + { + Process.Start(new ProcessStartInfo(uri.AbsoluteUri) { UseShellExecute = true }); + return true; + } + catch + { + return false; + } + } + + private static bool IsSupportedHyperlink(Uri uri) + => uri is not null && uri.IsAbsoluteUri && SupportedHyperlinkSchemes.Contains(uri.Scheme); + + private static void ScrollHost_PreviewMouseWheel(object sender, MouseWheelEventArgs e) + { + ScrollViewer scrollViewer = sender as ScrollViewer ?? (sender as DependencyObject)?.FindVisualDescendant(); + + if (scrollViewer is null || scrollViewer.ScrollableHeight <= 0.0) + return; + + if (e.Delta > 0) + scrollViewer.LineUp(); + else if (e.Delta < 0) + scrollViewer.LineDown(); + + e.Handled = true; + } + private static string NormalizeLineEndings(string text) => (text ?? string.Empty) .Replace("\r\n", "\n", StringComparison.Ordinal) @@ -461,13 +640,6 @@ private static Color Blend(Color first, Color second, double ratio) (byte)Math.Round(first.B * inverseRatio + second.B * clampedRatio)); } - private static SolidColorBrush CreateFrozenBrush(Color color) - { - var brush = new SolidColorBrush(color); - brush.Freeze(); - return brush; - } - private sealed class CodeBlockInfo { public CodeBlockInfo(string placeholder, string language, string code) diff --git a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj index efc49f7ca1..6e08d2b09b 100644 --- a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj +++ b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj @@ -46,5 +46,6 @@ + \ No newline at end of file diff --git a/TombLib/TombLib.WPF/BrushHelpers.cs b/TombLib/TombLib.WPF/BrushHelpers.cs index 0c2f454646..bbb11d0c90 100644 --- a/TombLib/TombLib.WPF/BrushHelpers.cs +++ b/TombLib/TombLib.WPF/BrushHelpers.cs @@ -4,13 +4,20 @@ namespace TombLib.WPF; public static class BrushHelpers { - public static Brush CreateFrozenBrush(Color color) + public static SolidColorBrush CreateFrozenBrush(Color color) { var brush = new SolidColorBrush(color); brush.Freeze(); return brush; } + public static SolidColorBrush CreateFrozenBrush(string colorValue) + { + var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); + brush.Freeze(); + return brush; + } + public static Pen CreateFrozenPen(Brush brush, double thickness) { var pen = new Pen(brush, thickness); diff --git a/TombLib/TombLib.WPF/DependencyObjectExtensions.cs b/TombLib/TombLib.WPF/DependencyObjectExtensions.cs new file mode 100644 index 0000000000..2ec23ce2e1 --- /dev/null +++ b/TombLib/TombLib.WPF/DependencyObjectExtensions.cs @@ -0,0 +1,110 @@ +using System.Windows; +using System.Windows.Media; +using System.Windows.Media.Media3D; + +namespace TombLib.WPF; + +public static class DependencyObjectExtensions +{ + public static T? FindVisualAncestor(this DependencyObject? dependencyObject) where T : DependencyObject + { + DependencyObject? ancestor = dependencyObject; + + do + ancestor = GetVisualParent(ancestor); + while (ancestor is not null and not T); + + return ancestor as T; + } + + public static T? FindVisualAncestorOrSelf(this DependencyObject? dependencyObject) where T : DependencyObject + { + if (dependencyObject is T self) + return self; + + return dependencyObject.FindVisualAncestor(); + } + + public static T? FindAncestor(this DependencyObject? dependencyObject) where T : DependencyObject + { + DependencyObject? ancestor = dependencyObject; + + do + ancestor = GetParentElement(ancestor); + while (ancestor is not null and not T); + + return ancestor as T; + } + + public static T? FindAncestorOrSelf(this DependencyObject? dependencyObject) where T : DependencyObject + { + if (dependencyObject is T self) + return self; + + return dependencyObject.FindAncestor(); + } + + public static T? FindVisualDescendant(this DependencyObject? dependencyObject) where T : DependencyObject + { + if (dependencyObject is null) + return null; + + if (dependencyObject is T self) + return self; + + if (!HasVisualChildren(dependencyObject)) + return null; + + int childCount = VisualTreeHelper.GetChildrenCount(dependencyObject); + + for (int i = 0; i < childCount; i++) + { + T? descendant = VisualTreeHelper.GetChild(dependencyObject, i).FindVisualDescendant(); + + if (descendant is not null) + return descendant; + } + + return null; + } + + public static bool IsDescendantOf(this DependencyObject? dependencyObject, DependencyObject? ancestor) + { + while (dependencyObject is not null) + { + if (ReferenceEquals(dependencyObject, ancestor)) + return true; + + dependencyObject = GetParentElement(dependencyObject); + } + + return false; + } + + private static DependencyObject? GetParentElement(DependencyObject? dependencyObject) + { + if (dependencyObject is null) + return null; + + if (dependencyObject is FrameworkContentElement contentElement) + return contentElement.Parent; + + DependencyObject? visualParent = GetVisualParent(dependencyObject); + + if (visualParent is not null) + return visualParent; + + return LogicalTreeHelper.GetParent(dependencyObject); + } + + private static DependencyObject? GetVisualParent(DependencyObject? dependencyObject) + { + if (dependencyObject is not Visual && dependencyObject is not Visual3D) + return null; + + return VisualTreeHelper.GetParent(dependencyObject); + } + + private static bool HasVisualChildren(DependencyObject dependencyObject) + => dependencyObject is Visual || dependencyObject is Visual3D; +} \ No newline at end of file From e84cc2e35297a6f2df394f77f13b571544730e63 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 11:48:06 +0100 Subject: [PATCH 04/34] Refactor pass 1 --- .../LuaStudio.Intellisense.cs | 18 +- TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs | 4 +- .../LuaLanguageServerClient.cs | 5 +- .../LuaLanguageServerIntellisenseProvider.cs | 18 +- .../Settings/LuaSettingsControl.cs | 52 +- .../LuaEditor.Completion.cs | 353 +++++++++++ .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 135 +++++ .../LuaEditor.Intellisense.cs | 565 +----------------- .../LuaEditor.Navigation.cs | 13 +- .../LuaEditor.SemanticHighlighting.cs | 6 +- .../LuaEditor.SignatureHelp.cs | 57 ++ TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 34 +- .../LuaEditorConfiguration.cs | 33 +- .../Objects/ColorScheme.cs | 43 +- .../Objects/LuaCompletionData.cs | 5 +- .../Objects/LuaDefinitionLocation.cs | 4 +- .../Objects/SyntaxHighlighting.cs | 122 ++-- .../TombEngineLanguageScriptService.cs | 89 +-- .../Utils/Autocomplete.cs | 7 - .../Utils/LuaLineParser.cs | 121 ++++ .../TombEngineLanguageScriptServiceTests.cs | 17 + 21 files changed, 874 insertions(+), 827 deletions(-) create mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs create mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/Utils/Autocomplete.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 5689f753bc..6fc63ca757 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Windows.Forms; using ICSharpCode.AvalonEdit.Document; @@ -52,7 +51,8 @@ private void EditorTabControl_LuaFileOpened(object sender, EventArgs e) return; editor.IntellisenseProvider = _intellisenseProvider; - editor.DefinitionNavigationRequested = NavigateToDefinition; + editor.DefinitionNavigationRequested -= NavigateToDefinition; + editor.DefinitionNavigationRequested += NavigateToDefinition; editor.TextChangedDelayed -= LuaEditor_TextChangedDelayed; editor.TextChangedDelayed += LuaEditor_TextChangedDelayed; @@ -75,18 +75,11 @@ private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyL return; } - bool matched = false; - foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) { if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) - { ApplyDiagnosticsToEditor(editor, diagnostics); - matched = true; - } } - - Debug.WriteLine($"[LuaLS] DiagnosticsUpdated for '{filePath}': {diagnostics?.Count ?? 0} items, tab matched={matched}."); } private void IntellisenseProvider_SemanticTokensUpdated(string filePath, IReadOnlyList semanticTokens) @@ -126,12 +119,7 @@ private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) } private static void ApplyDiagnosticsToEditor(LuaEditor editor, IReadOnlyList diagnostics) - { - int count = editor.LiveErrorUnderlining ? (diagnostics?.Count ?? 0) : 0; - Debug.WriteLine($"[LuaLS] Applying {count} diagnostics to '{editor.FilePath}' (LiveErrorUnderlining={editor.LiveErrorUnderlining})."); - - editor.SetDiagnostics(editor.LiveErrorUnderlining ? diagnostics : Array.Empty()); - } + => editor.SetDiagnostics(editor.LiveErrorUnderlining ? diagnostics : Array.Empty()); private static void ApplySemanticTokensToEditor(LuaEditor editor, IReadOnlyList semanticTokens) => editor.SetSemanticTokens(semanticTokens ?? Array.Empty()); diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs index 7903600f20..30bd943273 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs @@ -136,9 +136,9 @@ private void AppendScript(ScriptGenerationResult result, CreateGeneratedFiles(result.FilesToCreate); } - catch + catch (Exception exception) { - // Oh well... + Debug.WriteLine($"[LuaStudio] Failed to append generated Lua script output: {exception}"); } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index 79bc0d71d3..80c7231e09 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -554,7 +554,10 @@ private void Process_Exited(object sender, EventArgs e) } IsReady = false; - Debug.WriteLine($"[LuaLS] Process exited unexpectedly{(exitCode is not null ? $" with code {exitCode.Value}" : string.Empty)}."); + + if (!_isDisposed) + Debug.WriteLine($"[LuaLS] Process exited unexpectedly{(exitCode is not null ? $" with code {exitCode.Value}" : string.Empty)}."); + FailPendingRequests(new IOException("The Lua language server process exited unexpectedly.")); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index 7c0d8d0b5b..c7d9db2496 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -170,7 +170,7 @@ public async Task GetDefinitionAsync(string filePath, str if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) { - Debug.WriteLine($"[LuaLS] Definition request aborted: document sync failed for '{filePath}'."); + Debug.WriteLine($"[LuaLS] Definition request skipped because document sync failed for '{filePath}'."); return null; } @@ -181,9 +181,7 @@ public async Task GetDefinitionAsync(string filePath, str position = new { line, character = column } }, cancellationToken).ConfigureAwait(false); - LuaDefinitionLocation result = LuaLanguageServerResponseParser.ParseDefinitionLocation(response); - Debug.WriteLine($"[LuaLS] Definition at ({line},{column}): {(result is not null ? $"'{result.FilePath}' L{result.LineNumber}" : "null")}."); - return result; + return LuaLanguageServerResponseParser.ParseDefinitionLocation(response); } public async Task GetSignatureHelpAsync(string filePath, string content, @@ -228,7 +226,9 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) _startupSucceeded = await _client.StartAsync(cancellationToken).ConfigureAwait(false); - Debug.WriteLine($"[LuaLS] Server startup result: {_startupSucceeded}."); + if (!_startupSucceeded) + Debug.WriteLine("[LuaLS] Failed to start the Lua language server."); + return _startupSucceeded; } finally @@ -368,7 +368,7 @@ private void HandleDiagnosticsPublished(JsonElement parameters) { if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters, out string filePath)) { - Debug.WriteLine("[LuaLS] Diagnostics rejected: unable to resolve file path."); + Debug.WriteLine("[LuaLS] Diagnostics could not be matched to a local file path."); return; } @@ -377,17 +377,13 @@ private void HandleDiagnosticsPublished(JsonElement parameters) if (!LuaLanguageServerDiagnosticsParser.TryParse(parameters, filePath, document?.Content, document?.Version ?? 0, out LuaPublishedDiagnostics publishedDiagnostics)) { - Debug.WriteLine($"[LuaLS] Diagnostics rejected for '{filePath}'."); + Debug.WriteLine($"[LuaLS] Diagnostics payload could not be parsed for '{filePath}'."); return; } if (!_documents.TryStoreDiagnostics(publishedDiagnostics)) - { - Debug.WriteLine($"[LuaLS] Diagnostics ignored as stale for '{publishedDiagnostics.FilePath}'."); return; - } - Debug.WriteLine($"[LuaLS] Publishing {publishedDiagnostics.Diagnostics.Count} diagnostics for '{publishedDiagnostics.FilePath}'."); DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs index 290814c554..cdf9018612 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs @@ -102,6 +102,9 @@ private void comboBox_FontFamily_SelectedIndexChanged(object sender, EventArgs e private void comboBox_ColorSchemes_SelectedIndexChanged(object sender, EventArgs e) { + if (comboBox_ColorSchemes.SelectedItem is null) + return; + if (comboBox_ColorSchemes.Items.Count == 1) button_DeleteScheme.Enabled = false; // Disallow deleting the last available scheme @@ -131,19 +134,10 @@ private void menuItem_Italic_Click(object sender, EventArgs e) private void button_SaveScheme_Click(object sender, EventArgs e) { - using (var form = new FormSaveSchemeAs(ColorSchemeType.GameFlowScript)) + using (var form = new FormSaveSchemeAs(ColorSchemeType.Lua)) if (form.ShowDialog(this) == DialogResult.OK) { - var currentScheme = new ColorScheme - { - Values = (HighlightingObject)colorButton_Values.Tag, - Operators = (HighlightingObject)colorButton_Operators.Tag, - SpecialOperators = (HighlightingObject)colorButton_SpecialOperators.Tag, - Statements = (HighlightingObject)colorButton_Statements.Tag, - Comments = (HighlightingObject)colorButton_Comments.Tag, - Background = ColorTranslator.ToHtml(colorButton_Background.BackColor), - Foreground = ColorTranslator.ToHtml(colorButton_Foreground.BackColor) - }; + ColorScheme currentScheme = CreateCurrentScheme(); XmlUtils.WriteXmlFile(form.SchemeFilePath, currentScheme); @@ -247,7 +241,8 @@ public void ApplySettings(LuaEditorConfiguration config) ApplySettingsFromCheckBoxes(config); - //config.SelectedColorSchemeName = comboBox_ColorSchemes.SelectedItem.ToString(); + if (comboBox_ColorSchemes.SelectedItem is not null) + config.SelectedColorSchemeName = comboBox_ColorSchemes.SelectedItem.ToString(); config.Save(); } @@ -323,16 +318,7 @@ private void ChangeColor(DarkButton targetButton) private void UpdatePreview() { - var currentScheme = new ColorScheme - { - Values = (HighlightingObject)colorButton_Values.Tag, - Operators = (HighlightingObject)colorButton_Operators.Tag, - SpecialOperators = (HighlightingObject)colorButton_SpecialOperators.Tag, - Statements = (HighlightingObject)colorButton_Statements.Tag, - Comments = (HighlightingObject)colorButton_Comments.Tag, - Background = ColorTranslator.ToHtml(colorButton_Background.BackColor), - Foreground = ColorTranslator.ToHtml(colorButton_Foreground.BackColor) - }; + ColorScheme currentScheme = CreateCurrentScheme(); bool itemFound = false; @@ -386,12 +372,25 @@ private void UpdateColorButtons(ColorScheme scheme) UpdateColorButtonStyleText(colorButton_SpecialOperators); UpdateColorButtonStyleText(colorButton_Statements); UpdateColorButtonStyleText(colorButton_Comments); - UpdateColorButtonStyleText(colorButton_Comments); colorButton_Background.BackColor = ColorTranslator.FromHtml(scheme.Background); colorButton_Foreground.BackColor = ColorTranslator.FromHtml(scheme.Foreground); } + private ColorScheme CreateCurrentScheme() + { + return new ColorScheme + { + Values = (HighlightingObject)colorButton_Values.Tag, + Operators = (HighlightingObject)colorButton_Operators.Tag, + SpecialOperators = (HighlightingObject)colorButton_SpecialOperators.Tag, + Statements = (HighlightingObject)colorButton_Statements.Tag, + Comments = (HighlightingObject)colorButton_Comments.Tag, + Background = ColorTranslator.ToHtml(colorButton_Background.BackColor), + Foreground = ColorTranslator.ToHtml(colorButton_Foreground.BackColor) + }; + } + private void buttonContextMenu_Opening(object sender, CancelEventArgs e) { var sourceButton = (DarkButton)((DarkContextMenu)sender).SourceControl; @@ -459,6 +458,13 @@ private void UpdatePreviewColors(ColorScheme scheme) private void ToggleSaveSchemeButton() { + if (comboBox_ColorSchemes.SelectedItem is null) + { + button_SaveScheme.Enabled = false; + button_SaveScheme.Visible = false; + return; + } + bool isUntitled = comboBox_ColorSchemes.SelectedItem.ToString().Equals("~UNTITLED", StringComparison.OrdinalIgnoreCase); button_SaveScheme.Enabled = isUntitled; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs new file mode 100644 index 0000000000..83e56a28f7 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -0,0 +1,353 @@ +using System; +using System.Diagnostics; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Interop; +using System.Windows.Threading; +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Utils; +using TombLib.WPF; + +namespace TombLib.Scripting.Lua +{ + public sealed partial class LuaEditor + { + private static readonly FieldInfo CompletionToolTipField = + typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); + + private static bool _completionToolTipFieldLoggedMissing; + + private CancellationTokenSource _completionCancellationTokenSource; + private CancellationTokenSource _completionToolTipCancellationTokenSource; + private int _completionRequestToken; + private int _completionToolTipUpdateToken; + + private void CloseCompletionWindow() + { + CancelCompletionToolTipUpdate(); + + if (_completionWindow is null) + return; + + if (CompletionToolTipField?.GetValue(_completionWindow) is ToolTip tooltip) + tooltip.IsOpen = false; + + _completionWindow.Close(); + _completionWindow = null; + } + + private void InitializeLuaCompletionWindow() + { + InitializeCompletionWindow(420, 320); + LuaCompletionWindowStyle.Apply(_completionWindow); + StyleCompletionTooltip(); + MakeCompletionWindowNonActivatable(); + } + + private async Task RequestCompletionAsync(int offset, char? triggerCharacter) + { + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionCancellationTokenSource); + int requestToken = ++_completionRequestToken; + + try + { + if (!IsIntellisenseAvailable()) + return; + + (int line, int column) = GetPositionFromOffset(offset); + var items = await IntellisenseProvider + .GetCompletionItemsAsync(FilePath, Text, line, column, triggerCharacter, cancellationToken) + .ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + return; + + if (items is null || items.Count == 0) + { + CloseCompletionWindow(); + return; + } + + var completionDataItems = new LuaCompletionData[items.Count]; + + for (int i = 0; i < items.Count; i++) + completionDataItems[i] = new LuaCompletionData(items[i]); + + if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + return; + + CloseCompletionWindow(); + + InitializeLuaCompletionWindow(); + SetCompletionWindowOffsets(offset); + + foreach (LuaCompletionData completionDataItem in completionDataItems) + _completionWindow.CompletionList.CompletionData.Add(completionDataItem); + + if (_completionWindow.CompletionList.CompletionData.Count > 0) + { + ShowCompletionWindow(); + ScheduleInitialSelection(); + } + } + catch (OperationCanceledException) + { + } + catch (Exception exception) + { + CloseCompletionWindow(); + WriteDebugFailure("Completion request", exception); + } + } + + private bool IsValidAutocompleteContext(int offset, char? triggerCharacter) + { + if (offset <= 0 || Document is null || Document.TextLength == 0) + return false; + + if (IsInsideCommentOrString(offset)) + return false; + + if (triggerCharacter is '.' || triggerCharacter is ':') + return true; + + char typedCharacter = Document.GetCharAt(offset - 1); + + if (!IsIdentifierCharacter(typedCharacter)) + return false; + + if (offset >= 2) + { + char previousCharacter = Document.GetCharAt(offset - 2); + + if (previousCharacter == '.') + return false; + } + + return true; + } + + private bool IsInsideCommentOrString(int offset) + { + DocumentLine currentLine = Document.GetLineByOffset(Math.Max(0, Math.Min(offset, Document.TextLength))); + int lineStart = currentLine.Offset; + int inspectedLength = Math.Max(0, Math.Min(offset, currentLine.EndOffset) - lineStart); + string lineText = Document.GetText(lineStart, inspectedLength); + + return LuaLineParser.IsInsideCommentOrString(lineText); + } + + private void StyleCompletionTooltip() + { + if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; + + if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) + { + if (!_completionToolTipFieldLoggedMissing) + { + _completionToolTipFieldLoggedMissing = true; + Debug.WriteLine("[Lua] AvalonEdit completion tooltip styling is unavailable because the internal tooltip field could not be found."); + } + + return; + } + + tooltip.Background = DefaultToolTipBackground; + tooltip.BorderBrush = DefaultToolTipBorder; + tooltip.BorderThickness = new Thickness(0.0); + tooltip.Padding = new Thickness(0.0); + tooltip.PlacementTarget = listBox; + tooltip.Placement = PlacementMode.Right; + tooltip.HorizontalOffset = 10.0; + tooltip.StaysOpen = true; + + listBox.SelectionChanged += (s, e) => ScheduleCompletionTooltipUpdate(tooltip); + listBox.PreviewMouseLeftButtonUp += (s, e) => HandleCompletionListClick(listBox, tooltip, e); + } + + private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) + { + ListBoxItem listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); + + if (listBoxItem is null) + return; + + if (!ReferenceEquals(listBox.SelectedItem, listBoxItem.DataContext)) + listBox.SelectedItem = listBoxItem.DataContext; + + listBox.ScrollIntoView(listBoxItem.DataContext); + ScheduleCompletionTooltipUpdate(tooltip); + } + + private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) + { + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionToolTipCancellationTokenSource); + int updateToken = ++_completionToolTipUpdateToken; + + Dispatcher.BeginInvoke( + new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, cancellationToken, updateToken)), + DispatcherPriority.Background); + } + + private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationToken cancellationToken, int updateToken) + { + if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; + + ICompletionData item = listBox.SelectedItem as ICompletionData; + + if (item is null) + { + tooltip.IsOpen = false; + return; + } + + try + { + object description = item.Description; + + if (description is not null) + ApplyCompletionToolTipContent(tooltip, description); + else + tooltip.IsOpen = false; + + if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) + { + object resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested || updateToken != _completionToolTipUpdateToken) + return; + + if (_completionWindow?.CompletionList.ListBox is not ListBox currentListBox + || !ReferenceEquals(currentListBox, listBox) + || !ReferenceEquals(currentListBox.SelectedItem, item)) + { + return; + } + + if (resolvedDescription is not null) + ApplyCompletionToolTipContent(tooltip, resolvedDescription); + else + tooltip.IsOpen = false; + } + } + catch (OperationCanceledException) + { + } + catch (Exception exception) + { + tooltip.IsOpen = false; + WriteDebugFailure("Completion tooltip update", exception); + } + } + + private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) + { + tooltip.Content = content; + if (!tooltip.IsOpen) + tooltip.IsOpen = true; + else + { + tooltip.InvalidateMeasure(); + tooltip.InvalidateVisual(); + } + } + + private void CancelCompletionToolTipUpdate() + { + CancelAndDispose(ref _completionToolTipCancellationTokenSource); + _completionToolTipUpdateToken++; + } + + private void ScheduleCloseIfEmpty() + => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); + + private void ScheduleInitialSelection() + => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.ContextIdle); + + private void SelectInitialItem() + { + if (_completionWindow is null) + return; + + _completionWindow.CompletionList.SelectItem(GetCompletionWindowQuery()); + CloseCompletionWindowIfEmpty(); + } + + private void MakeCompletionWindowNonActivatable() + { + _completionWindow.SourceInitialized += (s, e) => + { + if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) + source.AddHook(CompletionWindowWndProc); + }; + } + + private static IntPtr CompletionWindowWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + const int WM_MOUSEACTIVATE = 0x0021; + const int MA_NOACTIVATE = 3; + + if (msg == WM_MOUSEACTIVATE) + { + handled = true; + return new IntPtr(MA_NOACTIVATE); + } + + return IntPtr.Zero; + } + + private bool CloseCompletionWindowIfEmpty() + { + if (_completionWindow is null) + return false; + + ListBox listBox = _completionWindow.CompletionList.ListBox; + + if (listBox is null || listBox.HasItems) + return false; + + CloseCompletionWindow(); + return true; + } + + private string GetCompletionWindowQuery() + { + if (_completionWindow is null || Document is null) + return string.Empty; + + int startOffset = Math.Max(0, Math.Min(_completionWindow.StartOffset, Document.TextLength)); + int endOffset = Math.Max(startOffset, Math.Min(_completionWindow.EndOffset, Document.TextLength)); + + return endOffset > startOffset + ? Document.GetText(startOffset, endOffset - startOffset) + : string.Empty; + } + + private void SetCompletionWindowOffsets(int offset) + { + int startOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + + while (startOffset > 0) + { + char currentChar = Document.GetCharAt(startOffset - 1); + + if (char.IsLetterOrDigit(currentChar) || currentChar == '_') + startOffset--; + else + break; + } + + _completionWindow.StartOffset = startOffset; + _completionWindow.EndOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs new file mode 100644 index 0000000000..31a08f74e1 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -0,0 +1,135 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Objects; +using TombLib.Scripting.Rendering; + +namespace TombLib.Scripting.Lua +{ + public sealed partial class LuaEditor + { + private CancellationTokenSource _hoverCancellationTokenSource; + private int _hoverRequestToken; + + protected override async void HandleMouseHover(MouseEventArgs e) + { + int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); + + if (hoveredOffset == -1) + return; + + bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); + + if (!IsIntellisenseAvailable()) + { + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + + return; + } + + string hoveredWord = GetWordFromOffset(hoveredOffset); + + if (string.IsNullOrWhiteSpace(hoveredWord)) + { + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + + return; + } + + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _hoverCancellationTokenSource); + int hoverRequestToken = ++_hoverRequestToken; + + try + { + LuaHoverInfo hoverInfo = await RequestHoverAsync(hoveredOffset, cancellationToken).ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) + return; + + int currentHoveredOffset = GetOffsetFromPoint(Mouse.GetPosition(this)); + + if (currentHoveredOffset != hoveredOffset) + return; + + bool hasHover = hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content); + + if (hasHover && hasDiagnostic) + ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); + else if (hasHover) + ShowHoverToolTip(hoverInfo); + else if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + } + catch (OperationCanceledException) + { + } + catch (Exception exception) + { + WriteDebugFailure("Hover request", exception); + + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + } + } + + private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) + { + GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); + + var panel = new StackPanel { MaxWidth = ToolTipTextMaxWidth }; + + panel.Children.Add(CreateHoverToolTipContent(hoverInfo)); + + panel.Children.Add(new Border + { + Background = diagnosticBackground, + BorderBrush = diagnosticBorder, + BorderThickness = new Thickness(1.0), + CornerRadius = new CornerRadius(3.0), + Padding = new Thickness(8.0, 4.0, 8.0, 4.0), + Margin = new Thickness(0.0, 6.0, 0.0, 0.0), + Child = new TextBlock + { + Text = diagnosticMessage, + Foreground = ToolTipForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = ToolTipTextFontSize, + TextWrapping = TextWrapping.Wrap, + MaxWidth = ToolTipTextMaxWidth + } + }); + + ShowToolTip(panel, DefaultToolTipBorder, DefaultToolTipBackground); + } + + private void ShowHoverToolTip(LuaHoverInfo hoverInfo) + => ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); + + private FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) + { + if (hoverInfo.IsMarkdown) + return MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground); + + return MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); + } + + private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) + { + if (!IsIntellisenseAvailable()) + return null; + + (int line, int column) = GetPositionFromOffset(offset); + + return await IntellisenseProvider + .GetHoverAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index d4fc075273..fe70a211b0 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -1,35 +1,14 @@ using System; -using System.Reflection; +using System.Diagnostics; using System.Threading; -using System.Threading.Tasks; using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; using System.Windows.Input; -using System.Windows.Interop; -using System.Windows.Media; -using System.Windows.Threading; -using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; -using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Objects; -using TombLib.Scripting.Rendering; -using TombLib.WPF; namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private static readonly FieldInfo CompletionToolTipField = - typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); - - private CancellationTokenSource _hoverCancellationTokenSource; - private CancellationTokenSource _completionCancellationTokenSource; - private CancellationTokenSource _completionToolTipCancellationTokenSource; - private CancellationTokenSource _signatureCancellationTokenSource; - private int _completionRequestToken; - private int _completionToolTipUpdateToken; - private int _hoverRequestToken; private Window _hostWindow; private void BindLuaIntellisenseEvents() @@ -77,26 +56,19 @@ private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) _textMateHighlighting?.Dispose(); _textMateHighlighting = null; - _hoverCancellationTokenSource?.Cancel(); - _hoverCancellationTokenSource?.Dispose(); - _hoverCancellationTokenSource = null; - - _completionCancellationTokenSource?.Cancel(); - _completionCancellationTokenSource?.Dispose(); - _completionCancellationTokenSource = null; + CancelAndDispose(ref _hoverCancellationTokenSource); + CancelAndDispose(ref _completionCancellationTokenSource); CancelCompletionToolTipUpdate(); - _signatureCancellationTokenSource?.Cancel(); - _signatureCancellationTokenSource?.Dispose(); - _signatureCancellationTokenSource = null; + CancelAndDispose(ref _signatureCancellationTokenSource); if (_hostWindow is not null) _hostWindow.Deactivated -= HostWindow_Deactivated; _hostWindow = null; - DismissSignatureHelp(); + DismissTransientToolTips(); ClearDiagnostics(); ClearSemanticTokens(); @@ -153,111 +125,6 @@ private async void TextArea_TextEntered(object sender, TextCompositionEventArgs await RequestCompletionAsync(CaretOffset, triggerCharacter).ConfigureAwait(true); } - protected override async void HandleMouseHover(MouseEventArgs e) - { - int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); - - if (hoveredOffset == -1) - return; - - bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); - - if (!IsIntellisenseAvailable()) - { - if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); - - return; - } - - string hoveredWord = GetWordFromOffset(hoveredOffset); - - if (string.IsNullOrWhiteSpace(hoveredWord)) - { - if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); - - return; - } - - _hoverCancellationTokenSource?.Cancel(); - _hoverCancellationTokenSource?.Dispose(); - - _hoverCancellationTokenSource = new CancellationTokenSource(); - CancellationToken cancellationToken = _hoverCancellationTokenSource.Token; - int hoverRequestToken = ++_hoverRequestToken; - - try - { - LuaHoverInfo hoverInfo = await RequestHoverAsync(hoveredOffset, cancellationToken).ConfigureAwait(true); - - if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) - return; - - int currentHoveredOffset = GetOffsetFromPoint(Mouse.GetPosition(this)); - - if (currentHoveredOffset != hoveredOffset) - return; - - bool hasHover = hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content); - - if (hasHover && hasDiagnostic) - ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); - else if (hasHover) - ShowHoverToolTip(hoverInfo); - else if (hasDiagnostic) - { - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); - } - } - catch - { - if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); - } - } - - private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) - { - GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); - - var panel = new StackPanel { MaxWidth = ToolTipTextMaxWidth }; - - panel.Children.Add(CreateHoverToolTipContent(hoverInfo)); - - panel.Children.Add(new Border - { - Background = diagnosticBackground, - BorderBrush = diagnosticBorder, - BorderThickness = new Thickness(1.0), - CornerRadius = new CornerRadius(3.0), - Padding = new Thickness(8.0, 4.0, 8.0, 4.0), - Margin = new Thickness(0.0, 6.0, 0.0, 0.0), - Child = new TextBlock - { - Text = diagnosticMessage, - Foreground = ToolTipForeground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = ToolTipTextFontSize, - TextWrapping = TextWrapping.Wrap, - MaxWidth = ToolTipTextMaxWidth - } - }); - - ShowToolTip(panel, DefaultToolTipBorder, DefaultToolTipBackground); - } - - private void ShowHoverToolTip(LuaHoverInfo hoverInfo) - => ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); - - private FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) - { - if (hoverInfo.IsMarkdown) - return MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground); - - return MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); - } - private bool IsIntellisenseAvailable() => IntellisenseProvider is not null && IntellisenseProvider.IsAvailable && !string.IsNullOrWhiteSpace(FilePath); @@ -282,411 +149,20 @@ private static bool TryGetCompletionTrigger(string inputText, out char? triggerC private static bool ShouldKeepCompletionWindowOpen(string inputText) => inputText?.Length == 1 && (char.IsLetterOrDigit(inputText[0]) || inputText[0] == '_'); - private void CloseCompletionWindow() - { - CancelCompletionToolTipUpdate(); - - if (_completionWindow is null) - return; - - if (CompletionToolTipField?.GetValue(_completionWindow) is ToolTip tooltip) - tooltip.IsOpen = false; - - _completionWindow.Close(); - _completionWindow = null; - } - - private void InitializeLuaCompletionWindow() - { - InitializeCompletionWindow(420, 320); - LuaCompletionWindowStyle.Apply(_completionWindow); - StyleCompletionTooltip(); - MakeCompletionWindowNonActivatable(); - } - - private async Task RequestCompletionAsync(int offset, char? triggerCharacter) - { - _completionCancellationTokenSource?.Cancel(); - _completionCancellationTokenSource?.Dispose(); - _completionCancellationTokenSource = new CancellationTokenSource(); - - CancellationToken cancellationToken = _completionCancellationTokenSource.Token; - int requestToken = ++_completionRequestToken; - - try - { - if (!IsIntellisenseAvailable()) - return; - - (int line, int column) = GetPositionFromOffset(offset); - var items = await IntellisenseProvider - .GetCompletionItemsAsync(FilePath, Text, line, column, triggerCharacter, cancellationToken) - .ConfigureAwait(true); - - if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) - return; - - if (items is null || items.Count == 0) - { - CloseCompletionWindow(); - return; - } - - var completionDataItems = new LuaCompletionData[items.Count]; - - for (int i = 0; i < items.Count; i++) - completionDataItems[i] = new LuaCompletionData(items[i]); - - if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) - return; - - CloseCompletionWindow(); - - InitializeLuaCompletionWindow(); - SetCompletionWindowOffsets(offset); - - foreach (LuaCompletionData completionDataItem in completionDataItems) - _completionWindow.CompletionList.CompletionData.Add(completionDataItem); - - if (_completionWindow.CompletionList.CompletionData.Count > 0) - { - ShowCompletionWindow(); - ScheduleInitialSelection(); - } - } - catch - { - CloseCompletionWindow(); - // Ignore completion failures and keep the editor responsive. - } - } - - private bool IsValidAutocompleteContext(int offset, char? triggerCharacter) - { - if (offset <= 0 || Document is null) - return false; - - if (IsInsideCommentOrString(offset)) - return false; - - if (triggerCharacter is '.' || triggerCharacter is ':') - return true; - - char typedCharacter = Document.GetCharAt(offset - 1); - - if (!IsIdentifierCharacter(typedCharacter)) - return false; - - if (offset >= 2) - { - char previousCharacter = Document.GetCharAt(offset - 2); - - if (previousCharacter == '.') - return false; - } - - return true; - } - - private bool IsInsideCommentOrString(int offset) - { - DocumentLine currentLine = Document.GetLineByOffset(Math.Max(0, Math.Min(offset, Document.TextLength))); - int lineStart = currentLine.Offset; - int inspectedLength = Math.Max(0, Math.Min(offset, currentLine.EndOffset) - lineStart); - string lineText = Document.GetText(lineStart, inspectedLength); - - bool isInsideSingleQuotedString = false; - bool isInsideDoubleQuotedString = false; - bool isEscaped = false; - - for (int i = 0; i < lineText.Length; i++) - { - char currentChar = lineText[i]; - - if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && currentChar == '-' - && i + 1 < lineText.Length && lineText[i + 1] == '-') - { - return true; - } - - if (isEscaped) - { - isEscaped = false; - continue; - } - - if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\') - { - isEscaped = true; - continue; - } - - if (!isInsideDoubleQuotedString && currentChar == '\'') - isInsideSingleQuotedString = !isInsideSingleQuotedString; - else if (!isInsideSingleQuotedString && currentChar == '"') - isInsideDoubleQuotedString = !isInsideDoubleQuotedString; - } - - return isInsideSingleQuotedString || isInsideDoubleQuotedString; - } - private static bool IsIdentifierCharacter(char character) => char.IsLetterOrDigit(character) || character == '_'; private static bool IsIdentifierTriggerCharacter(char character) => char.IsLetter(character) || character == '_'; - private void StyleCompletionTooltip() - { - if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) - return; - - if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) - return; - - tooltip.Background = DefaultToolTipBackground; - tooltip.BorderBrush = DefaultToolTipBorder; - tooltip.BorderThickness = new Thickness(0.0); - tooltip.Padding = new Thickness(0.0); - tooltip.PlacementTarget = listBox; - tooltip.Placement = PlacementMode.Right; - tooltip.HorizontalOffset = 10.0; - tooltip.StaysOpen = true; - - listBox.SelectionChanged += (s, e) => ScheduleCompletionTooltipUpdate(tooltip); - listBox.PreviewMouseLeftButtonUp += (s, e) => HandleCompletionListClick(listBox, tooltip, e); - } - - private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) - { - ListBoxItem listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); - - if (listBoxItem is null) - return; - - if (!ReferenceEquals(listBox.SelectedItem, listBoxItem.DataContext)) - listBox.SelectedItem = listBoxItem.DataContext; - - listBox.ScrollIntoView(listBoxItem.DataContext); - ScheduleCompletionTooltipUpdate(tooltip); - } - - private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) - { - _completionToolTipCancellationTokenSource?.Cancel(); - _completionToolTipCancellationTokenSource?.Dispose(); - _completionToolTipCancellationTokenSource = new CancellationTokenSource(); - - CancellationToken cancellationToken = _completionToolTipCancellationTokenSource.Token; - int updateToken = ++_completionToolTipUpdateToken; - - Dispatcher.BeginInvoke( - new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, cancellationToken, updateToken)), - DispatcherPriority.Background); - } - - private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationToken cancellationToken, int updateToken) - { - if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) - return; - - ICompletionData item = listBox.SelectedItem as ICompletionData; - - if (item is null) - { - tooltip.IsOpen = false; - return; - } - - try - { - object description = item.Description; - - if (description is not null) - ApplyCompletionToolTipContent(tooltip, description); - else - tooltip.IsOpen = false; - - if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) - { - object resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); - - if (cancellationToken.IsCancellationRequested || updateToken != _completionToolTipUpdateToken) - return; - - if (_completionWindow?.CompletionList.ListBox is not ListBox currentListBox - || !ReferenceEquals(currentListBox, listBox) - || !ReferenceEquals(currentListBox.SelectedItem, item)) - { - return; - } - - if (resolvedDescription is not null) - ApplyCompletionToolTipContent(tooltip, resolvedDescription); - else - tooltip.IsOpen = false; - } - } - catch (OperationCanceledException) - { - } - catch - { - tooltip.IsOpen = false; - } - } - - private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) - { - tooltip.Content = content; - - if (!tooltip.IsOpen) - tooltip.IsOpen = true; - else - { - tooltip.InvalidateMeasure(); - tooltip.InvalidateVisual(); - } - } - - private void CancelCompletionToolTipUpdate() - { - _completionToolTipCancellationTokenSource?.Cancel(); - _completionToolTipCancellationTokenSource?.Dispose(); - _completionToolTipCancellationTokenSource = null; - _completionToolTipUpdateToken++; - } - - private void ScheduleCloseIfEmpty() - => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); - - private void ScheduleInitialSelection() - => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.Background); - - private void SelectInitialItem() - { - if (_completionWindow is null) - return; - - _completionWindow.CompletionList.SelectItem(GetCompletionWindowQuery()); - CloseCompletionWindowIfEmpty(); - } - - // AvalonEdit's CompletionWindowBase does not set WS_EX_NOACTIVATE, so clicking the - // completion list activates the popup window and steals keyboard focus from the editor. - // This hook returns MA_NOACTIVATE to prevent that while still allowing clicks through. - - private void MakeCompletionWindowNonActivatable() - { - _completionWindow.SourceInitialized += (s, e) => - { - if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) - source.AddHook(CompletionWindowWndProc); - }; - } - - private static IntPtr CompletionWindowWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) - { - const int WM_MOUSEACTIVATE = 0x0021; - const int MA_NOACTIVATE = 3; - - if (msg == WM_MOUSEACTIVATE) - { - handled = true; - return new IntPtr(MA_NOACTIVATE); - } - - return IntPtr.Zero; - } - - private bool CloseCompletionWindowIfEmpty() - { - if (_completionWindow is null) - return false; - - var listBox = _completionWindow.CompletionList.ListBox; - - if (listBox is null || listBox.HasItems) - return false; - - CloseCompletionWindow(); - return true; - } - - private string GetCompletionWindowQuery() - { - if (_completionWindow is null || Document is null) - return string.Empty; - - int startOffset = Math.Max(0, Math.Min(_completionWindow.StartOffset, Document.TextLength)); - int endOffset = Math.Max(startOffset, Math.Min(_completionWindow.EndOffset, Document.TextLength)); - - return endOffset > startOffset - ? Document.GetText(startOffset, endOffset - startOffset) - : string.Empty; - } - - private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) - { - if (!IsIntellisenseAvailable()) - return null; - - (int line, int column) = GetPositionFromOffset(offset); - - return await IntellisenseProvider - .GetHoverAsync(FilePath, Text, line, column, cancellationToken) - .ConfigureAwait(true); - } - - private async Task RequestSignatureHelpAsync(int offset) - { - if (!IsIntellisenseAvailable()) - { - DismissSignatureHelp(); - return; - } - - _signatureCancellationTokenSource?.Cancel(); - _signatureCancellationTokenSource?.Dispose(); - _signatureCancellationTokenSource = new CancellationTokenSource(); - - CancellationToken cancellationToken = _signatureCancellationTokenSource.Token; - - try - { - (int line, int column) = GetPositionFromOffset(offset); - LuaSignatureInfo signatureInfo = await IntellisenseProvider - .GetSignatureHelpAsync(FilePath, Text, line, column, cancellationToken) - .ConfigureAwait(true); - - if (cancellationToken.IsCancellationRequested) - return; - - if (signatureInfo is null) - { - DismissSignatureHelp(); - return; - } - - ShowSignatureToolTip(signatureInfo); - } - catch - { - // Ignore signature help failures and keep the editor responsive. - } - } - private void DismissTransientToolTips() { - _hoverCancellationTokenSource?.Cancel(); + CancelAndDispose(ref _hoverCancellationTokenSource); _hoverRequestToken++; DismissSignatureHelp(); CloseDefinitionToolTip(true); } - private void ScheduleSignatureHelpRefresh() - => Dispatcher.BeginInvoke(new Action(() => _ = RequestSignatureHelpAsync(CaretOffset))); - private (int line, int column) GetPositionFromOffset(int offset) { int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); @@ -695,22 +171,27 @@ private void ScheduleSignatureHelpRefresh() return (location.Line - 1, location.Column - 1); } - private void SetCompletionWindowOffsets(int offset) + private static CancellationToken ResetCancellationTokenSource(ref CancellationTokenSource cancellationTokenSource) { - int startOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + CancelAndDispose(ref cancellationTokenSource); + cancellationTokenSource = new CancellationTokenSource(); + return cancellationTokenSource.Token; + } - while (startOffset > 0) - { - char currentChar = Document.GetCharAt(startOffset - 1); + private static void CancelAndDispose(ref CancellationTokenSource cancellationTokenSource) + { + if (cancellationTokenSource is null) + return; - if (char.IsLetterOrDigit(currentChar) || currentChar == '_') - startOffset--; - else - break; - } + cancellationTokenSource.Cancel(); + cancellationTokenSource.Dispose(); + cancellationTokenSource = null; + } - _completionWindow.StartOffset = startOffset; - _completionWindow.EndOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + private static void WriteDebugFailure(string area, Exception exception) + { + if (exception is not null) + Debug.WriteLine($"[Lua] {area} failed: {exception}"); } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index 94769b8ebf..932fb1315e 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; @@ -53,11 +54,6 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo if (!IsIntellisenseAvailable()) return false; - - if (DefinitionNavigationRequested is null) - return false; - - try { foreach (int candidateOffset in GetDefinitionCandidateOffsets(offset)) @@ -70,17 +66,20 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo if (definitionLocation is null) continue; - DefinitionNavigationRequested(definitionLocation); + + DefinitionNavigationRequested?.Invoke(definitionLocation); return true; } + return false; } catch (OperationCanceledException) { return false; } - catch + catch (Exception exception) { + Debug.WriteLine($"[Lua] Go to definition failed: {exception}"); return false; } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs index 76901fa95e..b016ddf735 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs @@ -22,10 +22,8 @@ private void EnsureSemanticTokensColorizerAttached() if (_semanticTokensColorizer is null) _semanticTokensColorizer = new LuaSemanticTokensColorizer(TextArea.TextView); - if (TextArea.TextView.LineTransformers.Contains(_semanticTokensColorizer)) - TextArea.TextView.LineTransformers.Remove(_semanticTokensColorizer); - - TextArea.TextView.LineTransformers.Add(_semanticTokensColorizer); + if (!TextArea.TextView.LineTransformers.Contains(_semanticTokensColorizer)) + TextArea.TextView.LineTransformers.Add(_semanticTokensColorizer); } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index 2e42e16208..248b1778e8 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -1,4 +1,6 @@ using System; +using System.Threading; +using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -15,6 +17,8 @@ public sealed partial class LuaEditor private static readonly SolidColorBrush SignatureActiveParamForeground = CreateFrozenBrush(Color.FromRgb(86, 180, 235)); private static readonly SolidColorBrush SignatureForeground = CreateFrozenBrush(Colors.Gainsboro); + private CancellationTokenSource _signatureCancellationTokenSource; + private readonly Popup _signaturePopup = new Popup(); private readonly Border _signaturePopupBorder = new Border(); private readonly ContentPresenter _signaturePopupPresenter = new ContentPresenter(); @@ -63,6 +67,19 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) var panel = new StackPanel { MaxWidth = contentMaxWidth }; panel.Children.Add(BuildSignatureBlock(signatureInfo)); + if (!string.IsNullOrWhiteSpace(signatureInfo.Documentation)) + { + panel.Children.Add(new TextBlock + { + Text = signatureInfo.Documentation, + Foreground = SignatureParamDocForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), + TextWrapping = TextWrapping.Wrap, + Margin = new Thickness(0.0, 4.0, 0.0, 0.0) + }); + } + if (signatureInfo.ActiveParameter < signatureInfo.Parameters.Count) { LuaParameterInfo activeParam = signatureInfo.Parameters[signatureInfo.ActiveParameter]; @@ -120,6 +137,46 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) _signaturePopup.IsOpen = true; } + private async Task RequestSignatureHelpAsync(int offset) + { + if (!IsIntellisenseAvailable()) + { + DismissSignatureHelp(); + return; + } + + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _signatureCancellationTokenSource); + + try + { + (int line, int column) = GetPositionFromOffset(offset); + LuaSignatureInfo signatureInfo = await IntellisenseProvider + .GetSignatureHelpAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested) + return; + + if (signatureInfo is null) + { + DismissSignatureHelp(); + return; + } + + ShowSignatureToolTip(signatureInfo); + } + catch (OperationCanceledException) + { + } + catch (Exception exception) + { + WriteDebugFailure("Signature help", exception); + } + } + + private void ScheduleSignatureHelpRefresh() + => Dispatcher.BeginInvoke(new Action(() => _ = RequestSignatureHelpAsync(CaretOffset))); + private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo) { var textBlock = new TextBlock diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index bb8c9d59f3..7b6c8f0640 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -1,9 +1,5 @@ -using ICSharpCode.AvalonEdit.Highlighting; -using ICSharpCode.AvalonEdit.Highlighting.Xshd; using System; -using System.IO; using System.Windows.Media; -using System.Xml; using TombLib.Scripting.Bases; using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Objects; @@ -18,7 +14,7 @@ public sealed partial class LuaEditor : TextEditorBase private LuaTextMateInstallation _textMateHighlighting; public ILuaIntellisenseProvider IntellisenseProvider { get; set; } - public Action DefinitionNavigationRequested { get; set; } + public event Action DefinitionNavigationRequested; public LuaEditor(Version engineVersion) : base(engineVersion) { @@ -30,29 +26,35 @@ public LuaEditor(Version engineVersion) : base(engineVersion) public override void UpdateSettings(Bases.ConfigurationBase configuration) { var config = configuration as LuaEditorConfiguration; - - string xmlFile = Path.Combine(DefaultPaths.LuaColorConfigsDirectory, "Default.xml"); + ColorScheme colorScheme = config?.ColorScheme ?? new ColorScheme(); _textMateHighlighting?.Dispose(); _textMateHighlighting = null; if (!LuaTextMateSyntaxHighlighting.TryInstall(this, out _textMateHighlighting)) - { - using (var stream = new FileStream(xmlFile, FileMode.Open, FileAccess.Read)) - using (var reader = new XmlTextReader(stream)) - SyntaxHighlighting = HighlightingLoader.Load(reader, HighlightingManager.Instance); - } + SyntaxHighlighting = new SyntaxHighlighting(colorScheme); else - { SyntaxHighlighting = null; - } EnsureSemanticTokensColorizerAttached(); - Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#202020")); - Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("White")); + Background = CreateEditorBrush(colorScheme.Background, "#202020"); + Foreground = CreateEditorBrush(colorScheme.Foreground, "White"); base.UpdateSettings(configuration); LiveErrorUnderlining = true; } + + private static SolidColorBrush CreateEditorBrush(string colorValue, string fallbackColorValue) + { + try + { + string effectiveColor = string.IsNullOrWhiteSpace(colorValue) ? fallbackColorValue : colorValue; + return new SolidColorBrush((Color)ColorConverter.ConvertFromString(effectiveColor)); + } + catch + { + return new SolidColorBrush((Color)ColorConverter.ConvertFromString(fallbackColorValue)); + } + } } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs index f67d633e17..9b9633fca4 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs @@ -9,39 +9,38 @@ namespace TombLib.Scripting.Lua public sealed class LuaEditorConfiguration : TextEditorConfigBase { public override string DefaultPath { get; } - - #region Color scheme + public ColorScheme ColorScheme = new ColorScheme(); private string _selectedColorSchemeName; + public string SelectedColorSchemeName { get => _selectedColorSchemeName; set { - _selectedColorSchemeName = value; - - string schemeFilePath = - Path.Combine(DefaultPaths.LuaColorConfigsDirectory, value + ConfigurationDefaults.ColorSchemeFileExtension); + _selectedColorSchemeName = string.IsNullOrWhiteSpace(value) + ? ConfigurationDefaults.SelectedColorSchemeName + : value; - if (!File.Exists(schemeFilePath)) - ColorScheme = new ColorScheme(); - else - ColorScheme = XmlUtils.ReadXmlFile(schemeFilePath); + ColorScheme = LoadColorScheme(_selectedColorSchemeName); } } - public ColorScheme ColorScheme; - - #endregion Color scheme - - #region Construction - public LuaEditorConfiguration() { DefaultPath = Path.Combine(DefaultPaths.TextEditorConfigsDirectory, ConfigurationDefaults.ConfigurationFileName); SelectedColorSchemeName = ConfigurationDefaults.SelectedColorSchemeName; } - #endregion Construction + private static ColorScheme LoadColorScheme(string schemeName) + { + string schemeFilePath = Path.Combine( + DefaultPaths.LuaColorConfigsDirectory, + schemeName + ConfigurationDefaults.ColorSchemeFileExtension); + + return File.Exists(schemeFilePath) + ? XmlUtils.ReadXmlFile(schemeFilePath) + : new ColorScheme(); + } } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs index 0b6fa96ac8..1538bb8436 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using TombLib.Scripting.Bases; using TombLib.Scripting.Objects; @@ -12,31 +13,37 @@ public sealed class ColorScheme : ColorSchemeBase public HighlightingObject Operators { get; set; } = new HighlightingObject(); public HighlightingObject SpecialOperators { get; set; } = new HighlightingObject(); - #region Operators + public static bool operator ==(ColorScheme left, ColorScheme right) + => ReferenceEquals(left, right) || left is not null && left.Equals(right); - public static bool operator ==(ColorScheme a, ColorScheme b) => a.Equals(b); - public static bool operator !=(ColorScheme a, ColorScheme b) => !a.Equals(b); + public static bool operator !=(ColorScheme left, ColorScheme right) + => !(left == right); public override bool Equals(object obj) { - if (obj == null || !(obj is ColorScheme)) + if (obj is not ColorScheme other) return false; - else - { - var objectToCompare = obj as ColorScheme; - return Comments == objectToCompare.Comments - && Values == objectToCompare.Values - && Statements == objectToCompare.Statements - && Operators == objectToCompare.Operators - && SpecialOperators == objectToCompare.SpecialOperators - && Background.Equals(objectToCompare.Background, StringComparison.OrdinalIgnoreCase) - && Foreground.Equals(objectToCompare.Foreground, StringComparison.OrdinalIgnoreCase); - } + return EqualityComparer.Default.Equals(Comments, other.Comments) + && EqualityComparer.Default.Equals(Values, other.Values) + && EqualityComparer.Default.Equals(Statements, other.Statements) + && EqualityComparer.Default.Equals(Operators, other.Operators) + && EqualityComparer.Default.Equals(SpecialOperators, other.SpecialOperators) + && string.Equals(Background, other.Background, StringComparison.OrdinalIgnoreCase) + && string.Equals(Foreground, other.Foreground, StringComparison.OrdinalIgnoreCase); } - public override int GetHashCode() => ToString().GetHashCode(); - - #endregion Operators + public override int GetHashCode() + { + var hashCode = new HashCode(); + hashCode.Add(Comments); + hashCode.Add(Values); + hashCode.Add(Statements); + hashCode.Add(Operators); + hashCode.Add(SpecialOperators); + hashCode.Add(Background ?? string.Empty, StringComparer.OrdinalIgnoreCase); + hashCode.Add(Foreground ?? string.Empty, StringComparer.OrdinalIgnoreCase); + return hashCode.ToHashCode(); + } } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index b364d69f4c..c061d29fac 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -68,7 +68,10 @@ public async Task GetDescriptionAsync(CancellationToken cancellationToke try { - LuaCompletionItem resolvedItem = await resolveTask.ConfigureAwait(true); + LuaCompletionItem resolvedItem = cancellationToken.CanBeCanceled + ? await resolveTask.WaitAsync(cancellationToken).ConfigureAwait(true) + : await resolveTask.ConfigureAwait(true); + ApplyResolvedItem(resolvedItem); return Description; } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs index 794dc2d36d..2cb16f5dcb 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs @@ -7,8 +7,8 @@ public sealed class LuaDefinitionLocation public LuaDefinitionLocation(string filePath, int lineNumber, int columnNumber) { FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); - LineNumber = lineNumber; - ColumnNumber = columnNumber; + LineNumber = Math.Max(1, lineNumber); + ColumnNumber = Math.Max(1, columnNumber); } public string FilePath { get; } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs b/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs index 5b339ac0dc..839ca5ee94 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs @@ -4,104 +4,68 @@ using System.Text.RegularExpressions; using System.Windows; using System.Windows.Media; +using TombLib.Scripting.Objects; using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua.Objects { public sealed class SyntaxHighlighting : IHighlightingDefinition { - private readonly ColorScheme _scheme; + private static readonly IReadOnlyList EmptyHighlightingColors = Array.Empty(); + private static readonly IDictionary EmptyProperties = new Dictionary(); - #region Construction + private readonly ColorScheme _scheme; + private readonly HighlightingRuleSet _mainRuleSet; public SyntaxHighlighting(ColorScheme scheme) - => _scheme = scheme; - - #endregion Construction - - #region Rules - - public HighlightingRuleSet MainRuleSet { - get - { - var ruleSet = new HighlightingRuleSet(); - - ruleSet.Rules.Add(new HighlightingRule - { - Regex = new Regex(Patterns.Comments), - Color = new HighlightingColor - { - Foreground = new SimpleHighlightingBrush((Color)ColorConverter.ConvertFromString(_scheme.Comments.HtmlColor)), - FontWeight = _scheme.Comments.IsBold ? FontWeights.Bold : FontWeights.Normal, - FontStyle = _scheme.Comments.IsItalic ? FontStyles.Italic : FontStyles.Normal - } - }); - - ruleSet.Rules.Add(new HighlightingRule - { - Regex = new Regex(Patterns.Values, RegexOptions.IgnoreCase), - Color = new HighlightingColor - { - Foreground = new SimpleHighlightingBrush((Color)ColorConverter.ConvertFromString(_scheme.Values.HtmlColor)), - FontWeight = _scheme.Values.IsBold ? FontWeights.Bold : FontWeights.Normal, - FontStyle = _scheme.Values.IsItalic ? FontStyles.Italic : FontStyles.Normal - } - }); - - ruleSet.Rules.Add(new HighlightingRule - { - Regex = new Regex(Patterns.Statements, RegexOptions.IgnoreCase), - Color = new HighlightingColor - { - Foreground = new SimpleHighlightingBrush((Color)ColorConverter.ConvertFromString(_scheme.Statements.HtmlColor)), - FontWeight = _scheme.Statements.IsBold ? FontWeights.Bold : FontWeights.Normal, - FontStyle = _scheme.Statements.IsItalic ? FontStyles.Italic : FontStyles.Normal - } - }); - - ruleSet.Rules.Add(new HighlightingRule - { - Regex = new Regex(Patterns.Operators, RegexOptions.IgnoreCase), - Color = new HighlightingColor - { - Foreground = new SimpleHighlightingBrush((Color)ColorConverter.ConvertFromString(_scheme.Operators.HtmlColor)), - FontWeight = _scheme.Operators.IsBold ? FontWeights.Bold : FontWeights.Normal, - FontStyle = _scheme.Operators.IsItalic ? FontStyles.Italic : FontStyles.Normal - } - }); - - ruleSet.Rules.Add(new HighlightingRule - { - Regex = new Regex(Patterns.SpecialOperators, RegexOptions.IgnoreCase), - Color = new HighlightingColor - { - Foreground = new SimpleHighlightingBrush((Color)ColorConverter.ConvertFromString(_scheme.SpecialOperators.HtmlColor)), - FontWeight = _scheme.SpecialOperators.IsBold ? FontWeights.Bold : FontWeights.Normal, - FontStyle = _scheme.SpecialOperators.IsItalic ? FontStyles.Italic : FontStyles.Normal - } - }); - - ruleSet.Name = "Lua Rules"; - return ruleSet; - } + _scheme = scheme ?? new ColorScheme(); + _mainRuleSet = CreateMainRuleSet(); } - #endregion Rules - - #region Other + public HighlightingRuleSet MainRuleSet => _mainRuleSet; public string Name => "Lua Rules"; - public IEnumerable NamedHighlightingColors => throw new NotImplementedException(); - public IDictionary Properties => throw new NotImplementedException(); + public IEnumerable NamedHighlightingColors => EmptyHighlightingColors; + public IDictionary Properties => EmptyProperties; public HighlightingColor GetNamedColor(string name) - => throw new NotImplementedException(); + => null; public HighlightingRuleSet GetNamedRuleSet(string name) - => throw new NotImplementedException(); + => string.Equals(name, Name, StringComparison.Ordinal) ? _mainRuleSet : null; + + private HighlightingRuleSet CreateMainRuleSet() + { + var ruleSet = new HighlightingRuleSet + { + Name = Name + }; + + ruleSet.Rules.Add(CreateRule(Patterns.Comments, _scheme.Comments)); + ruleSet.Rules.Add(CreateRule(Patterns.Values, _scheme.Values, RegexOptions.IgnoreCase)); + ruleSet.Rules.Add(CreateRule(Patterns.Statements, _scheme.Statements, RegexOptions.IgnoreCase)); + ruleSet.Rules.Add(CreateRule(Patterns.Operators, _scheme.Operators, RegexOptions.IgnoreCase)); + ruleSet.Rules.Add(CreateRule(Patterns.SpecialOperators, _scheme.SpecialOperators, RegexOptions.IgnoreCase)); - #endregion Other + return ruleSet; + } + + private static HighlightingRule CreateRule(string pattern, HighlightingObject highlighting, RegexOptions options = RegexOptions.None) + { + highlighting ??= new HighlightingObject(); + + return new HighlightingRule + { + Regex = new Regex(pattern, RegexOptions.Compiled | options), + Color = new HighlightingColor + { + Foreground = new SimpleHighlightingBrush((Color)ColorConverter.ConvertFromString(highlighting.HtmlColor)), + FontWeight = highlighting.IsBold ? FontWeights.Bold : FontWeights.Normal, + FontStyle = highlighting.IsItalic ? FontStyles.Italic : FontStyles.Normal + } + }; + } } } diff --git a/TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs b/TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs index a9577b0b84..1cee590b50 100644 --- a/TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs +++ b/TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs @@ -2,9 +2,9 @@ using System; using System.Collections.Generic; -using System.Text; using System.Text.RegularExpressions; using ICSharpCode.AvalonEdit.Document; +using TombLib.Scripting.Lua.Utils; namespace TombLib.Scripting.Lua.Services; @@ -41,7 +41,7 @@ public sealed class TombEngineLanguageScriptService { foreach (DocumentLine line in document.Lines) { - string lineText = StripLuaLineComment(document.GetText(line)); + string lineText = LuaLineParser.StripLineComment(document.GetText(line)); Match match = SetStringsRegex.Match(lineText); if (match.Success) @@ -57,7 +57,7 @@ public sealed class TombEngineLanguageScriptService foreach (DocumentLine line in document.Lines) { - if (regex.IsMatch(StripLuaLineComment(document.GetText(line)))) + if (regex.IsMatch(LuaLineParser.StripLineComment(document.GetText(line)))) return line; } @@ -71,9 +71,9 @@ public sealed class TombEngineLanguageScriptService for (DocumentLine? line = stringsStartLine; line is not null; line = line.NextLine) { - string lineText = StripLuaLineComment(document.GetText(line)); + string lineText = LuaLineParser.StripLineComment(document.GetText(line)); - foreach (char character in EnumerateStructuralLuaCharacters(lineText)) + foreach (char character in LuaLineParser.EnumerateStructuralCharacters(lineText)) { if (character == '{') { @@ -101,7 +101,7 @@ public sealed class TombEngineLanguageScriptService for (int i = stopLine.LineNumber - 1; i > stringsStartLine.LineNumber; i--) { DocumentLine line = document.GetLineByNumber(i); - string cleanLine = StripLuaLineComment(document.GetText(line)).TrimEnd(); + string cleanLine = LuaLineParser.StripLineComment(document.GetText(line)).TrimEnd(); if (cleanLine.EndsWith("}") || cleanLine.EndsWith("},")) return line; @@ -113,7 +113,7 @@ public sealed class TombEngineLanguageScriptService private static int InsertLanguageScript(TextDocument document, string languageScript, DocumentLine insertionLine) { string rawLine = document.GetText(insertionLine); - string cleanLine = StripLuaLineComment(rawLine).TrimEnd(); + string cleanLine = LuaLineParser.StripLineComment(rawLine).TrimEnd(); if (cleanLine.EndsWith("}")) { @@ -130,79 +130,4 @@ private static int InsertLanguageScriptIntoEmptyTable(TextDocument document, str document.Insert(stopLine.Offset, languageScript + Environment.NewLine); return stopLine.LineNumber; } - - private static string StripLuaLineComment(string lineText) - { - var builder = new StringBuilder(lineText.Length); - - bool isInSingleQuotedString = false; - bool isInDoubleQuotedString = false; - - for (int i = 0; i < lineText.Length; i++) - { - char character = lineText[i]; - - if ((isInSingleQuotedString || isInDoubleQuotedString) && character == '\\' && i + 1 < lineText.Length) - { - builder.Append(character); - builder.Append(lineText[i + 1]); - - i++; - continue; - } - - if (!isInDoubleQuotedString && character == '\'') - { - isInSingleQuotedString = !isInSingleQuotedString; - builder.Append(character); - continue; - } - - if (!isInSingleQuotedString && character == '"') - { - isInDoubleQuotedString = !isInDoubleQuotedString; - builder.Append(character); - continue; - } - - if (!isInSingleQuotedString && !isInDoubleQuotedString && character == '-' && i + 1 < lineText.Length && lineText[i + 1] == '-') - break; - - builder.Append(character); - } - - return builder.ToString(); - } - - private static IEnumerable EnumerateStructuralLuaCharacters(string lineText) - { - bool isInSingleQuotedString = false; - bool isInDoubleQuotedString = false; - - for (int i = 0; i < lineText.Length; i++) - { - char character = lineText[i]; - - if ((isInSingleQuotedString || isInDoubleQuotedString) && character == '\\' && i + 1 < lineText.Length) - { - i++; - continue; - } - - if (!isInDoubleQuotedString && character == '\'') - { - isInSingleQuotedString = !isInSingleQuotedString; - continue; - } - - if (!isInSingleQuotedString && character == '"') - { - isInDoubleQuotedString = !isInDoubleQuotedString; - continue; - } - - if (!isInSingleQuotedString && !isInDoubleQuotedString) - yield return character; - } - } } diff --git a/TombLib/TombLib.Scripting.Lua/Utils/Autocomplete.cs b/TombLib/TombLib.Scripting.Lua/Utils/Autocomplete.cs deleted file mode 100644 index d4ed09353e..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Utils/Autocomplete.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TombLib.Scripting.Lua.Utils -{ - public static class Autocomplete - { - // TODO - } -} diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs new file mode 100644 index 0000000000..809f7b4352 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -0,0 +1,121 @@ +using System.Collections.Generic; +using System.Text; + +namespace TombLib.Scripting.Lua.Utils +{ + internal static class LuaLineParser + { + public static bool IsInsideCommentOrString(string lineText) + { + if (string.IsNullOrEmpty(lineText)) + return false; + + bool isInsideSingleQuotedString = false; + bool isInsideDoubleQuotedString = false; + bool isEscaped = false; + + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; + + if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && IsLineCommentStart(lineText, i)) + return true; + + if (isEscaped) + { + isEscaped = false; + continue; + } + + if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\' && i + 1 < lineText.Length) + { + isEscaped = true; + continue; + } + + if (!isInsideDoubleQuotedString && currentChar == '\'') + isInsideSingleQuotedString = !isInsideSingleQuotedString; + else if (!isInsideSingleQuotedString && currentChar == '"') + isInsideDoubleQuotedString = !isInsideDoubleQuotedString; + } + + return isInsideSingleQuotedString || isInsideDoubleQuotedString; + } + + public static string StripLineComment(string lineText) + { + if (string.IsNullOrEmpty(lineText)) + return string.Empty; + + var builder = new StringBuilder(lineText.Length); + bool isInsideSingleQuotedString = false; + bool isInsideDoubleQuotedString = false; + + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; + + if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && IsLineCommentStart(lineText, i)) + break; + + if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\' && i + 1 < lineText.Length) + { + builder.Append(currentChar); + builder.Append(lineText[i + 1]); + i++; + continue; + } + + if (!isInsideDoubleQuotedString && currentChar == '\'') + isInsideSingleQuotedString = !isInsideSingleQuotedString; + else if (!isInsideSingleQuotedString && currentChar == '"') + isInsideDoubleQuotedString = !isInsideDoubleQuotedString; + + builder.Append(currentChar); + } + + return builder.ToString(); + } + + public static IEnumerable EnumerateStructuralCharacters(string lineText) + { + if (string.IsNullOrEmpty(lineText)) + yield break; + + bool isInsideSingleQuotedString = false; + bool isInsideDoubleQuotedString = false; + + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; + + if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && IsLineCommentStart(lineText, i)) + yield break; + + if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\' && i + 1 < lineText.Length) + { + i++; + continue; + } + + if (!isInsideDoubleQuotedString && currentChar == '\'') + { + isInsideSingleQuotedString = !isInsideSingleQuotedString; + continue; + } + + if (!isInsideSingleQuotedString && currentChar == '"') + { + isInsideDoubleQuotedString = !isInsideDoubleQuotedString; + continue; + } + + if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString) + yield return currentChar; + } + } + + private static bool IsLineCommentStart(string lineText, int index) + => lineText[index] == '-' && index + 1 < lineText.Length && lineText[index + 1] == '-'; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs b/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs index 6f8c836bc5..7ddb7da73f 100644 --- a/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs +++ b/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs @@ -74,6 +74,23 @@ public void TryInsertLanguageScript_PlacesCommaBeforeTrailingComment() StringAssert.Contains(document.Text, "newLevel = { \"New Level\" }"); } + [TestMethod] + public void TryInsertLanguageScript_IgnoresEscapedQuotesAndCommentMarkersInsideStrings() + { + var document = CreateDocument( + "local strings = {", + " existing = { \"A \\\"quoted\\\" } brace and -- marker\" } -- note", + "}", + string.Empty, + "TEN.Flow.SetStrings(strings)"); + + int? insertedLineNumber = _service.TryInsertLanguageScript(document, " newLevel = { \"New Level\" }"); + + Assert.AreEqual(3, insertedLineNumber); + StringAssert.Contains(document.Text, "existing = { \"A \\\"quoted\\\" } brace and -- marker\" }, -- note"); + StringAssert.Contains(document.Text, "newLevel = { \"New Level\" }"); + } + [TestMethod] public void TryInsertLanguageScript_ReturnsNullWhenStringsTableIsMissing() { From 2fe19664bf5282753737023eae42b5425279315b Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 12:15:06 +0100 Subject: [PATCH 05/34] Refactor pass 2 --- GlobalPaths.cs | 2 +- .../LuaSemanticTokensColorizer.cs | 16 +-- .../LuaEditor.Completion.cs | 56 ++------ .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 23 +++- .../LuaEditor.Intellisense.cs | 42 +++--- .../LuaEditor.Navigation.cs | 97 +++----------- .../LuaEditor.SemanticHighlighting.cs | 4 +- .../LuaEditor.SignatureHelp.cs | 6 +- TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 6 +- .../LuaEditorConfiguration.cs | 2 +- .../LuaTextBox.Designer.cs | 4 +- TombLib/TombLib.Scripting.Lua/LuaTextBox.cs | 43 +++++-- .../Objects/ColorScheme.cs | 6 +- .../Objects/LuaCompletionData.cs | 26 ++-- .../Objects/LuaCompletionIconFactory.cs | 2 +- .../Objects/LuaCompletionItem.cs | 16 +-- .../Objects/LuaSignatureInfo.cs | 8 +- .../Objects/SyntaxHighlighting.cs | 4 +- .../Properties/InternalsVisibleTo.cs | 3 + .../Services/ILuaIntellisenseProvider.cs | 10 +- .../TombLib.Scripting.Lua.csproj | 1 + .../Utils/LuaEditorInteractionRules.cs | 120 ++++++++++++++++++ .../LuaEditorInteractionRulesTests.cs | 112 ++++++++++++++++ 23 files changed, 395 insertions(+), 214 deletions(-) create mode 100644 TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs create mode 100644 TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs diff --git a/GlobalPaths.cs b/GlobalPaths.cs index bd1ed59fd6..06f8f9ecfe 100644 --- a/GlobalPaths.cs +++ b/GlobalPaths.cs @@ -7,7 +7,7 @@ internal static class DefaultPaths { - public static string ProgramDirectory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + public static string ProgramDirectory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? AppContext.BaseDirectory; #region Configs diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index 20979e16c9..69ee5b7fa5 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -44,7 +44,7 @@ public void SetTokens(IReadOnlyList tokens) { LuaSemanticToken token = tokens[i]; - if (!groupedTokens.TryGetValue(token.Line, out List lineTokens)) + if (!groupedTokens.TryGetValue(token.Line, out List? lineTokens) || lineTokens is null) { lineTokens = new List(); groupedTokens[token.Line] = lineTokens; @@ -73,7 +73,7 @@ public void ClearTokens() protected override void ColorizeLine(DocumentLine line) { - if (!_tokensByLine.TryGetValue(line.LineNumber - 1, out IReadOnlyList tokens)) + if (!_tokensByLine.TryGetValue(line.LineNumber - 1, out IReadOnlyList? tokens) || tokens is null) return; int lineLength = line.Length; @@ -98,7 +98,7 @@ protected override void ColorizeLine(DocumentLine line) private static LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) { - Brush foreground = token.Type switch + Brush? foreground = token.Type switch { "namespace" => token.HasModifier("defaultLibrary") ? DefaultLibraryBrush : TypeBrush, "type" => TypeBrush, @@ -126,7 +126,7 @@ private static LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) token.HasModifier("deprecated") ? DeprecatedDecorations : null); } - private static Brush ResolveVariableBrush(LuaSemanticToken token) + private static Brush? ResolveVariableBrush(LuaSemanticToken token) { if (token.HasModifier("defaultLibrary")) return DefaultLibraryBrush; @@ -163,7 +163,7 @@ private static TextDecorationCollection CreateTextDecorations(TextDecorationColl private readonly struct LuaSemanticTokenStyle { - public LuaSemanticTokenStyle(Brush foreground, bool isBold, Brush background, TextDecorationCollection textDecorations) + public LuaSemanticTokenStyle(Brush? foreground, bool isBold, Brush? background, TextDecorationCollection? textDecorations) { Foreground = foreground; IsBold = isBold; @@ -171,10 +171,10 @@ public LuaSemanticTokenStyle(Brush foreground, bool isBold, Brush background, Te TextDecorations = textDecorations; } - public Brush Foreground { get; } + public Brush? Foreground { get; } public bool IsBold { get; } - public Brush Background { get; } - public TextDecorationCollection TextDecorations { get; } + public Brush? Background { get; } + public TextDecorationCollection? TextDecorations { get; } public bool HasFormatting => Foreground is not null || Background is not null || IsBold || TextDecorations is not null; } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index 83e56a28f7..39a6c44641 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -10,22 +10,20 @@ using System.Windows.Interop; using System.Windows.Threading; using ICSharpCode.AvalonEdit.CodeCompletion; -using ICSharpCode.AvalonEdit.Document; using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Lua.Utils; using TombLib.WPF; namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private static readonly FieldInfo CompletionToolTipField = + private static readonly FieldInfo? CompletionToolTipField = typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); private static bool _completionToolTipFieldLoggedMissing; - private CancellationTokenSource _completionCancellationTokenSource; - private CancellationTokenSource _completionToolTipCancellationTokenSource; + private CancellationTokenSource? _completionCancellationTokenSource; + private CancellationTokenSource? _completionToolTipCancellationTokenSource; private int _completionRequestToken; private int _completionToolTipUpdateToken; @@ -61,6 +59,9 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) if (!IsIntellisenseAvailable()) return; + DismissSignatureHelp(); + CloseDefinitionToolTip(true); + (int line, int column) = GetPositionFromOffset(offset); var items = await IntellisenseProvider .GetCompletionItemsAsync(FilePath, Text, line, column, triggerCharacter, cancellationToken) @@ -107,43 +108,6 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) } } - private bool IsValidAutocompleteContext(int offset, char? triggerCharacter) - { - if (offset <= 0 || Document is null || Document.TextLength == 0) - return false; - - if (IsInsideCommentOrString(offset)) - return false; - - if (triggerCharacter is '.' || triggerCharacter is ':') - return true; - - char typedCharacter = Document.GetCharAt(offset - 1); - - if (!IsIdentifierCharacter(typedCharacter)) - return false; - - if (offset >= 2) - { - char previousCharacter = Document.GetCharAt(offset - 2); - - if (previousCharacter == '.') - return false; - } - - return true; - } - - private bool IsInsideCommentOrString(int offset) - { - DocumentLine currentLine = Document.GetLineByOffset(Math.Max(0, Math.Min(offset, Document.TextLength))); - int lineStart = currentLine.Offset; - int inspectedLength = Math.Max(0, Math.Min(offset, currentLine.EndOffset) - lineStart); - string lineText = Document.GetText(lineStart, inspectedLength); - - return LuaLineParser.IsInsideCommentOrString(lineText); - } - private void StyleCompletionTooltip() { if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) @@ -175,7 +139,7 @@ private void StyleCompletionTooltip() private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) { - ListBoxItem listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); + ListBoxItem? listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); if (listBoxItem is null) return; @@ -202,7 +166,7 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationTok if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) return; - ICompletionData item = listBox.SelectedItem as ICompletionData; + ICompletionData? item = listBox.SelectedItem as ICompletionData; if (item is null) { @@ -212,7 +176,7 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationTok try { - object description = item.Description; + object? description = item.Description; if (description is not null) ApplyCompletionToolTipContent(tooltip, description); @@ -221,7 +185,7 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationTok if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) { - object resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); + object? resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); if (cancellationToken.IsCancellationRequested || updateToken != _completionToolTipUpdateToken) return; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index 31a08f74e1..7f933c0e26 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -6,6 +6,7 @@ using System.Windows.Input; using System.Windows.Media; using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Utils; using TombLib.Scripting.Objects; using TombLib.Scripting.Rendering; @@ -13,7 +14,7 @@ namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private CancellationTokenSource _hoverCancellationTokenSource; + private CancellationTokenSource? _hoverCancellationTokenSource; private int _hoverRequestToken; protected override async void HandleMouseHover(MouseEventArgs e) @@ -25,6 +26,16 @@ protected override async void HandleMouseHover(MouseEventArgs e) bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); + bool isCompletionWindowOpen = _completionWindow is not null; + + if (!LuaEditorInteractionRules.CanRequestHover(Document, hoveredOffset, isCompletionWindowOpen, _signaturePopup.IsOpen)) + { + if (!isCompletionWindowOpen && !_signaturePopup.IsOpen && hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + + return; + } + if (!IsIntellisenseAvailable()) { if (hasDiagnostic) @@ -48,7 +59,7 @@ protected override async void HandleMouseHover(MouseEventArgs e) try { - LuaHoverInfo hoverInfo = await RequestHoverAsync(hoveredOffset, cancellationToken).ConfigureAwait(true); + LuaHoverInfo? hoverInfo = await RequestHoverAsync(hoveredOffset, cancellationToken).ConfigureAwait(true); if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) return; @@ -58,11 +69,9 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (currentHoveredOffset != hoveredOffset) return; - bool hasHover = hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content); - - if (hasHover && hasDiagnostic) + if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) && hasDiagnostic) ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); - else if (hasHover) + else if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content)) ShowHoverToolTip(hoverInfo); else if (hasDiagnostic) ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); @@ -120,7 +129,7 @@ private FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) return MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); } - private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) + private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) { if (!IsIntellisenseAvailable()) return null; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index fe70a211b0..f072c4cbe5 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -1,15 +1,17 @@ using System; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Windows; using System.Windows.Input; using ICSharpCode.AvalonEdit.Document; +using TombLib.Scripting.Lua.Utils; namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private Window _hostWindow; + private Window? _hostWindow; private void BindLuaIntellisenseEvents() { @@ -23,18 +25,21 @@ private void BindLuaIntellisenseEvents() Unloaded += LuaEditor_Unloaded; } - private void LuaEditor_Loaded(object sender, RoutedEventArgs e) + private void LuaEditor_Loaded(object? sender, RoutedEventArgs e) => AttachHostWindowHandlers(); - private void LuaEditor_IsKeyboardFocusWithinChanged(object sender, DependencyPropertyChangedEventArgs e) + private void LuaEditor_IsKeyboardFocusWithinChanged(object? sender, DependencyPropertyChangedEventArgs e) { if (e.NewValue is bool hasKeyboardFocus && !hasKeyboardFocus) + { + CloseCompletionWindow(); DismissTransientToolTips(); + } } private void AttachHostWindowHandlers() { - Window window = Window.GetWindow(this); + Window? window = Window.GetWindow(this); if (window == _hostWindow) return; @@ -48,10 +53,13 @@ private void AttachHostWindowHandlers() _hostWindow.Deactivated += HostWindow_Deactivated; } - private void HostWindow_Deactivated(object sender, EventArgs e) - => DismissTransientToolTips(); + private void HostWindow_Deactivated(object? sender, EventArgs e) + { + CloseCompletionWindow(); + DismissTransientToolTips(); + } - private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) + private void LuaEditor_Unloaded(object? sender, RoutedEventArgs e) { _textMateHighlighting?.Dispose(); _textMateHighlighting = null; @@ -62,6 +70,7 @@ private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) CancelCompletionToolTipUpdate(); CancelAndDispose(ref _signatureCancellationTokenSource); + CloseCompletionWindow(); if (_hostWindow is not null) _hostWindow.Deactivated -= HostWindow_Deactivated; @@ -75,7 +84,7 @@ private void LuaEditor_Unloaded(object sender, RoutedEventArgs e) IntellisenseProvider?.CloseDocument(FilePath); } - private async void TextArea_TextEntering(object sender, TextCompositionEventArgs e) + private async void TextArea_TextEntering(object? sender, TextCompositionEventArgs e) { if (!AutocompleteEnabled || !IsIntellisenseAvailable()) return; @@ -84,11 +93,12 @@ private async void TextArea_TextEntering(object sender, TextCompositionEventArgs { e.Handled = true; - await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); + if (LuaEditorInteractionRules.IsValidManualCompletionContext(Document, CaretOffset)) + await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); } } - private async void TextArea_TextEntered(object sender, TextCompositionEventArgs e) + private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs e) { if (!IsIntellisenseAvailable()) return; @@ -121,14 +131,16 @@ private async void TextArea_TextEntered(object sender, TextCompositionEventArgs if (!AutocompleteEnabled) return; - if (TryGetCompletionTrigger(e.Text, out char? triggerCharacter) && IsValidAutocompleteContext(CaretOffset, triggerCharacter)) + if (TryGetCompletionTrigger(e.Text, out char? triggerCharacter) + && LuaEditorInteractionRules.IsValidAutocompleteContext(Document, CaretOffset, triggerCharacter)) await RequestCompletionAsync(CaretOffset, triggerCharacter).ConfigureAwait(true); } + [MemberNotNullWhen(true, nameof(IntellisenseProvider))] private bool IsIntellisenseAvailable() => IntellisenseProvider is not null && IntellisenseProvider.IsAvailable && !string.IsNullOrWhiteSpace(FilePath); - private static bool TryGetCompletionTrigger(string inputText, out char? triggerCharacter) + private static bool TryGetCompletionTrigger(string? inputText, out char? triggerCharacter) { triggerCharacter = null; @@ -146,7 +158,7 @@ private static bool TryGetCompletionTrigger(string inputText, out char? triggerC return IsIdentifierTriggerCharacter(typedChar); } - private static bool ShouldKeepCompletionWindowOpen(string inputText) + private static bool ShouldKeepCompletionWindowOpen(string? inputText) => inputText?.Length == 1 && (char.IsLetterOrDigit(inputText[0]) || inputText[0] == '_'); private static bool IsIdentifierCharacter(char character) @@ -171,14 +183,14 @@ private void DismissTransientToolTips() return (location.Line - 1, location.Column - 1); } - private static CancellationToken ResetCancellationTokenSource(ref CancellationTokenSource cancellationTokenSource) + private static CancellationToken ResetCancellationTokenSource(ref CancellationTokenSource? cancellationTokenSource) { CancelAndDispose(ref cancellationTokenSource); cancellationTokenSource = new CancellationTokenSource(); return cancellationTokenSource.Token; } - private static void CancelAndDispose(ref CancellationTokenSource cancellationTokenSource) + private static void CancelAndDispose(ref CancellationTokenSource? cancellationTokenSource) { if (cancellationTokenSource is null) return; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index 932fb1315e..455563b4cc 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -1,19 +1,20 @@ using System; -using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Utils; namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private async void TextEditor_KeyDown(object sender, KeyEventArgs e) + private async void TextEditor_KeyDown(object? sender, KeyEventArgs e) { - if (e.Key == Key.Escape && (_signaturePopup.IsOpen || _specialToolTip.IsOpen)) + if (e.Key == Key.Escape && (_completionWindow is not null || _signaturePopup.IsOpen || _specialToolTip.IsOpen)) { + CloseCompletionWindow(); DismissTransientToolTips(); e.Handled = true; return; @@ -29,13 +30,16 @@ private async void TextEditor_KeyDown(object sender, KeyEventArgs e) } } - private void TextEditor_PreviewMouseDown(object sender, MouseButtonEventArgs e) + private void TextEditor_PreviewMouseDown(object? sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left || e.ChangedButton == MouseButton.Right) + { + CloseCompletionWindow(); DismissTransientToolTips(); + } } - private async void TextEditor_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + private async void TextEditor_PreviewMouseLeftButtonDown(object? sender, MouseButtonEventArgs e) { if (!Keyboard.Modifiers.HasFlag(ModifierKeys.Control) || e.ChangedButton != MouseButton.Left) return; @@ -56,22 +60,20 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo try { - foreach (int candidateOffset in GetDefinitionCandidateOffsets(offset)) - { - (int line, int column) = GetPositionFromOffset(candidateOffset); + if (!LuaEditorInteractionRules.TryGetDefinitionStartOffset(Document, offset, out int definitionOffset)) + return false; - LuaDefinitionLocation definitionLocation = await IntellisenseProvider - .GetDefinitionAsync(FilePath, Text, line, column, cancellationToken) - .ConfigureAwait(true); + (int line, int column) = GetPositionFromOffset(definitionOffset); - if (definitionLocation is null) - continue; + LuaDefinitionLocation? definitionLocation = await IntellisenseProvider + .GetDefinitionAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); - DefinitionNavigationRequested?.Invoke(definitionLocation); - return true; - } + if (definitionLocation is null) + return false; - return false; + DefinitionNavigationRequested?.Invoke(definitionLocation); + return true; } catch (OperationCanceledException) { @@ -86,66 +88,5 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo public async void NavigateToDefinitionAtCaretAsync() => await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true); - - private IEnumerable GetDefinitionCandidateOffsets(int offset) - { - int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); - var offsets = new List(); - - AddDefinitionCandidateOffset(offsets, safeOffset); - - if (safeOffset > 0) - AddDefinitionCandidateOffset(offsets, safeOffset - 1); - - if (TryGetDefinitionWordBounds(safeOffset, out int wordStart, out int wordEnd)) - { - AddDefinitionCandidateOffset(offsets, wordStart); - AddDefinitionCandidateOffset(offsets, wordEnd - 1); - } - - return offsets; - } - - private bool TryGetDefinitionWordBounds(int offset, out int wordStart, out int wordEnd) - { - wordStart = 0; - wordEnd = 0; - - if (Document.TextLength == 0) - return false; - - int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); - int probeOffset = safeOffset; - - if (probeOffset >= Document.TextLength) - probeOffset = Document.TextLength - 1; - - if (probeOffset > 0 - && !IsIdentifierCharacter(Document.GetCharAt(probeOffset)) - && IsIdentifierCharacter(Document.GetCharAt(probeOffset - 1))) - { - probeOffset--; - } - - if (!IsIdentifierCharacter(Document.GetCharAt(probeOffset))) - return false; - - wordStart = probeOffset; - wordEnd = probeOffset + 1; - - while (wordStart > 0 && IsIdentifierCharacter(Document.GetCharAt(wordStart - 1))) - wordStart--; - - while (wordEnd < Document.TextLength && IsIdentifierCharacter(Document.GetCharAt(wordEnd))) - wordEnd++; - - return wordEnd > wordStart; - } - - private static void AddDefinitionCandidateOffset(ICollection offsets, int offset) - { - if (!offsets.Contains(offset)) - offsets.Add(offset); - } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs index b016ddf735..42c601c15b 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs @@ -6,12 +6,12 @@ namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private LuaSemanticTokensColorizer _semanticTokensColorizer; + private LuaSemanticTokensColorizer? _semanticTokensColorizer; public void SetSemanticTokens(IReadOnlyList tokens) { EnsureSemanticTokensColorizerAttached(); - _semanticTokensColorizer.SetTokens(tokens); + _semanticTokensColorizer!.SetTokens(tokens); } public void ClearSemanticTokens() diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index 248b1778e8..6fb72ef0fe 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -17,7 +17,7 @@ public sealed partial class LuaEditor private static readonly SolidColorBrush SignatureActiveParamForeground = CreateFrozenBrush(Color.FromRgb(86, 180, 235)); private static readonly SolidColorBrush SignatureForeground = CreateFrozenBrush(Colors.Gainsboro); - private CancellationTokenSource _signatureCancellationTokenSource; + private CancellationTokenSource? _signatureCancellationTokenSource; private readonly Popup _signaturePopup = new Popup(); private readonly Border _signaturePopupBorder = new Border(); @@ -43,7 +43,7 @@ private void InitializeSignaturePopup() private void DismissSignatureHelp() { - _signatureCancellationTokenSource?.Cancel(); + CancelAndDispose(ref _signatureCancellationTokenSource); if (_signaturePopup.IsOpen) _signaturePopup.IsOpen = false; @@ -150,7 +150,7 @@ private async Task RequestSignatureHelpAsync(int offset) try { (int line, int column) = GetPositionFromOffset(offset); - LuaSignatureInfo signatureInfo = await IntellisenseProvider + LuaSignatureInfo? signatureInfo = await IntellisenseProvider .GetSignatureHelpAsync(FilePath, Text, line, column, cancellationToken) .ConfigureAwait(true); diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index 7b6c8f0640..a23d732ca5 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -11,10 +11,10 @@ public sealed partial class LuaEditor : TextEditorBase { public override string DefaultFileExtension => ".lua"; - private LuaTextMateInstallation _textMateHighlighting; + private LuaTextMateInstallation? _textMateHighlighting; - public ILuaIntellisenseProvider IntellisenseProvider { get; set; } - public event Action DefinitionNavigationRequested; + public ILuaIntellisenseProvider? IntellisenseProvider { get; set; } + public event Action? DefinitionNavigationRequested; public LuaEditor(Version engineVersion) : base(engineVersion) { diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs index 9b9633fca4..44174d0e6a 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs @@ -11,7 +11,7 @@ public sealed class LuaEditorConfiguration : TextEditorConfigBase public override string DefaultPath { get; } public ColorScheme ColorScheme = new ColorScheme(); - private string _selectedColorSchemeName; + private string _selectedColorSchemeName = ConfigurationDefaults.SelectedColorSchemeName; public string SelectedColorSchemeName { diff --git a/TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs b/TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs index 942509664e..a6efc6bf9b 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs @@ -1,4 +1,6 @@ -namespace TombLib.Scripting.Lua +#nullable disable + +namespace TombLib.Scripting.Lua { partial class LuaTextBox { diff --git a/TombLib/TombLib.Scripting.Lua/LuaTextBox.cs b/TombLib/TombLib.Scripting.Lua/LuaTextBox.cs index 357e0ff7f8..223b8a1fce 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaTextBox.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaTextBox.cs @@ -8,9 +8,10 @@ namespace TombLib.Scripting.Lua { public partial class LuaTextBox : UserControl { - private DarkTranslucentForm _overlayForm; + private DarkTranslucentForm? _overlayForm; + private LuaEditor? _textEditor; - public LuaEditor TextEditor { get; private set; } + public LuaEditor TextEditor => _textEditor ?? throw new InvalidOperationException("Lua editor is not initialized."); public LuaTextBox() { @@ -23,11 +24,11 @@ private void InitializeTextEditor() { if (LicenseManager.UsageMode == LicenseUsageMode.Runtime) { - TextEditor = new LuaEditor(new Version(0, 0)); - TextEditor.AllowDrop = true; - TextEditor.WordWrap = true; - TextEditor.DragEnter += textEditor_DragEnter; - ehTextEditor.Child = TextEditor; + _textEditor = new LuaEditor(new Version(0, 0)); + _textEditor.AllowDrop = true; + _textEditor.WordWrap = true; + _textEditor.DragEnter += textEditor_DragEnter; + ehTextEditor.Child = _textEditor; _overlayForm = new DarkTranslucentForm(Colors.GreyBackground, 0.01); // 0 won't show form! _overlayForm.AllowDrop = true; @@ -39,34 +40,48 @@ private void InitializeTextEditor() public void Paste(string text) { - TextEditor.TextArea.PerformTextInput(text); - TextEditor.Focus(); + if (_textEditor is null) + return; + + _textEditor.TextArea.PerformTextInput(text); + _textEditor.Focus(); } protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); - TextEditor.Focus(); + + if (_textEditor is not null) + _textEditor.Focus(); } - private void textEditor_DragEnter(object sender, System.Windows.DragEventArgs e) + private void textEditor_DragEnter(object? sender, System.Windows.DragEventArgs e) { + if (_overlayForm is null) + return; + _overlayForm.Show(); _overlayForm.Location = PointToScreen(new System.Drawing.Point(0)); _overlayForm.Size = ClientSize; } - private void overlayForm_DragEnter(object sender, DragEventArgs e) => + private void overlayForm_DragEnter(object? sender, DragEventArgs e) => OnDragEnter(e); - private void overlayForm_DragDrop(object sender, DragEventArgs e) + private void overlayForm_DragDrop(object? sender, DragEventArgs e) { + if (_overlayForm is null) + return; + _overlayForm.Hide(); OnDragDrop(e); } - private void overlayForm_DragLeave(object sender, EventArgs e) + private void overlayForm_DragLeave(object? sender, EventArgs e) { + if (_overlayForm is null) + return; + _overlayForm.Hide(); OnDragLeave(e); } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs index 1538bb8436..c81728fba0 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs @@ -13,13 +13,13 @@ public sealed class ColorScheme : ColorSchemeBase public HighlightingObject Operators { get; set; } = new HighlightingObject(); public HighlightingObject SpecialOperators { get; set; } = new HighlightingObject(); - public static bool operator ==(ColorScheme left, ColorScheme right) + public static bool operator ==(ColorScheme? left, ColorScheme? right) => ReferenceEquals(left, right) || left is not null && left.Equals(right); - public static bool operator !=(ColorScheme left, ColorScheme right) + public static bool operator !=(ColorScheme? left, ColorScheme? right) => !(left == right); - public override bool Equals(object obj) + public override bool Equals(object? obj) { if (obj is not ColorScheme other) return false; diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index c061d29fac..d3b2fec0ac 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -23,9 +23,9 @@ public sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged private static readonly SolidColorBrush DescriptionForegroundBrush = CreateFrozenBrush(Colors.Gainsboro); private readonly object _resolveSync = new object(); private LuaCompletionItem _item; - private string _displayDetail; - private object _cachedDescription; - private Task _resolveTask; + private string? _displayDetail; + private object? _cachedDescription; + private Task? _resolveTask; public LuaCompletionData(LuaCompletionItem item) { @@ -33,22 +33,22 @@ public LuaCompletionData(LuaCompletionItem item) _displayDetail = FlattenSingleLineText(_item.Detail); } - public event PropertyChangedEventHandler PropertyChanged; + public event PropertyChangedEventHandler? PropertyChanged; public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind); public string Text => _item.FilterText; public string DisplayText => _item.Label; - public string DisplayDetail => _displayDetail; + public string? DisplayDetail => _displayDetail; public Visibility DetailVisibility => string.IsNullOrEmpty(_displayDetail) ? Visibility.Collapsed : Visibility.Visible; public object Content => DisplayText; - public object Description => _cachedDescription ??= BuildDescriptionContent(); + public object? Description => _cachedDescription ??= BuildDescriptionContent(); public double Priority => _item.Priority; public bool CanResolve => _item.CanResolve; public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) => textArea.Document.Replace(completionSegment, _item.InsertText); - public async Task GetDescriptionAsync(CancellationToken cancellationToken = default) + public async Task GetDescriptionAsync(CancellationToken cancellationToken = default) { if (!CanResolve) return Description; @@ -87,7 +87,7 @@ public async Task GetDescriptionAsync(CancellationToken cancellationToke } } - private static string FlattenSingleLineText(string text) + private static string? FlattenSingleLineText(string? text) { if (string.IsNullOrWhiteSpace(text)) return null; @@ -96,7 +96,7 @@ private static string FlattenSingleLineText(string text) return lines.Length == 0 ? null : string.Join(" ", lines).Trim(); } - private object BuildDescriptionContent() + private object? BuildDescriptionContent() { bool hasDetail = !string.IsNullOrWhiteSpace(_item.Detail); bool hasDescription = !string.IsNullOrWhiteSpace(_item.Description); @@ -126,9 +126,11 @@ private object BuildDescriptionContent() if (hasDescription) { + string descriptionText = _item.Description!; + panel.Children.Add(_item.IsDescriptionMarkdown - ? MarkdownToolTipRenderer.CreateContent(_item.Description, DescriptionForegroundBrush, DescriptionBackgroundBrush, false) - : MarkdownToolTipRenderer.CreatePlainTextContent(_item.Description, DescriptionForegroundBrush, false)); + ? MarkdownToolTipRenderer.CreateContent(descriptionText, DescriptionForegroundBrush, DescriptionBackgroundBrush, false) + : MarkdownToolTipRenderer.CreatePlainTextContent(descriptionText, DescriptionForegroundBrush, false)); } return new Border @@ -157,7 +159,7 @@ private void ApplyResolvedItem(LuaCompletionItem resolvedItem) OnPropertyChanged(nameof(Description)); } - private void OnPropertyChanged([CallerMemberName] string propertyName = null) + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs index 123050880d..0db7465413 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -21,7 +21,7 @@ public static ImageSource GetIcon(LuaCompletionIconKind kind) { lock (Cache) { - if (Cache.TryGetValue(kind, out ImageSource image)) + if (Cache.TryGetValue(kind, out ImageSource? image)) return image; image = CreateIcon(kind); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index 98be1fa438..cf22fe3a7e 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -6,19 +6,19 @@ namespace TombLib.Scripting.Lua.Objects { public sealed class LuaCompletionItem { - private readonly Func> _resolveAsync; + private readonly Func>? _resolveAsync; public LuaCompletionItem( string label, - string insertText = null, - string detail = null, - string description = null, - string filterText = null, + string? insertText = null, + string? detail = null, + string? description = null, + string? filterText = null, double priority = 0.0, LuaCompletionItemKind kind = LuaCompletionItemKind.Text, LuaCompletionIconKind iconKind = LuaCompletionIconKind.Misc, bool isDescriptionMarkdown = false, - Func> resolveAsync = null) + Func>? resolveAsync = null) { Label = label ?? throw new ArgumentNullException(nameof(label)); InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; @@ -34,8 +34,8 @@ public LuaCompletionItem( public string Label { get; } public string InsertText { get; } - public string Detail { get; } - public string Description { get; } + public string? Detail { get; } + public string? Description { get; } public string FilterText { get; } public double Priority { get; } public LuaCompletionItemKind Kind { get; } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs index 0ce669955e..cdb5417a57 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs @@ -5,7 +5,7 @@ namespace TombLib.Scripting.Lua.Objects { public sealed class LuaSignatureInfo { - public LuaSignatureInfo(string label, string documentation, IReadOnlyList parameters, + public LuaSignatureInfo(string label, string? documentation, IReadOnlyList parameters, int activeParameter) { Label = label ?? throw new ArgumentNullException(nameof(label)); @@ -15,20 +15,20 @@ public LuaSignatureInfo(string label, string documentation, IReadOnlyList Parameters { get; } public int ActiveParameter { get; } } public sealed class LuaParameterInfo { - public LuaParameterInfo(string label, string documentation) + public LuaParameterInfo(string label, string? documentation) { Label = label ?? string.Empty; Documentation = documentation; } public string Label { get; } - public string Documentation { get; } + public string? Documentation { get; } } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs b/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs index 839ca5ee94..69aaaa0e66 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs @@ -30,10 +30,10 @@ public SyntaxHighlighting(ColorScheme scheme) public IEnumerable NamedHighlightingColors => EmptyHighlightingColors; public IDictionary Properties => EmptyProperties; - public HighlightingColor GetNamedColor(string name) + public HighlightingColor? GetNamedColor(string name) => null; - public HighlightingRuleSet GetNamedRuleSet(string name) + public HighlightingRuleSet? GetNamedRuleSet(string name) => string.Equals(name, Name, StringComparison.Ordinal) ? _mainRuleSet : null; private HighlightingRuleSet CreateMainRuleSet() diff --git a/TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs b/TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs new file mode 100644 index 0000000000..aac16969dc --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("TombLib.Test")] \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs index 15931cdd9a..e7ec28523a 100644 --- a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs +++ b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs @@ -10,8 +10,8 @@ namespace TombLib.Scripting.Lua.Services public interface ILuaIntellisenseProvider : IDisposable { bool IsAvailable { get; } - event Action> DiagnosticsUpdated; - event Action> SemanticTokensUpdated; + event Action>? DiagnosticsUpdated; + event Action>? SemanticTokensUpdated; IReadOnlyList GetDiagnostics(string filePath); IReadOnlyList GetSemanticTokens(string filePath); @@ -23,13 +23,13 @@ public interface ILuaIntellisenseProvider : IDisposable Task> GetCompletionItemsAsync(string filePath, string content, int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default); - Task GetHoverAsync(string filePath, string content, + Task GetHoverAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); - Task GetDefinitionAsync(string filePath, string content, + Task GetDefinitionAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); - Task GetSignatureHelpAsync(string filePath, string content, + Task GetSignatureHelpAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index ad64531840..3e4178502f 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -3,6 +3,7 @@ net6.0-windows Library false + enable true true true diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs new file mode 100644 index 0000000000..a9ac74b990 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -0,0 +1,120 @@ +using System; +using ICSharpCode.AvalonEdit.Document; + +namespace TombLib.Scripting.Lua.Utils +{ + internal static class LuaEditorInteractionRules + { + public static bool CanRequestHover(TextDocument? document, int offset, bool isCompletionWindowOpen, bool isSignatureHelpOpen) + { + if (isCompletionWindowOpen || isSignatureHelpOpen) + return false; + + return !IsInsideCommentOrString(document, offset); + } + + public static bool IsValidAutocompleteContext(TextDocument? document, int offset, char? triggerCharacter) + { + if (offset <= 0 || document is null || document.TextLength == 0) + return false; + + if (IsInsideCommentOrString(document, offset)) + return false; + + if (triggerCharacter is '.' || triggerCharacter is ':') + return true; + + char typedCharacter = document.GetCharAt(offset - 1); + + if (!IsIdentifierCharacter(typedCharacter)) + return false; + + if (offset >= 2 && document.GetCharAt(offset - 2) == '.') + return false; + + return true; + } + + public static bool IsValidManualCompletionContext(TextDocument? document, int offset) + { + if (document is null) + return false; + + if (document.TextLength == 0) + return true; + + return !IsInsideCommentOrString(document, offset); + } + + public static bool TryGetDefinitionStartOffset(TextDocument? document, int offset, out int definitionOffset) + { + definitionOffset = 0; + + if (document is null || document.TextLength == 0) + return false; + + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + + if (IsInsideCommentOrString(document, safeOffset)) + return false; + + if (!TryGetDefinitionWordBounds(document, safeOffset, out definitionOffset, out _)) + return false; + + return true; + } + + public static bool IsInsideCommentOrString(TextDocument? document, int offset) + { + if (document is null || document.TextLength == 0) + return false; + + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + DocumentLine currentLine = document.GetLineByOffset(safeOffset); + int lineStart = currentLine.Offset; + int inspectedLength = Math.Max(0, Math.Min(safeOffset, currentLine.EndOffset) - lineStart); + string lineText = document.GetText(lineStart, inspectedLength); + + return LuaLineParser.IsInsideCommentOrString(lineText); + } + + private static bool TryGetDefinitionWordBounds(TextDocument document, int offset, out int wordStart, out int wordEnd) + { + wordStart = 0; + wordEnd = 0; + + if (document.TextLength == 0) + return false; + + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + int probeOffset = safeOffset; + + if (probeOffset >= document.TextLength) + probeOffset = document.TextLength - 1; + + if (probeOffset > 0 + && !IsIdentifierCharacter(document.GetCharAt(probeOffset)) + && IsIdentifierCharacter(document.GetCharAt(probeOffset - 1))) + { + probeOffset--; + } + + if (!IsIdentifierCharacter(document.GetCharAt(probeOffset))) + return false; + + wordStart = probeOffset; + wordEnd = probeOffset + 1; + + while (wordStart > 0 && IsIdentifierCharacter(document.GetCharAt(wordStart - 1))) + wordStart--; + + while (wordEnd < document.TextLength && IsIdentifierCharacter(document.GetCharAt(wordEnd))) + wordEnd++; + + return wordEnd > wordStart; + } + + private static bool IsIdentifierCharacter(char character) + => char.IsLetterOrDigit(character) || character == '_'; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs new file mode 100644 index 0000000000..7040152f51 --- /dev/null +++ b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs @@ -0,0 +1,112 @@ +using System; +using ICSharpCode.AvalonEdit.Document; +using TombLib.Scripting.Lua.Utils; + +namespace TombLib.Test; + +[TestClass] +public class LuaEditorInteractionRulesTests +{ + [TestMethod] + public void IsValidAutocompleteContext_AllowsMemberTriggerInCode() + { + var document = CreateDocument("player."); + + bool result = LuaEditorInteractionRules.IsValidAutocompleteContext(document, document.TextLength, '.'); + + Assert.IsTrue(result); + } + + [TestMethod] + public void IsValidAutocompleteContext_BlocksIdentifierImmediatelyAfterDot() + { + var document = CreateDocument("player.a"); + + bool result = LuaEditorInteractionRules.IsValidAutocompleteContext(document, document.TextLength, null); + + Assert.IsFalse(result); + } + + [TestMethod] + public void IsValidManualCompletionContext_BlocksCommentText() + { + var document = CreateDocument("-- player"); + + bool result = LuaEditorInteractionRules.IsValidManualCompletionContext(document, document.TextLength); + + Assert.IsFalse(result); + } + + [TestMethod] + public void IsValidManualCompletionContext_BlocksOpenString() + { + var document = CreateDocument("print(\"player"); + + bool result = LuaEditorInteractionRules.IsValidManualCompletionContext(document, document.TextLength); + + Assert.IsFalse(result); + } + + [TestMethod] + public void CanRequestHover_ReturnsFalseWhenCompletionWindowIsOpen() + { + var document = CreateDocument("player"); + + bool result = LuaEditorInteractionRules.CanRequestHover(document, document.TextLength, true, false); + + Assert.IsFalse(result); + } + + [TestMethod] + public void CanRequestHover_BlocksCommentText() + { + var document = CreateDocument("value = 1 -- hover target"); + + bool result = LuaEditorInteractionRules.CanRequestHover(document, document.TextLength, false, false); + + Assert.IsFalse(result); + } + + [TestMethod] + public void TryGetDefinitionStartOffset_ReturnsWordStartFromInsideIdentifier() + { + const string identifier = "targetValue"; + string text = "local " + identifier + " = 1"; + var document = CreateDocument(text); + int identifierStart = text.IndexOf(identifier, StringComparison.Ordinal); + int probeOffset = identifierStart + 4; + + bool result = LuaEditorInteractionRules.TryGetDefinitionStartOffset(document, probeOffset, out int definitionOffset); + + Assert.IsTrue(result); + Assert.AreEqual(identifierStart, definitionOffset); + } + + [TestMethod] + public void TryGetDefinitionStartOffset_ReturnsWordStartWhenCaretIsAfterIdentifier() + { + const string identifier = "targetValue"; + string text = "return " + identifier; + var document = CreateDocument(text); + int identifierStart = text.IndexOf(identifier, StringComparison.Ordinal); + int probeOffset = identifierStart + identifier.Length; + + bool result = LuaEditorInteractionRules.TryGetDefinitionStartOffset(document, probeOffset, out int definitionOffset); + + Assert.IsTrue(result); + Assert.AreEqual(identifierStart, definitionOffset); + } + + [TestMethod] + public void TryGetDefinitionStartOffset_BlocksCommentText() + { + var document = CreateDocument("-- targetValue"); + + bool result = LuaEditorInteractionRules.TryGetDefinitionStartOffset(document, document.TextLength, out _); + + Assert.IsFalse(result); + } + + private static TextDocument CreateDocument(params string[] lines) + => new(string.Join(Environment.NewLine, lines)); +} \ No newline at end of file From a75991d8bd15cecabed5c9506026f57d9986ae43 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 13:10:39 +0100 Subject: [PATCH 06/34] Refactor pass 3 --- TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs | 13 +- .../LuaLanguageServerIntellisenseProvider.cs | 103 ++++--- .../LuaLanguageServerResponseParser.cs | 92 +++--- .../TextEditors/ColorSchemes/Lua/VS15.luasch | 30 ++ .../LuaSemanticTokensColorizer.cs | 39 ++- .../LuaEditor.Completion.cs | 86 ++++-- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 36 ++- .../LuaEditor.Intellisense.cs | 13 +- .../LuaEditor.SignatureHelp.cs | 48 ++-- TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 40 ++- .../Objects/ColorScheme.cs | 19 +- .../Objects/LuaCompletionData.cs | 8 +- .../Objects/LuaCompletionIconFactory.cs | 34 +-- .../Objects/LuaCompletionItem.cs | 3 - .../Objects/LuaCompletionItemKind.cs | 31 -- .../Objects/LuaCompletionWindowStyle.cs | 7 +- .../Resources/LuaEditorColorPalette.cs | 23 ++ .../TombEngineLanguageScriptService.cs | 133 --------- .../TombLib.Scripting.Lua.csproj | 3 + .../Utils/LuaEditorInteractionRules.cs | 15 +- .../Utils/LuaLineParser.cs | 272 +++++++++++++++--- .../Utils/TombEngineLanguageScriptService.cs | 135 +++++++++ .../TombLib.Scripting/Bases/TextEditorBase.cs | 22 +- .../Rendering/MarkdownToolTipRenderer.cs | 4 +- .../Resources/TextEditorColorPalette.cs | 21 ++ TombLib/TombLib.Test/LuaColorSchemeTests.cs | 21 ++ .../LuaEditorInteractionRulesTests.cs | 20 ++ TombLib/TombLib.Test/LuaLineParserTests.cs | 40 +++ .../TombEngineLanguageScriptServiceTests.cs | 19 +- 29 files changed, 922 insertions(+), 408 deletions(-) create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch delete mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs create mode 100644 TombLib/TombLib.Scripting/Resources/TextEditorColorPalette.cs create mode 100644 TombLib/TombLib.Test/LuaColorSchemeTests.cs create mode 100644 TombLib/TombLib.Test/LuaLineParserTests.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs index 30bd943273..235ec63f45 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs @@ -18,7 +18,7 @@ using TombLib.Scripting.Interfaces; using TombLib.Scripting.Lua; using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Lua.Utils; using TombLib.Scripting.Objects; namespace TombIDE.ScriptingStudio @@ -162,7 +162,7 @@ private void AppendGameFlowScript(string scriptText, bool wasScriptFileAlreadyOp private void AppendLanguageScript(string languageScript, bool wasLanguageFileAlreadyOpened, bool wasLanguageFileFileChanged) { - EditorTabControl.OpenFile(PathHelper.GetLanguageFilePath(ScriptRootDirectoryPath, TombLib.LevelData.TRVersion.Game.TombEngine), EditorType.Text); + EditorTabControl.OpenFile(PathHelper.GetLanguageFilePath(ScriptRootDirectoryPath, TombLib.LevelData.TRVersion.Game.TombEngine)); TabPage affectedTab = EditorTabControl.SelectedTab; if (CurrentEditor is TextEditorBase stringsEditor) @@ -208,7 +208,7 @@ private void CreateGeneratedFiles(IReadOnlyList files) private bool IsLevelLanguageStringDefined(string levelName) { - EditorTabControl.OpenFile(PathHelper.GetLanguageFilePath(ScriptRootDirectoryPath, TombLib.LevelData.TRVersion.Game.TombEngine), EditorType.Text); + EditorTabControl.OpenFile(PathHelper.GetLanguageFilePath(ScriptRootDirectoryPath, TombLib.LevelData.TRVersion.Game.TombEngine)); if (CurrentEditor is TextEditorBase editor) { @@ -223,7 +223,7 @@ private bool IsLevelLanguageStringDefined(string levelName) private void RenameRequestedLanguageString(string oldName, string newName) { - EditorTabControl.OpenFile(PathHelper.GetLanguageFilePath(ScriptRootDirectoryPath, TombLib.LevelData.TRVersion.Game.TombEngine), EditorType.Text); + EditorTabControl.OpenFile(PathHelper.GetLanguageFilePath(ScriptRootDirectoryPath, TombLib.LevelData.TRVersion.Game.TombEngine)); if (CurrentEditor is TextEditorBase editor) { @@ -282,7 +282,10 @@ protected override void ApplyUserSettings() ApplyUserSettings(editor); if (editor is LuaEditor luaEditor) - ApplyDiagnosticsToEditor(luaEditor, _intellisenseProvider?.GetDiagnostics(luaEditor.FilePath)); + { + ApplyDiagnosticsToEditor(luaEditor, _intellisenseProvider.GetDiagnostics(luaEditor.FilePath)); + ApplySemanticTokensToEditor(luaEditor, _intellisenseProvider.GetSemanticTokens(luaEditor.FilePath)); + } } UpdateSettings(); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index c7d9db2496..49086f5d89 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -60,10 +61,10 @@ public IReadOnlyList GetSemanticTokens(string filePath) } public void OpenDocument(string filePath, string content) - => _ = TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None); + => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document open"); public void UpdateDocument(string filePath, string content) - => _ = TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None); + => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document change"); public void CloseDocument(string filePath) { @@ -73,7 +74,7 @@ public void CloseDocument(string filePath) if (!_documents.TryClose(normalizedFilePath, out LuaDocumentSnapshot document)) return; - _ = CloseDocumentAsync(document, CancellationToken.None); + ObserveBackgroundTask(CloseDocumentAsync(document, CancellationToken.None), "Document close"); } public async Task> GetCompletionItemsAsync(string filePath, string content, @@ -258,40 +259,54 @@ private async Task SynchronizeDocumentAsync(string filePath, string conten if (request is null) return true; - if (request.Kind == LuaDocumentSynchronizationKind.Open) + try { - await _client.SendNotificationAsync("textDocument/didOpen", - new - { - textDocument = new + if (request.Kind == LuaDocumentSynchronizationKind.Open) + { + await _client.SendNotificationAsync("textDocument/didOpen", + new { - uri = request.Document.Uri, - languageId = "lua", - version = request.Document.Version, - text = request.Document.Content - } - }, cancellationToken).ConfigureAwait(false); + textDocument = new + { + uri = request.Document.Uri, + languageId = "lua", + version = request.Document.Version, + text = request.Document.Content + } + }, cancellationToken).ConfigureAwait(false); + } + else if (request.Kind == LuaDocumentSynchronizationKind.Change) + { + await _client.SendNotificationAsync("textDocument/didChange", + new + { + textDocument = new + { + uri = request.Document.Uri, + version = request.Document.Version + }, + contentChanges = new[] + { + new { text = request.Document.Content } + } + }, cancellationToken).ConfigureAwait(false); + } + + await RefreshSemanticTokensAsync(request.Document, cancellationToken).ConfigureAwait(false); + return true; } - else if (request.Kind == LuaDocumentSynchronizationKind.Change) + catch (OperationCanceledException) { - await _client.SendNotificationAsync("textDocument/didChange", - new - { - textDocument = new - { - uri = request.Document.Uri, - version = request.Document.Version - }, - contentChanges = new[] - { - new { text = request.Document.Content } - } - }, cancellationToken).ConfigureAwait(false); + throw; + } + catch (IOException) + { + return false; + } + catch (ObjectDisposedException) + { + return false; } - - await RefreshSemanticTokensAsync(request.Document, cancellationToken).ConfigureAwait(false); - - return true; } private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) @@ -387,6 +402,30 @@ private void HandleDiagnosticsPublished(JsonElement parameters) DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); } + private static void ObserveBackgroundTask(Task task, string operation) + => _ = ObserveBackgroundTaskAsync(task, operation); + + private static async Task ObserveBackgroundTaskAsync(Task task, string operation) + { + try + { + await task.ConfigureAwait(false); + } + catch (OperationCanceledException) + { + } + catch (IOException) + { + } + catch (ObjectDisposedException) + { + } + catch (Exception exception) + { + Debug.WriteLine($"[LuaLS] {operation} failed: {exception}"); + } + } + public void Dispose() { if (_isDisposed) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs index 370f4957c1..05b1e2b00f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -11,6 +11,35 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense { internal static class LuaLanguageServerResponseParser { + private enum LuaLanguageServerCompletionKind + { + Text = 1, + Method = 2, + Function = 3, + Constructor = 4, + Field = 5, + Variable = 6, + Class = 7, + Interface = 8, + Module = 9, + Property = 10, + Unit = 11, + Value = 12, + Enum = 13, + Keyword = 14, + Snippet = 15, + Color = 16, + File = 17, + Reference = 18, + Folder = 19, + EnumMember = 20, + Constant = 21, + Struct = 22, + Event = 23, + Operator = 24, + TypeParameter = 25 + } + private readonly struct MarkupContent { public MarkupContent(string text, bool isMarkdown) @@ -94,9 +123,9 @@ public static LuaCompletionItem ParseCompletionItem(JsonElement itemElement, int ? filterTextElement.GetString() : label; - LuaCompletionItemKind kind = TryReadCompletionKind(itemElement, out LuaCompletionItemKind completionKind) - ? completionKind - : LuaCompletionItemKind.Text; + LuaLanguageServerCompletionKind completionKind = TryReadCompletionKind(itemElement, out LuaLanguageServerCompletionKind parsedCompletionKind) + ? parsedCompletionKind + : LuaLanguageServerCompletionKind.Text; string detail = BuildCompletionDetail(itemElement); MarkupContent description = BuildCompletionDescription(itemElement); @@ -109,8 +138,7 @@ public static LuaCompletionItem ParseCompletionItem(JsonElement itemElement, int description.Text, filterText, BuildCompletionPriority(itemElement, detail, searchableDescription, itemIndex), - kind, - BuildCompletionIconKind(kind, detail), + BuildCompletionIconKind(completionKind, detail), description.IsMarkdown, resolveAsync); } @@ -157,22 +185,22 @@ private static double BuildCompletionPriority(JsonElement itemElement, string de return priority; } - private static bool TryReadCompletionKind(JsonElement itemElement, out LuaCompletionItemKind kind) + private static bool TryReadCompletionKind(JsonElement itemElement, out LuaLanguageServerCompletionKind kind) { - kind = LuaCompletionItemKind.Text; + kind = LuaLanguageServerCompletionKind.Text; if (!itemElement.TryGetProperty("kind", out JsonElement kindElement) || !kindElement.TryGetInt32(out int rawKind) - || !Enum.IsDefined(typeof(LuaCompletionItemKind), rawKind)) + || !Enum.IsDefined(typeof(LuaLanguageServerCompletionKind), rawKind)) { return false; } - kind = (LuaCompletionItemKind)rawKind; + kind = (LuaLanguageServerCompletionKind)rawKind; return true; } - private static LuaCompletionIconKind BuildCompletionIconKind(LuaCompletionItemKind kind, string detail) + private static LuaCompletionIconKind BuildCompletionIconKind(LuaLanguageServerCompletionKind kind, string detail) { if (CompletionTextContains(detail, "parameter")) return LuaCompletionIconKind.Parameter; @@ -206,28 +234,28 @@ private static LuaCompletionIconKind BuildCompletionIconKind(LuaCompletionItemKi return kind switch { - LuaCompletionItemKind.Method => LuaCompletionIconKind.Method, - LuaCompletionItemKind.Function => LuaCompletionIconKind.Method, - LuaCompletionItemKind.Constructor => LuaCompletionIconKind.Method, - LuaCompletionItemKind.Field => LuaCompletionIconKind.Field, - LuaCompletionItemKind.Variable => LuaCompletionIconKind.Variable, - LuaCompletionItemKind.Class => LuaCompletionIconKind.Class, - LuaCompletionItemKind.Interface => LuaCompletionIconKind.Class, - LuaCompletionItemKind.Module => LuaCompletionIconKind.Namespace, - LuaCompletionItemKind.Property => LuaCompletionIconKind.Property, - LuaCompletionItemKind.Value => LuaCompletionIconKind.Variable, - LuaCompletionItemKind.Enum => LuaCompletionIconKind.Class, - LuaCompletionItemKind.Keyword => LuaCompletionIconKind.Keyword, - LuaCompletionItemKind.Snippet => LuaCompletionIconKind.Keyword, - LuaCompletionItemKind.File => LuaCompletionIconKind.File, - LuaCompletionItemKind.Reference => LuaCompletionIconKind.Variable, - LuaCompletionItemKind.Folder => LuaCompletionIconKind.Folder, - LuaCompletionItemKind.EnumMember => LuaCompletionIconKind.Constant, - LuaCompletionItemKind.Constant => LuaCompletionIconKind.Constant, - LuaCompletionItemKind.Struct => LuaCompletionIconKind.Class, - LuaCompletionItemKind.Event => LuaCompletionIconKind.Method, - LuaCompletionItemKind.Operator => LuaCompletionIconKind.Keyword, - LuaCompletionItemKind.TypeParameter => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Method => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Function => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Constructor => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Field => LuaCompletionIconKind.Field, + LuaLanguageServerCompletionKind.Variable => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Class => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Interface => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Module => LuaCompletionIconKind.Namespace, + LuaLanguageServerCompletionKind.Property => LuaCompletionIconKind.Property, + LuaLanguageServerCompletionKind.Value => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Enum => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Keyword => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.Snippet => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.File => LuaCompletionIconKind.File, + LuaLanguageServerCompletionKind.Reference => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Folder => LuaCompletionIconKind.Folder, + LuaLanguageServerCompletionKind.EnumMember => LuaCompletionIconKind.Constant, + LuaLanguageServerCompletionKind.Constant => LuaCompletionIconKind.Constant, + LuaLanguageServerCompletionKind.Struct => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Event => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Operator => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.TypeParameter => LuaCompletionIconKind.Class, _ => LuaCompletionIconKind.Misc }; } diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch new file mode 100644 index 0000000000..7adfb4be37 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch @@ -0,0 +1,30 @@ + + + + #6A9955 + false + false + + + #569CD6 + false + false + + + #569CD6 + false + false + + + Gainsboro + false + false + + + #569CD6 + false + false + + #202020 + Gainsboro + \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index 69ee5b7fa5..84e9fa1d5e 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -5,21 +5,21 @@ using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using TombLib.Scripting.Lua.Objects; -using static TombLib.WPF.BrushHelpers; +using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua.Highlighting { internal sealed class LuaSemanticTokensColorizer : DocumentColorizingTransformer { - private static readonly Brush DefaultLibraryBrush = CreateFrozenBrush("#4EC9B0"); - private static readonly Brush GlobalVariableBrush = CreateFrozenBrush("#4FC1FF"); - private static readonly Brush TypeBrush = CreateFrozenBrush("#4EC9B0"); - private static readonly Brush FunctionBrush = CreateFrozenBrush("#DCDCAA"); - private static readonly Brush ParameterBrush = CreateFrozenBrush("#9CDCFE"); - private static readonly Brush PropertyBrush = CreateFrozenBrush("#9CDCFE"); - private static readonly Brush DecoratorBrush = CreateFrozenBrush("#C586C0"); - private static readonly Brush MacroBrush = CreateFrozenBrush("#C586C0"); - private static readonly Brush EnumMemberBrush = CreateFrozenBrush("#B5CEA8"); + private static readonly Brush DefaultLibraryBrush = LuaEditorColorPalette.TypeBrush; + private static readonly Brush GlobalVariableBrush = LuaEditorColorPalette.PropertyBrush; + private static readonly Brush TypeBrush = LuaEditorColorPalette.TypeBrush; + private static readonly Brush FunctionBrush = LuaEditorColorPalette.MethodBrush; + private static readonly Brush ParameterBrush = LuaEditorColorPalette.VariableBrush; + private static readonly Brush PropertyBrush = LuaEditorColorPalette.VariableBrush; + private static readonly Brush DecoratorBrush = LuaEditorColorPalette.KeywordBrush; + private static readonly Brush MacroBrush = LuaEditorColorPalette.KeywordBrush; + private static readonly Brush EnumMemberBrush = LuaEditorColorPalette.ConstantBrush; private static readonly TextDecorationCollection DeprecatedDecorations = CreateTextDecorations(TextDecorations.Strikethrough); private static readonly IReadOnlyDictionary> EmptyTokensByLine = new Dictionary>(); @@ -56,7 +56,19 @@ public void SetTokens(IReadOnlyList tokens) var frozenMap = new Dictionary>(groupedTokens.Count); foreach (KeyValuePair> pair in groupedTokens) + { + pair.Value.Sort((left, right) => + { + int characterComparison = left.Character.CompareTo(right.Character); + + if (characterComparison != 0) + return characterComparison; + + return left.Length.CompareTo(right.Length); + }); + frozenMap[pair.Key] = pair.Value; + } _tokensByLine = frozenMap; _textView.Redraw(); @@ -122,7 +134,6 @@ private static LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) return new LuaSemanticTokenStyle( foreground, token.HasModifier("declaration") && (token.Type == "function" || token.Type == "method"), - null, token.HasModifier("deprecated") ? DeprecatedDecorations : null); } @@ -163,20 +174,18 @@ private static TextDecorationCollection CreateTextDecorations(TextDecorationColl private readonly struct LuaSemanticTokenStyle { - public LuaSemanticTokenStyle(Brush? foreground, bool isBold, Brush? background, TextDecorationCollection? textDecorations) + public LuaSemanticTokenStyle(Brush? foreground, bool isBold, TextDecorationCollection? textDecorations) { Foreground = foreground; IsBold = isBold; - Background = background; TextDecorations = textDecorations; } public Brush? Foreground { get; } public bool IsBold { get; } - public Brush? Background { get; } public TextDecorationCollection? TextDecorations { get; } - public bool HasFormatting => Foreground is not null || Background is not null || IsBold || TextDecorations is not null; + public bool HasFormatting => Foreground is not null || IsBold || TextDecorations is not null; } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index 39a6c44641..d340d1b339 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using System; using System.Diagnostics; +using System.Globalization; using System.Reflection; using System.Threading; using System.Threading.Tasks; @@ -8,22 +10,32 @@ using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Interop; +using System.Windows.Media; using System.Windows.Threading; using ICSharpCode.AvalonEdit.CodeCompletion; using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Utils; using TombLib.WPF; namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { + private const int CompletionWindowMinWidth = 420; + private const int CompletionWindowMaxWidth = 920; + private const int CompletionWindowHeight = 320; + private const double CompletionToolTipHorizontalOffset = 10.0; + private const double CompletionToolTipResolveDelayInMilliseconds = 120.0; + private const double CompletionWindowHorizontalChrome = 52.0; + private const double CompletionItemIconWidth = 24.0; + private const double CompletionItemDetailSpacing = 12.0; + private static readonly FieldInfo? CompletionToolTipField = typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); private static bool _completionToolTipFieldLoggedMissing; private CancellationTokenSource? _completionCancellationTokenSource; - private CancellationTokenSource? _completionToolTipCancellationTokenSource; private int _completionRequestToken; private int _completionToolTipUpdateToken; @@ -43,7 +55,7 @@ private void CloseCompletionWindow() private void InitializeLuaCompletionWindow() { - InitializeCompletionWindow(420, 320); + InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); LuaCompletionWindowStyle.Apply(_completionWindow); StyleCompletionTooltip(); MakeCompletionWindowNonActivatable(); @@ -87,6 +99,7 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) CloseCompletionWindow(); InitializeLuaCompletionWindow(); + ResizeCompletionWindow(completionDataItems); SetCompletionWindowOffsets(offset); foreach (LuaCompletionData completionDataItem in completionDataItems) @@ -130,7 +143,7 @@ private void StyleCompletionTooltip() tooltip.Padding = new Thickness(0.0); tooltip.PlacementTarget = listBox; tooltip.Placement = PlacementMode.Right; - tooltip.HorizontalOffset = 10.0; + tooltip.HorizontalOffset = CompletionToolTipHorizontalOffset; tooltip.StaysOpen = true; listBox.SelectionChanged += (s, e) => ScheduleCompletionTooltipUpdate(tooltip); @@ -153,15 +166,14 @@ private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseBu private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) { - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionToolTipCancellationTokenSource); int updateToken = ++_completionToolTipUpdateToken; Dispatcher.BeginInvoke( - new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, cancellationToken, updateToken)), + new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, updateToken)), DispatcherPriority.Background); } - private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationToken cancellationToken, int updateToken) + private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken) { if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) return; @@ -185,9 +197,14 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationTok if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) { - object? resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); + await Task.Delay(TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds)).ConfigureAwait(true); + + if (updateToken != _completionToolTipUpdateToken) + return; - if (cancellationToken.IsCancellationRequested || updateToken != _completionToolTipUpdateToken) + object? resolvedDescription = await luaCompletionData.GetDescriptionAsync().ConfigureAwait(true); + + if (updateToken != _completionToolTipUpdateToken) return; if (_completionWindow?.CompletionList.ListBox is not ListBox currentListBox @@ -203,9 +220,6 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationTok tooltip.IsOpen = false; } } - catch (OperationCanceledException) - { - } catch (Exception exception) { tooltip.IsOpen = false; @@ -213,6 +227,49 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, CancellationTok } } + private void ResizeCompletionWindow(IReadOnlyList completionDataItems) + { + if (_completionWindow is null || completionDataItems is null || completionDataItems.Count == 0) + return; + + double requiredWidth = CompletionWindowMinWidth; + + for (int i = 0; i < completionDataItems.Count; i++) + requiredWidth = Math.Max(requiredWidth, MeasureCompletionItemWidth(completionDataItems[i])); + + _completionWindow.Width = Math.Max( + CompletionWindowMinWidth, + Math.Min(CompletionWindowMaxWidth, requiredWidth + CompletionWindowHorizontalChrome)); + } + + private double MeasureCompletionItemWidth(LuaCompletionData completionData) + { + double width = CompletionItemIconWidth + MeasureCompletionTextWidth(completionData.DisplayText); + + if (!string.IsNullOrWhiteSpace(completionData.DisplayDetail)) + width += CompletionItemDetailSpacing + MeasureCompletionTextWidth(completionData.DisplayDetail); + + return width; + } + + private double MeasureCompletionTextWidth(string text) + { + if (string.IsNullOrWhiteSpace(text)) + return 0.0; + + double pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip; + var formattedText = new FormattedText( + text, + CultureInfo.CurrentUICulture, + FlowDirection.LeftToRight, + new Typeface(FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), + FontSize, + Foreground, + pixelsPerDip); + + return formattedText.WidthIncludingTrailingWhitespace; + } + private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) { tooltip.Content = content; @@ -226,10 +283,7 @@ private static void ApplyCompletionToolTipContent(ToolTip tooltip, object conten } private void CancelCompletionToolTipUpdate() - { - CancelAndDispose(ref _completionToolTipCancellationTokenSource); - _completionToolTipUpdateToken++; - } + => _completionToolTipUpdateToken++; private void ScheduleCloseIfEmpty() => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); @@ -304,7 +358,7 @@ private void SetCompletionWindowOffsets(int offset) { char currentChar = Document.GetCharAt(startOffset - 1); - if (char.IsLetterOrDigit(currentChar) || currentChar == '_') + if (LuaLineParser.IsIdentifierCharacter(currentChar)) startOffset--; else break; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index 7f933c0e26..c913feea62 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -30,16 +30,15 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (!LuaEditorInteractionRules.CanRequestHover(Document, hoveredOffset, isCompletionWindowOpen, _signaturePopup.IsOpen)) { - if (!isCompletionWindowOpen && !_signaturePopup.IsOpen && hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + if (!isCompletionWindowOpen && !_signaturePopup.IsOpen) + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); return; } if (!IsIntellisenseAvailable()) { - if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); return; } @@ -48,8 +47,7 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (string.IsNullOrWhiteSpace(hoveredWord)) { - if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); return; } @@ -69,12 +67,7 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (currentHoveredOffset != hoveredOffset) return; - if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) && hasDiagnostic) - ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); - else if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content)) - ShowHoverToolTip(hoverInfo); - else if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + ShowBestHoverToolTip(hoverInfo, hasDiagnostic, diagnosticMessage, diagnosticSeverity); } catch (OperationCanceledException) { @@ -83,11 +76,26 @@ protected override async void HandleMouseHover(MouseEventArgs e) { WriteDebugFailure("Hover request", exception); - if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); } } + private void ShowDiagnosticToolTipIfAvailable(bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + { + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + } + + private void ShowBestHoverToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + { + if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) && hasDiagnostic) + ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); + else if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content)) + ShowHoverToolTip(hoverInfo); + else + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + } + private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) { GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index f072c4cbe5..9d38828273 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -155,17 +155,11 @@ private static bool TryGetCompletionTrigger(string? inputText, out char? trigger return true; } - return IsIdentifierTriggerCharacter(typedChar); + return LuaLineParser.IsIdentifierTriggerCharacter(typedChar); } private static bool ShouldKeepCompletionWindowOpen(string? inputText) - => inputText?.Length == 1 && (char.IsLetterOrDigit(inputText[0]) || inputText[0] == '_'); - - private static bool IsIdentifierCharacter(char character) - => char.IsLetterOrDigit(character) || character == '_'; - - private static bool IsIdentifierTriggerCharacter(char character) - => char.IsLetter(character) || character == '_'; + => inputText?.Length == 1 && LuaLineParser.IsIdentifierCharacter(inputText[0]); private void DismissTransientToolTips() { @@ -202,8 +196,7 @@ private static void CancelAndDispose(ref CancellationTokenSource? cancellationTo private static void WriteDebugFailure(string area, Exception exception) { - if (exception is not null) - Debug.WriteLine($"[Lua] {area} failed: {exception}"); + Debug.WriteLine($"[Lua] {area} failed: {exception}"); } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index 6fb72ef0fe..0e2bf509f6 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -7,15 +7,15 @@ using System.Windows.Documents; using System.Windows.Media; using TombLib.Scripting.Lua.Objects; -using static TombLib.WPF.BrushHelpers; +using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private static readonly SolidColorBrush SignatureParamDocForeground = CreateFrozenBrush(Color.FromRgb(180, 180, 180)); - private static readonly SolidColorBrush SignatureActiveParamForeground = CreateFrozenBrush(Color.FromRgb(86, 180, 235)); - private static readonly SolidColorBrush SignatureForeground = CreateFrozenBrush(Colors.Gainsboro); + private static readonly SolidColorBrush SignatureParamDocForeground = LuaEditorColorPalette.SignatureParamDocForeground; + private static readonly SolidColorBrush SignatureActiveParamForeground = LuaEditorColorPalette.SignatureActiveParamForeground; + private static readonly SolidColorBrush SignatureForeground = LuaEditorColorPalette.SignatureForeground; private CancellationTokenSource? _signatureCancellationTokenSource; @@ -64,6 +64,25 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) + _signaturePopupBorder.BorderThickness.Bottom; double contentMaxWidth = Math.Max(0.0, availablePopupWidth - popupHorizontalPadding); + StackPanel panel = CreateSignaturePanel(signatureInfo, contentMaxWidth); + + panel.Measure(new Size(contentMaxWidth, double.PositiveInfinity)); + Size popupSize = new Size( + Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), + panel.DesiredSize.Height + popupVerticalPadding); + + if (_signaturePopup.IsOpen) + _signaturePopup.IsOpen = false; + + _signaturePopupPresenter.Content = panel; + _signaturePopupPresenter.InvalidateMeasure(); + _signaturePopupBorder.InvalidateMeasure(); + PositionSignaturePopup(popupSize); + _signaturePopup.IsOpen = true; + } + + private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double contentMaxWidth) + { var panel = new StackPanel { MaxWidth = contentMaxWidth }; panel.Children.Add(BuildSignatureBlock(signatureInfo)); @@ -86,7 +105,7 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) if (!string.IsNullOrWhiteSpace(activeParam.Documentation)) { - var parameterDocumentation = new TextBlock + panel.Children.Add(new TextBlock { Text = activeParam.Label + ": " + activeParam.Documentation, Foreground = SignatureParamDocForeground, @@ -94,23 +113,15 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), TextWrapping = TextWrapping.Wrap, Margin = new Thickness(0.0, 4.0, 0.0, 0.0) - }; - - panel.Children.Add(parameterDocumentation); + }); } } - panel.Measure(new Size(contentMaxWidth, double.PositiveInfinity)); - Size popupSize = new Size( - Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), - panel.DesiredSize.Height + popupVerticalPadding); - - if (_signaturePopup.IsOpen) - _signaturePopup.IsOpen = false; + return panel; + } - _signaturePopupPresenter.Content = panel; - _signaturePopupPresenter.InvalidateMeasure(); - _signaturePopupBorder.InvalidateMeasure(); + private void PositionSignaturePopup(Size popupSize) + { AttachHostWindowHandlers(); _signaturePopup.PlacementTarget = this; TextArea.TextView.EnsureVisualLines(); @@ -134,7 +145,6 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) _signaturePopup.HorizontalOffset = horizontalOffset; _signaturePopup.VerticalOffset = verticalOffset; - _signaturePopup.IsOpen = true; } private async Task RequestSignatureHelpAsync(int offset) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index a23d732ca5..5e68c5c511 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -1,5 +1,9 @@ +using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.AvalonEdit.Highlighting.Xshd; using System; +using System.IO; using System.Windows.Media; +using System.Xml; using TombLib.Scripting.Bases; using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Objects; @@ -31,29 +35,57 @@ public override void UpdateSettings(Bases.ConfigurationBase configuration) _textMateHighlighting = null; if (!LuaTextMateSyntaxHighlighting.TryInstall(this, out _textMateHighlighting)) - SyntaxHighlighting = new SyntaxHighlighting(colorScheme); + SyntaxHighlighting = LoadFallbackSyntaxHighlighting() ?? new SyntaxHighlighting(colorScheme); else SyntaxHighlighting = null; EnsureSemanticTokensColorizerAttached(); Background = CreateEditorBrush(colorScheme.Background, "#202020"); - Foreground = CreateEditorBrush(colorScheme.Foreground, "White"); + Foreground = CreateEditorBrush(colorScheme.Foreground, "Gainsboro"); base.UpdateSettings(configuration); LiveErrorUnderlining = true; } + private static IHighlightingDefinition? LoadFallbackSyntaxHighlighting() + { + string fallbackDefinitionPath = Path.Combine( + AppContext.BaseDirectory, + "Configs", + "TextEditors", + "ColorSchemes", + "Lua", + "Default.xml"); + + if (!File.Exists(fallbackDefinitionPath)) + return null; + + using var stream = new FileStream(fallbackDefinitionPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + using var reader = new XmlTextReader(stream); + return HighlightingLoader.Load(reader, HighlightingManager.Instance); + } + private static SolidColorBrush CreateEditorBrush(string colorValue, string fallbackColorValue) { try { string effectiveColor = string.IsNullOrWhiteSpace(colorValue) ? fallbackColorValue : colorValue; - return new SolidColorBrush((Color)ColorConverter.ConvertFromString(effectiveColor)); + var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(effectiveColor)); + + if (brush.CanFreeze) + brush.Freeze(); + + return brush; } catch { - return new SolidColorBrush((Color)ColorConverter.ConvertFromString(fallbackColorValue)); + var fallbackBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(fallbackColorValue)); + + if (fallbackBrush.CanFreeze) + fallbackBrush.Freeze(); + + return fallbackBrush; } } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs index c81728fba0..b6ec533deb 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs @@ -7,11 +7,17 @@ namespace TombLib.Scripting.Lua.Objects { public sealed class ColorScheme : ColorSchemeBase { - public HighlightingObject Comments { get; set; } = new HighlightingObject(); - public HighlightingObject Values { get; set; } = new HighlightingObject(); - public HighlightingObject Statements { get; set; } = new HighlightingObject(); - public HighlightingObject Operators { get; set; } = new HighlightingObject(); - public HighlightingObject SpecialOperators { get; set; } = new HighlightingObject(); + public HighlightingObject Comments { get; set; } = CreateDefaultHighlighting("#6A9955"); + public HighlightingObject Values { get; set; } = CreateDefaultHighlighting("#569CD6"); + public HighlightingObject Statements { get; set; } = CreateDefaultHighlighting("#569CD6"); + public HighlightingObject Operators { get; set; } = CreateDefaultHighlighting("Gainsboro"); + public HighlightingObject SpecialOperators { get; set; } = CreateDefaultHighlighting("#569CD6"); + + public ColorScheme() + { + Background = "#202020"; + Foreground = "Gainsboro"; + } public static bool operator ==(ColorScheme? left, ColorScheme? right) => ReferenceEquals(left, right) || left is not null && left.Equals(right); @@ -45,5 +51,8 @@ public override int GetHashCode() hashCode.Add(Foreground ?? string.Empty, StringComparer.OrdinalIgnoreCase); return hashCode.ToHashCode(); } + + private static HighlightingObject CreateDefaultHighlighting(string htmlColor) + => new HighlightingObject { HtmlColor = htmlColor }; } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index d3b2fec0ac..2e2c33cdd3 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -10,7 +10,7 @@ using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using TombLib.Scripting.Rendering; -using static TombLib.WPF.BrushHelpers; +using TombLib.Scripting.Resources; namespace TombLib.Scripting.Lua.Objects { @@ -18,9 +18,9 @@ public sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged { private const double DescriptionMaxWidth = 540.0; private const double DescriptionTextMaxWidth = 500.0; - private static readonly SolidColorBrush DescriptionBorderBrush = CreateFrozenBrush(Color.FromRgb(96, 96, 96)); - private static readonly SolidColorBrush DescriptionBackgroundBrush = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); - private static readonly SolidColorBrush DescriptionForegroundBrush = CreateFrozenBrush(Colors.Gainsboro); + private static readonly SolidColorBrush DescriptionBorderBrush = TextEditorColorPalette.ToolTipBorder; + private static readonly SolidColorBrush DescriptionBackgroundBrush = TextEditorColorPalette.ToolTipBackground; + private static readonly SolidColorBrush DescriptionForegroundBrush = TextEditorColorPalette.ToolTipForeground; private readonly object _resolveSync = new object(); private LuaCompletionItem _item; private string? _displayDetail; diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs index 0db7465413..50134b151c 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -1,20 +1,12 @@ using System.Collections.Generic; using System.Windows.Media; -using static TombLib.WPF.BrushHelpers; +using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua.Objects { // Geometry paths below are vendored from microsoft/vscode-codicons under the MIT license. internal static class LuaCompletionIconFactory { - private static readonly Brush MiscBrush = CreateFrozenBrush("#C8C8C8"); - private static readonly Brush MethodBrush = CreateFrozenBrush("#DCDCAA"); - private static readonly Brush VariableBrush = CreateFrozenBrush("#9CDCFE"); - private static readonly Brush PropertyBrush = CreateFrozenBrush("#4FC1FF"); - private static readonly Brush TypeBrush = CreateFrozenBrush("#4EC9B0"); - private static readonly Brush KeywordBrush = CreateFrozenBrush("#C586C0"); - private static readonly Brush ConstantBrush = CreateFrozenBrush("#B5CEA8"); - private static readonly Brush FileBrush = CreateFrozenBrush("#D7BA7D"); private static readonly Dictionary Cache = new Dictionary(); public static ImageSource GetIcon(LuaCompletionIconKind kind) @@ -55,18 +47,18 @@ private static Brush GetBrush(LuaCompletionIconKind kind) { return kind switch { - LuaCompletionIconKind.Variable => VariableBrush, - LuaCompletionIconKind.Field => PropertyBrush, - LuaCompletionIconKind.Method => MethodBrush, - LuaCompletionIconKind.Property => PropertyBrush, - LuaCompletionIconKind.Class => TypeBrush, - LuaCompletionIconKind.Keyword => KeywordBrush, - LuaCompletionIconKind.Constant => ConstantBrush, - LuaCompletionIconKind.Parameter => VariableBrush, - LuaCompletionIconKind.Namespace => TypeBrush, - LuaCompletionIconKind.File => FileBrush, - LuaCompletionIconKind.Folder => FileBrush, - _ => MiscBrush + LuaCompletionIconKind.Variable => LuaEditorColorPalette.VariableBrush, + LuaCompletionIconKind.Field => LuaEditorColorPalette.PropertyBrush, + LuaCompletionIconKind.Method => LuaEditorColorPalette.MethodBrush, + LuaCompletionIconKind.Property => LuaEditorColorPalette.PropertyBrush, + LuaCompletionIconKind.Class => LuaEditorColorPalette.TypeBrush, + LuaCompletionIconKind.Keyword => LuaEditorColorPalette.KeywordBrush, + LuaCompletionIconKind.Constant => LuaEditorColorPalette.ConstantBrush, + LuaCompletionIconKind.Parameter => LuaEditorColorPalette.VariableBrush, + LuaCompletionIconKind.Namespace => LuaEditorColorPalette.TypeBrush, + LuaCompletionIconKind.File => LuaEditorColorPalette.FileBrush, + LuaCompletionIconKind.Folder => LuaEditorColorPalette.FileBrush, + _ => LuaEditorColorPalette.MiscBrush }; } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index cf22fe3a7e..484ffe51b6 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -15,7 +15,6 @@ public LuaCompletionItem( string? description = null, string? filterText = null, double priority = 0.0, - LuaCompletionItemKind kind = LuaCompletionItemKind.Text, LuaCompletionIconKind iconKind = LuaCompletionIconKind.Misc, bool isDescriptionMarkdown = false, Func>? resolveAsync = null) @@ -26,7 +25,6 @@ public LuaCompletionItem( Description = string.IsNullOrWhiteSpace(description) ? null : description.Trim(); FilterText = string.IsNullOrWhiteSpace(filterText) ? label : filterText; Priority = priority; - Kind = kind; IconKind = iconKind; IsDescriptionMarkdown = isDescriptionMarkdown; _resolveAsync = resolveAsync; @@ -38,7 +36,6 @@ public LuaCompletionItem( public string? Description { get; } public string FilterText { get; } public double Priority { get; } - public LuaCompletionItemKind Kind { get; } public LuaCompletionIconKind IconKind { get; } public bool IsDescriptionMarkdown { get; } public bool CanResolve => _resolveAsync is not null; diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs deleted file mode 100644 index cacd86e4b4..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItemKind.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace TombLib.Scripting.Lua.Objects -{ - public enum LuaCompletionItemKind - { - Text = 1, - Method = 2, - Function = 3, - Constructor = 4, - Field = 5, - Variable = 6, - Class = 7, - Interface = 8, - Module = 9, - Property = 10, - Unit = 11, - Value = 12, - Enum = 13, - Keyword = 14, - Snippet = 15, - Color = 16, - File = 17, - Reference = 18, - Folder = 19, - EnumMember = 20, - Constant = 21, - Struct = 22, - Event = 23, - Operator = 24, - TypeParameter = 25 - } -} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs index 55f81db78f..d813a2eeeb 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs @@ -3,13 +3,13 @@ using System.Windows.Data; using System.Windows.Media; using ICSharpCode.AvalonEdit.CodeCompletion; -using static TombLib.WPF.BrushHelpers; +using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua.Objects { internal static class LuaCompletionWindowStyle { - private static readonly Brush DetailBrush = CreateFrozenBrush("#8C8C8C"); + private static readonly Brush DetailBrush = LuaEditorColorPalette.MutedTextBrush; private static readonly DataTemplate ItemTemplate = CreateItemTemplate(); private static readonly Style ItemContainerStyle = CreateItemContainerStyle(); @@ -29,8 +29,6 @@ public static void Apply(CompletionWindow window) window.CompletionList.ListBox.FontSize = window.TextArea.FontSize; window.CompletionList.ListBox.ItemTemplate = ItemTemplate; window.CompletionList.ListBox.ItemContainerStyle = ItemContainerStyle; - window.Width = 420.0; - window.Height = 320.0; } private static DataTemplate CreateItemTemplate() @@ -52,7 +50,6 @@ private static DataTemplate CreateItemTemplate() detail.SetValue(DockPanel.DockProperty, Dock.Right); detail.SetValue(TextBlock.ForegroundProperty, DetailBrush); detail.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); - detail.SetValue(FrameworkElement.MaxWidthProperty, 220.0); detail.SetValue(FrameworkElement.MarginProperty, new Thickness(12.0, 0.0, 0.0, 0.0)); detail.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); detail.SetBinding(TextBlock.TextProperty, new Binding(nameof(LuaCompletionData.DisplayDetail))); diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs new file mode 100644 index 0000000000..a1bfc55206 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs @@ -0,0 +1,23 @@ +using System.Windows.Media; +using TombLib.Scripting.Resources; +using static TombLib.WPF.BrushHelpers; + +namespace TombLib.Scripting.Lua.Resources +{ + internal static class LuaEditorColorPalette + { + public static readonly Brush MutedTextBrush = CreateFrozenBrush("#8C8C8C"); + public static readonly Brush MiscBrush = CreateFrozenBrush("#C8C8C8"); + public static readonly Brush MethodBrush = CreateFrozenBrush("#DCDCAA"); + public static readonly Brush VariableBrush = CreateFrozenBrush("#9CDCFE"); + public static readonly Brush PropertyBrush = CreateFrozenBrush("#4FC1FF"); + public static readonly Brush TypeBrush = CreateFrozenBrush("#4EC9B0"); + public static readonly Brush KeywordBrush = CreateFrozenBrush("#C586C0"); + public static readonly Brush ConstantBrush = CreateFrozenBrush("#B5CEA8"); + public static readonly Brush FileBrush = CreateFrozenBrush("#D7BA7D"); + + public static readonly SolidColorBrush SignatureParamDocForeground = CreateFrozenBrush(Color.FromRgb(180, 180, 180)); + public static readonly SolidColorBrush SignatureActiveParamForeground = CreateFrozenBrush(Color.FromRgb(86, 180, 235)); + public static readonly SolidColorBrush SignatureForeground = TextEditorColorPalette.ToolTipForeground; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs b/TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs deleted file mode 100644 index 1cee590b50..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Services/TombEngineLanguageScriptService.cs +++ /dev/null @@ -1,133 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using ICSharpCode.AvalonEdit.Document; -using TombLib.Scripting.Lua.Utils; - -namespace TombLib.Scripting.Lua.Services; - -public sealed class TombEngineLanguageScriptService -{ - private static readonly Regex SetStringsRegex = new(@"TEN\.Flow\.SetStrings\s*\(\s*(?[^)\s]+)\s*\)", RegexOptions.IgnoreCase); - - public int? TryInsertLanguageScript(TextDocument document, string languageScript) - { - string? stringsVariableName = TryGetStringsVariableName(document); - - if (stringsVariableName is null) - return null; - - DocumentLine? stringsStartLine = FindStringsStartLine(document, stringsVariableName); - - if (stringsStartLine is null) - return null; - - DocumentLine? stopLine = FindStringsStopLine(document, stringsStartLine); - - if (stopLine is null) - return null; - - DocumentLine? insertionLine = FindLanguageInsertionLine(document, stringsStartLine, stopLine); - - if (insertionLine is not null) - return InsertLanguageScript(document, languageScript, insertionLine); - - return InsertLanguageScriptIntoEmptyTable(document, languageScript, stopLine); - } - - private static string? TryGetStringsVariableName(TextDocument document) - { - foreach (DocumentLine line in document.Lines) - { - string lineText = LuaLineParser.StripLineComment(document.GetText(line)); - Match match = SetStringsRegex.Match(lineText); - - if (match.Success) - return match.Groups["name"].Value; - } - - return null; - } - - private static DocumentLine? FindStringsStartLine(TextDocument document, string stringsVariableName) - { - var regex = new Regex(@"^\s*local\s+" + Regex.Escape(stringsVariableName) + @"\s*="); - - foreach (DocumentLine line in document.Lines) - { - if (regex.IsMatch(LuaLineParser.StripLineComment(document.GetText(line)))) - return line; - } - - return null; - } - - private static DocumentLine? FindStringsStopLine(TextDocument document, DocumentLine stringsStartLine) - { - int bracketDepth = 0; - bool foundOpeningBracket = false; - - for (DocumentLine? line = stringsStartLine; line is not null; line = line.NextLine) - { - string lineText = LuaLineParser.StripLineComment(document.GetText(line)); - - foreach (char character in LuaLineParser.EnumerateStructuralCharacters(lineText)) - { - if (character == '{') - { - bracketDepth++; - foundOpeningBracket = true; - } - else if (character == '}') - { - if (!foundOpeningBracket || bracketDepth == 0) - return null; - - bracketDepth--; - - if (bracketDepth == 0) - return line; - } - } - } - - return null; - } - - private static DocumentLine? FindLanguageInsertionLine(TextDocument document, DocumentLine stringsStartLine, DocumentLine stopLine) - { - for (int i = stopLine.LineNumber - 1; i > stringsStartLine.LineNumber; i--) - { - DocumentLine line = document.GetLineByNumber(i); - string cleanLine = LuaLineParser.StripLineComment(document.GetText(line)).TrimEnd(); - - if (cleanLine.EndsWith("}") || cleanLine.EndsWith("},")) - return line; - } - - return null; - } - - private static int InsertLanguageScript(TextDocument document, string languageScript, DocumentLine insertionLine) - { - string rawLine = document.GetText(insertionLine); - string cleanLine = LuaLineParser.StripLineComment(rawLine).TrimEnd(); - - if (cleanLine.EndsWith("}")) - { - int commaOffset = insertionLine.Offset + cleanLine.Length; - document.Insert(commaOffset, ","); - } - - document.Insert(insertionLine.EndOffset, Environment.NewLine + languageScript); - return insertionLine.LineNumber + 1; - } - - private static int InsertLanguageScriptIntoEmptyTable(TextDocument document, string languageScript, DocumentLine stopLine) - { - document.Insert(stopLine.Offset, languageScript + Environment.NewLine); - return stopLine.LineNumber; - } -} diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index 3e4178502f..9a9086cc57 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -43,6 +43,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs index a9ac74b990..de0cff9bb3 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -26,7 +26,7 @@ public static bool IsValidAutocompleteContext(TextDocument? document, int offset char typedCharacter = document.GetCharAt(offset - 1); - if (!IsIdentifierCharacter(typedCharacter)) + if (!LuaLineParser.IsIdentifierCharacter(typedCharacter)) return false; if (offset >= 2 && document.GetCharAt(offset - 2) == '.') @@ -93,28 +93,25 @@ private static bool TryGetDefinitionWordBounds(TextDocument document, int offset probeOffset = document.TextLength - 1; if (probeOffset > 0 - && !IsIdentifierCharacter(document.GetCharAt(probeOffset)) - && IsIdentifierCharacter(document.GetCharAt(probeOffset - 1))) + && !LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset)) + && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset - 1))) { probeOffset--; } - if (!IsIdentifierCharacter(document.GetCharAt(probeOffset))) + if (!LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset))) return false; wordStart = probeOffset; wordEnd = probeOffset + 1; - while (wordStart > 0 && IsIdentifierCharacter(document.GetCharAt(wordStart - 1))) + while (wordStart > 0 && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(wordStart - 1))) wordStart--; - while (wordEnd < document.TextLength && IsIdentifierCharacter(document.GetCharAt(wordEnd))) + while (wordEnd < document.TextLength && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(wordEnd))) wordEnd++; return wordEnd > wordStart; } - - private static bool IsIdentifierCharacter(char character) - => char.IsLetterOrDigit(character) || character == '_'; } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs index 809f7b4352..8e200961ff 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -5,41 +5,96 @@ namespace TombLib.Scripting.Lua.Utils { internal static class LuaLineParser { + private enum ParserState + { + None, + SingleQuotedString, + DoubleQuotedString, + LongString, + LongComment + } + + public static bool IsIdentifierCharacter(char character) + => char.IsLetterOrDigit(character) || character == '_'; + + public static bool IsIdentifierTriggerCharacter(char character) + => char.IsLetter(character) || character == '_'; + public static bool IsInsideCommentOrString(string lineText) { if (string.IsNullOrEmpty(lineText)) return false; - bool isInsideSingleQuotedString = false; - bool isInsideDoubleQuotedString = false; - bool isEscaped = false; + ParserState state = ParserState.None; + int longBracketEqualsCount = 0; for (int i = 0; i < lineText.Length; i++) { char currentChar = lineText[i]; - if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && IsLineCommentStart(lineText, i)) - return true; + if (state == ParserState.LongString || state == ParserState.LongComment) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) + { + i += endTokenLength - 1; + state = ParserState.None; + } + + continue; + } + + if (state == ParserState.SingleQuotedString) + { + if (currentChar == '\\' && i + 1 < lineText.Length) + { + i++; + continue; + } - if (isEscaped) + if (currentChar == '\'') + state = ParserState.None; + + continue; + } + + if (state == ParserState.DoubleQuotedString) + { + if (currentChar == '\\' && i + 1 < lineText.Length) + { + i++; + continue; + } + + if (currentChar == '"') + state = ParserState.None; + + continue; + } + + if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) { - isEscaped = false; + state = ParserState.LongComment; + i += longCommentStartLength - 1; continue; } - if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\' && i + 1 < lineText.Length) + if (IsLineCommentStart(lineText, i)) + return true; + + if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) { - isEscaped = true; + state = ParserState.LongString; + i += longStringStartLength - 1; continue; } - if (!isInsideDoubleQuotedString && currentChar == '\'') - isInsideSingleQuotedString = !isInsideSingleQuotedString; - else if (!isInsideSingleQuotedString && currentChar == '"') - isInsideDoubleQuotedString = !isInsideDoubleQuotedString; + if (currentChar == '\'') + state = ParserState.SingleQuotedString; + else if (currentChar == '"') + state = ParserState.DoubleQuotedString; } - return isInsideSingleQuotedString || isInsideDoubleQuotedString; + return state != ParserState.None; } public static string StripLineComment(string lineText) @@ -48,28 +103,80 @@ public static string StripLineComment(string lineText) return string.Empty; var builder = new StringBuilder(lineText.Length); - bool isInsideSingleQuotedString = false; - bool isInsideDoubleQuotedString = false; + ParserState state = ParserState.None; + int longBracketEqualsCount = 0; for (int i = 0; i < lineText.Length; i++) { char currentChar = lineText[i]; - if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && IsLineCommentStart(lineText, i)) - break; + if (state == ParserState.LongComment) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) + { + i += endTokenLength - 1; + state = ParserState.None; + } + + continue; + } + + if (state == ParserState.LongString) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) + { + builder.Append(lineText, i, endTokenLength); + i += endTokenLength - 1; + state = ParserState.None; + } + else + builder.Append(currentChar); + + continue; + } - if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\' && i + 1 < lineText.Length) + if (state == ParserState.SingleQuotedString || state == ParserState.DoubleQuotedString) { builder.Append(currentChar); - builder.Append(lineText[i + 1]); - i++; + + if (currentChar == '\\' && i + 1 < lineText.Length) + { + builder.Append(lineText[i + 1]); + i++; + continue; + } + + if ((state == ParserState.SingleQuotedString && currentChar == '\'') + || (state == ParserState.DoubleQuotedString && currentChar == '"')) + { + state = ParserState.None; + } + + continue; + } + + if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + { + state = ParserState.LongComment; + i += longCommentStartLength - 1; + continue; + } + + if (IsLineCommentStart(lineText, i)) + break; + + if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) + { + builder.Append(lineText, i, longStringStartLength); + state = ParserState.LongString; + i += longStringStartLength - 1; continue; } - if (!isInsideDoubleQuotedString && currentChar == '\'') - isInsideSingleQuotedString = !isInsideSingleQuotedString; - else if (!isInsideSingleQuotedString && currentChar == '"') - isInsideDoubleQuotedString = !isInsideDoubleQuotedString; + if (currentChar == '\'') + state = ParserState.SingleQuotedString; + else if (currentChar == '"') + state = ParserState.DoubleQuotedString; builder.Append(currentChar); } @@ -82,39 +189,132 @@ public static IEnumerable EnumerateStructuralCharacters(string lineText) if (string.IsNullOrEmpty(lineText)) yield break; - bool isInsideSingleQuotedString = false; - bool isInsideDoubleQuotedString = false; + ParserState state = ParserState.None; + int longBracketEqualsCount = 0; for (int i = 0; i < lineText.Length; i++) { char currentChar = lineText[i]; - if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString && IsLineCommentStart(lineText, i)) + if (state == ParserState.LongComment || state == ParserState.LongString) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) + { + i += endTokenLength - 1; + state = ParserState.None; + } + + continue; + } + + if (state == ParserState.SingleQuotedString || state == ParserState.DoubleQuotedString) + { + if (currentChar == '\\' && i + 1 < lineText.Length) + i++; + else if ((state == ParserState.SingleQuotedString && currentChar == '\'') + || (state == ParserState.DoubleQuotedString && currentChar == '"')) + { + state = ParserState.None; + } + + continue; + } + + if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + { + state = ParserState.LongComment; + i += longCommentStartLength - 1; + continue; + } + + if (IsLineCommentStart(lineText, i)) yield break; - if ((isInsideSingleQuotedString || isInsideDoubleQuotedString) && currentChar == '\\' && i + 1 < lineText.Length) + if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) { - i++; + state = ParserState.LongString; + i += longStringStartLength - 1; continue; } - if (!isInsideDoubleQuotedString && currentChar == '\'') + if (currentChar == '\'') { - isInsideSingleQuotedString = !isInsideSingleQuotedString; + state = ParserState.SingleQuotedString; continue; } - if (!isInsideSingleQuotedString && currentChar == '"') + if (currentChar == '"') { - isInsideDoubleQuotedString = !isInsideDoubleQuotedString; + state = ParserState.DoubleQuotedString; continue; } - if (!isInsideSingleQuotedString && !isInsideDoubleQuotedString) - yield return currentChar; + yield return currentChar; } } + private static bool TryMatchLongCommentStart(string lineText, int index, out int equalsCount, out int tokenLength) + { + equalsCount = 0; + tokenLength = 0; + + if (!IsLineCommentStart(lineText, index) || !TryMatchLongBracketStart(lineText, index + 2, out equalsCount, out int bracketTokenLength)) + return false; + + tokenLength = 2 + bracketTokenLength; + return true; + } + + private static bool TryMatchLongBracketStart(string lineText, int index, out int equalsCount, out int tokenLength) + { + equalsCount = 0; + tokenLength = 0; + + if (index >= lineText.Length || lineText[index] != '[') + return false; + + int probeIndex = index + 1; + + while (probeIndex < lineText.Length && lineText[probeIndex] == '=') + { + equalsCount++; + probeIndex++; + } + + if (probeIndex >= lineText.Length || lineText[probeIndex] != '[') + { + equalsCount = 0; + return false; + } + + tokenLength = probeIndex - index + 1; + return true; + } + + private static bool TryMatchLongBracketEnd(string lineText, int index, int equalsCount, out int tokenLength) + { + tokenLength = 0; + + if (index >= lineText.Length || lineText[index] != ']') + return false; + + int probeIndex = index + 1; + + for (int i = 0; i < equalsCount; i++) + { + if (probeIndex >= lineText.Length || lineText[probeIndex] != '=') + return false; + + probeIndex++; + } + + if (probeIndex >= lineText.Length || lineText[probeIndex] != ']') + return false; + + tokenLength = probeIndex - index + 1; + return true; + } + private static bool IsLineCommentStart(string lineText, int index) => lineText[index] == '-' && index + 1 < lineText.Length && lineText[index + 1] == '-'; } diff --git a/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs new file mode 100644 index 0000000000..2f5e1a2d3a --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs @@ -0,0 +1,135 @@ +using System; +using System.Text.RegularExpressions; +using ICSharpCode.AvalonEdit.Document; + +namespace TombLib.Scripting.Lua.Utils +{ + public sealed class TombEngineLanguageScriptService + { + private static readonly Regex SetStringsRegex = new( + @"TEN\.Flow\.SetStrings\s*\(\s*(?[^)\s]+)\s*\)", + RegexOptions.Compiled | RegexOptions.IgnoreCase); + + public int? TryInsertLanguageScript(TextDocument document, string languageScript) + { + string? stringsVariableName = TryGetStringsVariableName(document); + + if (stringsVariableName is null) + return null; + + DocumentLine? stringsStartLine = FindStringsStartLine(document, stringsVariableName); + + if (stringsStartLine is null) + return null; + + DocumentLine? stopLine = FindStringsStopLine(document, stringsStartLine); + + if (stopLine is null) + return null; + + DocumentLine? insertionLine = FindLanguageInsertionLine(document, stringsStartLine, stopLine); + + if (insertionLine is not null) + return InsertLanguageScript(document, languageScript, insertionLine); + + return InsertLanguageScriptIntoEmptyTable(document, languageScript, stopLine); + } + + private static string? TryGetStringsVariableName(TextDocument document) + { + foreach (DocumentLine line in document.Lines) + { + string lineText = LuaLineParser.StripLineComment(document.GetText(line)); + Match match = SetStringsRegex.Match(lineText); + + if (match.Success) + return match.Groups["name"].Value; + } + + return null; + } + + private static DocumentLine? FindStringsStartLine(TextDocument document, string stringsVariableName) + { + Regex regex = CreateStringsStartRegex(stringsVariableName); + + foreach (DocumentLine line in document.Lines) + { + if (regex.IsMatch(LuaLineParser.StripLineComment(document.GetText(line)))) + return line; + } + + return null; + } + + private static Regex CreateStringsStartRegex(string stringsVariableName) + => new(@"^\s*local\s+" + Regex.Escape(stringsVariableName) + @"\s*=", RegexOptions.Compiled); + + private static DocumentLine? FindStringsStopLine(TextDocument document, DocumentLine stringsStartLine) + { + int bracketDepth = 0; + bool foundOpeningBracket = false; + + for (DocumentLine? line = stringsStartLine; line is not null; line = line.NextLine) + { + string lineText = LuaLineParser.StripLineComment(document.GetText(line)); + + foreach (char character in LuaLineParser.EnumerateStructuralCharacters(lineText)) + { + if (character == '{') + { + bracketDepth++; + foundOpeningBracket = true; + } + else if (character == '}') + { + if (!foundOpeningBracket || bracketDepth == 0) + return null; + + bracketDepth--; + + if (bracketDepth == 0) + return line; + } + } + } + + return null; + } + + private static DocumentLine? FindLanguageInsertionLine(TextDocument document, DocumentLine stringsStartLine, DocumentLine stopLine) + { + for (int i = stopLine.LineNumber - 1; i > stringsStartLine.LineNumber; i--) + { + DocumentLine line = document.GetLineByNumber(i); + string cleanLine = LuaLineParser.StripLineComment(document.GetText(line)).TrimEnd(); + + if (cleanLine.EndsWith("}") || cleanLine.EndsWith("},")) + return line; + } + + return null; + } + + private static int InsertLanguageScript(TextDocument document, string languageScript, DocumentLine insertionLine) + { + string rawLine = document.GetText(insertionLine); + string cleanLine = LuaLineParser.StripLineComment(rawLine).TrimEnd(); + + if (cleanLine.EndsWith("}")) + { + int commaOffset = insertionLine.Offset + cleanLine.Length; + document.Insert(commaOffset, ","); + } + + document.Insert(insertionLine.EndOffset, Environment.NewLine + languageScript); + return insertionLine.LineNumber + 1; + } + + private static int InsertLanguageScriptIntoEmptyTable(TextDocument document, string languageScript, DocumentLine stopLine) + { + document.Insert(stopLine.Offset, languageScript + Environment.NewLine); + return stopLine.LineNumber; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 06b01d459a..1684ee67b4 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -33,17 +33,17 @@ public abstract class TextEditorBase : TextEditor, IEditorControl, ISupportsFind private const double ToolTipMaxWidth = 540.0; protected const double ToolTipTextMaxWidth = 500.0; protected static readonly double ToolTipTextFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); - protected static readonly SolidColorBrush DefaultToolTipBorder = CreateFrozenBrush(Color.FromRgb(96, 96, 96)); - protected static readonly SolidColorBrush DefaultToolTipBackground = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); - private static readonly SolidColorBrush ErrorToolTipBorder = CreateFrozenBrush(Color.FromRgb(128, 86, 86)); - private static readonly SolidColorBrush ErrorToolTipBackground = CreateFrozenBrush(Color.FromRgb(78, 44, 44)); - private static readonly SolidColorBrush WarningToolTipBorder = CreateFrozenBrush(Color.FromRgb(145, 122, 62)); - private static readonly SolidColorBrush WarningToolTipBackground = CreateFrozenBrush(Color.FromRgb(86, 69, 30)); - private static readonly SolidColorBrush InformationToolTipBorder = CreateFrozenBrush(Color.FromRgb(80, 118, 168)); - private static readonly SolidColorBrush InformationToolTipBackground = CreateFrozenBrush(Color.FromRgb(46, 68, 104)); - private static readonly SolidColorBrush HintToolTipBorder = CreateFrozenBrush(Color.FromRgb(108, 108, 108)); - private static readonly SolidColorBrush HintToolTipBackground = CreateFrozenBrush(Color.FromRgb(58, 58, 58)); - protected static readonly SolidColorBrush ToolTipForeground = CreateFrozenBrush(Colors.Gainsboro); + protected static readonly SolidColorBrush DefaultToolTipBorder = TextEditorColorPalette.ToolTipBorder; + protected static readonly SolidColorBrush DefaultToolTipBackground = TextEditorColorPalette.ToolTipBackground; + private static readonly SolidColorBrush ErrorToolTipBorder = TextEditorColorPalette.ErrorToolTipBorder; + private static readonly SolidColorBrush ErrorToolTipBackground = TextEditorColorPalette.ErrorToolTipBackground; + private static readonly SolidColorBrush WarningToolTipBorder = TextEditorColorPalette.WarningToolTipBorder; + private static readonly SolidColorBrush WarningToolTipBackground = TextEditorColorPalette.WarningToolTipBackground; + private static readonly SolidColorBrush InformationToolTipBorder = TextEditorColorPalette.InformationToolTipBorder; + private static readonly SolidColorBrush InformationToolTipBackground = TextEditorColorPalette.InformationToolTipBackground; + private static readonly SolidColorBrush HintToolTipBorder = TextEditorColorPalette.HintToolTipBorder; + private static readonly SolidColorBrush HintToolTipBackground = TextEditorColorPalette.HintToolTipBackground; + protected static readonly SolidColorBrush ToolTipForeground = TextEditorColorPalette.ToolTipForeground; public EditorType EditorType => EditorType.Text; public abstract string DefaultFileExtension { get; } diff --git a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs index 2d26e90be6..3d74755fec 100644 --- a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs @@ -35,8 +35,8 @@ public static class MarkdownToolTipRenderer private static readonly FontFamily CodeFontFamily = new FontFamily(TextEditorBaseDefaults.FontFamily); private static readonly double BodyFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); private static readonly double CodeFontSize = Math.Max(BodyFontSize - 1.0, 13.0); - private static readonly Brush DefaultForeground = CreateFrozenBrush(Colors.Gainsboro); - private static readonly Brush DefaultBackground = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); + private static readonly Brush DefaultForeground = TextEditorColorPalette.ToolTipForeground; + private static readonly Brush DefaultBackground = TextEditorColorPalette.ToolTipBackground; private static readonly Brush DefaultLinkForeground = CreateFrozenBrush(Color.FromRgb(112, 192, 231)); private static readonly HashSet SupportedHyperlinkSchemes = new HashSet(StringComparer.OrdinalIgnoreCase) { diff --git a/TombLib/TombLib.Scripting/Resources/TextEditorColorPalette.cs b/TombLib/TombLib.Scripting/Resources/TextEditorColorPalette.cs new file mode 100644 index 0000000000..b526c0e092 --- /dev/null +++ b/TombLib/TombLib.Scripting/Resources/TextEditorColorPalette.cs @@ -0,0 +1,21 @@ +using System.Windows.Media; +using static TombLib.WPF.BrushHelpers; + +namespace TombLib.Scripting.Resources +{ + public static class TextEditorColorPalette + { + public static readonly SolidColorBrush ToolTipBorder = CreateFrozenBrush(Color.FromRgb(96, 96, 96)); + public static readonly SolidColorBrush ToolTipBackground = CreateFrozenBrush(Color.FromRgb(64, 64, 64)); + public static readonly SolidColorBrush ToolTipForeground = CreateFrozenBrush(Colors.Gainsboro); + + public static readonly SolidColorBrush ErrorToolTipBorder = CreateFrozenBrush(Color.FromRgb(128, 86, 86)); + public static readonly SolidColorBrush ErrorToolTipBackground = CreateFrozenBrush(Color.FromRgb(78, 44, 44)); + public static readonly SolidColorBrush WarningToolTipBorder = CreateFrozenBrush(Color.FromRgb(145, 122, 62)); + public static readonly SolidColorBrush WarningToolTipBackground = CreateFrozenBrush(Color.FromRgb(86, 69, 30)); + public static readonly SolidColorBrush InformationToolTipBorder = CreateFrozenBrush(Color.FromRgb(80, 118, 168)); + public static readonly SolidColorBrush InformationToolTipBackground = CreateFrozenBrush(Color.FromRgb(46, 68, 104)); + public static readonly SolidColorBrush HintToolTipBorder = CreateFrozenBrush(Color.FromRgb(108, 108, 108)); + public static readonly SolidColorBrush HintToolTipBackground = CreateFrozenBrush(Color.FromRgb(58, 58, 58)); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaColorSchemeTests.cs b/TombLib/TombLib.Test/LuaColorSchemeTests.cs new file mode 100644 index 0000000000..f8757b255b --- /dev/null +++ b/TombLib/TombLib.Test/LuaColorSchemeTests.cs @@ -0,0 +1,21 @@ +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaColorSchemeTests +{ + [TestMethod] + public void DefaultColorScheme_UsesLuaEditorDefaults() + { + var scheme = new ColorScheme(); + + Assert.AreEqual("#202020", scheme.Background); + Assert.AreEqual("Gainsboro", scheme.Foreground); + Assert.AreEqual("#6A9955", scheme.Comments.HtmlColor); + Assert.AreEqual("#569CD6", scheme.Values.HtmlColor); + Assert.AreEqual("#569CD6", scheme.Statements.HtmlColor); + Assert.AreEqual("Gainsboro", scheme.Operators.HtmlColor); + Assert.AreEqual("#569CD6", scheme.SpecialOperators.HtmlColor); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs index 7040152f51..2c55412dd9 100644 --- a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs +++ b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs @@ -47,6 +47,26 @@ public void IsValidManualCompletionContext_BlocksOpenString() Assert.IsFalse(result); } + [TestMethod] + public void IsValidManualCompletionContext_BlocksOpenLongComment() + { + var document = CreateDocument("--[[ player"); + + bool result = LuaEditorInteractionRules.IsValidManualCompletionContext(document, document.TextLength); + + Assert.IsFalse(result); + } + + [TestMethod] + public void IsValidManualCompletionContext_BlocksOpenLongString() + { + var document = CreateDocument("value = [[player"); + + bool result = LuaEditorInteractionRules.IsValidManualCompletionContext(document, document.TextLength); + + Assert.IsFalse(result); + } + [TestMethod] public void CanRequestHover_ReturnsFalseWhenCompletionWindowIsOpen() { diff --git a/TombLib/TombLib.Test/LuaLineParserTests.cs b/TombLib/TombLib.Test/LuaLineParserTests.cs new file mode 100644 index 0000000000..c54df9f9af --- /dev/null +++ b/TombLib/TombLib.Test/LuaLineParserTests.cs @@ -0,0 +1,40 @@ +using System.Linq; +using TombLib.Scripting.Lua.Utils; + +namespace TombLib.Test; + +[TestClass] +public class LuaLineParserTests +{ + [TestMethod] + public void IsInsideCommentOrString_ReturnsTrueInsideLongComment() + { + bool result = LuaLineParser.IsInsideCommentOrString("--[[ comment"); + + Assert.IsTrue(result); + } + + [TestMethod] + public void IsInsideCommentOrString_ReturnsTrueInsideLongString() + { + bool result = LuaLineParser.IsInsideCommentOrString("value = [[comment"); + + Assert.IsTrue(result); + } + + [TestMethod] + public void StripLineComment_RemovesInlineLongCommentAndKeepsCodeAfterIt() + { + string result = LuaLineParser.StripLineComment("value = 1 --[[ remove this ]] + 2"); + + Assert.AreEqual("value = 1 + 2", result); + } + + [TestMethod] + public void EnumerateStructuralCharacters_SkipsLongStringContents() + { + string result = new string(LuaLineParser.EnumerateStructuralCharacters("{ [[ignored } text]] }").ToArray()); + + Assert.AreEqual("{ }", result); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs b/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs index 7ddb7da73f..f11e0e0914 100644 --- a/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs +++ b/TombLib/TombLib.Test/TombEngineLanguageScriptServiceTests.cs @@ -1,5 +1,5 @@ using ICSharpCode.AvalonEdit.Document; -using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Lua.Utils; namespace TombLib.Test; @@ -91,6 +91,23 @@ public void TryInsertLanguageScript_IgnoresEscapedQuotesAndCommentMarkersInsideS StringAssert.Contains(document.Text, "newLevel = { \"New Level\" }"); } + [TestMethod] + public void TryInsertLanguageScript_IgnoresBracesInsideLongStrings() + { + var document = CreateDocument( + "local strings = {", + " existing = { [[A } brace inside a long string]] }", + "}", + string.Empty, + "TEN.Flow.SetStrings(strings)"); + + int? insertedLineNumber = _service.TryInsertLanguageScript(document, " newLevel = { \"New Level\" }"); + + Assert.AreEqual(3, insertedLineNumber); + StringAssert.Contains(document.Text, "existing = { [[A } brace inside a long string]] },"); + StringAssert.Contains(document.Text, "newLevel = { \"New Level\" }"); + } + [TestMethod] public void TryInsertLanguageScript_ReturnsNullWhenStringsTableIsMissing() { From ee5e2755c595da0fe9f666f440e5c80aaefaf686 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 14:26:21 +0100 Subject: [PATCH 07/34] Add "Tomorrow Night" theme --- GlobalPaths.cs | 3 +- .../Settings/FormSaveSchemeAs.cs | 14 +- .../Settings/LuaSettingsControl.cs | 417 ++++++------------ .../TextEditors/ColorSchemes/Lua/Default.xml | 149 ------- .../TextEditors/ColorSchemes/Lua/VS15.luasch | 30 -- .../TextEditors/Themes/Lua/Monokai.json | 32 ++ .../TextEditors/Themes/Lua/NG_CENTER.json | 33 ++ .../TextEditors/Themes/Lua/Obsidian.json | 32 ++ .../TextEditors/Themes/Lua/TomorrowNight.json | 34 ++ .../Themes/Lua/VSCodeDarkPlus.json | 33 ++ .../Themes/Lua/VSCodeLightPlus.json | 33 ++ .../Themes/Lua/VisualStudio15.json | 33 ++ .../LuaSemanticTokensColorizer.cs | 61 +-- .../LuaEditor.Completion.cs | 5 +- .../LuaEditor.SemanticHighlighting.cs | 4 +- .../LuaEditor.SignatureHelp.cs | 17 +- TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 60 +-- .../LuaEditorConfiguration.cs | 39 +- .../Objects/ColorScheme.cs | 58 --- .../Objects/LuaCompletionData.cs | 9 +- .../Objects/LuaCompletionIconFactory.cs | 35 +- .../Objects/LuaCompletionWindowStyle.cs | 10 +- .../TombLib.Scripting.Lua/Objects/LuaTheme.cs | 74 ++++ .../Objects/SyntaxHighlighting.cs | 71 --- .../Resources/ConfigurationDefaults.cs | 3 +- .../Resources/LuaEditorColorPalette.cs | 127 +++++- .../Resources/LuaThemeRepository.cs | 142 ++++++ .../TombLib.Scripting.Lua.csproj | 5 +- .../LuaTextMateSyntaxHighlighting.cs | 46 +- .../TextMateThemeStyleResolver.cs | 260 +++++++++-- .../Highlighting/TextMateTokenTheme.cs | 16 + TombLib/TombLib.Test/LuaColorSchemeTests.cs | 21 - .../LuaThemeConfigurationTests.cs | 57 +++ 33 files changed, 1121 insertions(+), 842 deletions(-) delete mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml delete mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json delete mode 100644 TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs create mode 100644 TombLib/TombLib.Scripting/Highlighting/TextMateTokenTheme.cs delete mode 100644 TombLib/TombLib.Test/LuaColorSchemeTests.cs create mode 100644 TombLib/TombLib.Test/LuaThemeConfigurationTests.cs diff --git a/GlobalPaths.cs b/GlobalPaths.cs index 06f8f9ecfe..d6dd83a5bf 100644 --- a/GlobalPaths.cs +++ b/GlobalPaths.cs @@ -16,10 +16,11 @@ internal static class DefaultPaths public static string ConfigsDirectory => Path.Combine(ProgramDirectory, "Configs"); public static string GeometryIOConfigsDirectory => Path.Combine(ConfigsDirectory, "GeometryIO"); public static string TextEditorConfigsDirectory => Path.Combine(ConfigsDirectory, "TextEditors"); + public static string TextEditorThemesDirectory => Path.Combine(TextEditorConfigsDirectory, "Themes"); public static string ColorSchemesDirectory => Path.Combine(TextEditorConfigsDirectory, "ColorSchemes"); public static string ClassicScriptColorConfigsDirectory => Path.Combine(ColorSchemesDirectory, "ClassicScript"); - public static string LuaColorConfigsDirectory => Path.Combine(ColorSchemesDirectory, "Lua"); + public static string LuaThemeConfigsDirectory => Path.Combine(TextEditorThemesDirectory, "Lua"); public static string GameFlowColorConfigsDirectory => Path.Combine(ColorSchemesDirectory, "GameFlowScript"); public static string T1MColorConfigsDirectory => Path.Combine(ColorSchemesDirectory, "Tomb1Main"); diff --git a/TombIDE/TombIDE.ScriptingStudio/Settings/FormSaveSchemeAs.cs b/TombIDE/TombIDE.ScriptingStudio/Settings/FormSaveSchemeAs.cs index 5df6860f2a..90379cead1 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Settings/FormSaveSchemeAs.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Settings/FormSaveSchemeAs.cs @@ -9,8 +9,7 @@ namespace TombIDE.ScriptingStudio.Settings internal enum ColorSchemeType { ClassicScript, - GameFlowScript, - Lua + GameFlowScript } internal partial class FormSaveSchemeAs : DarkForm @@ -77,17 +76,6 @@ private void button_Save_Click(object sender, EventArgs e) schemeFilePath = Path.Combine(schemeFolderPath, newName + ".gflsch"); break; } - case ColorSchemeType.Lua: - { - string schemeFolderPath = DefaultPaths.LuaColorConfigsDirectory; - - foreach (string file in Directory.GetFiles(schemeFolderPath, "*.luasch", SearchOption.TopDirectoryOnly)) - if (Path.GetFileNameWithoutExtension(file).Equals(newName, StringComparison.OrdinalIgnoreCase)) - throw new ArgumentException("A scheme with the same name already exists."); - - schemeFilePath = Path.Combine(schemeFolderPath, newName + ".luasch"); - break; - } } // // // // diff --git a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs index cdf9018612..e7ebaf2a9f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs @@ -1,25 +1,33 @@ using DarkUI.Controls; -using DarkUI.Forms; using System; using System.Collections.Generic; using System.ComponentModel; -using System.Diagnostics; using System.Drawing; using System.Drawing.Text; -using System.IO; using System.Windows; using System.Windows.Forms; using TombLib.Scripting.Lua; using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Resources; using TombLib.Scripting.Objects; using TombLib.Scripting.Resources; -using TombLib.Utils; namespace TombIDE.ScriptingStudio.Settings { internal partial class LuaSettingsControl : UserControl { - // TODO: Refactor !!! + private const string PreviewText = + "---@class Weapon\n" + + "local Weapon = {}\n" + + "global levelName = \"Lara\"\n\n" + + "function Weapon:new(name)\n" + + " local damage = math.max(levelName and 1 or 0, 1)\n" + + " self.name = name\n" + + " return damage\n" + + "end"; + + private static readonly string[] PreviewLines = PreviewText.Replace("\r", string.Empty).Split('\n'); + private static readonly IReadOnlyList PreviewTokens = CreatePreviewTokens(); private LuaEditor editorPreview; @@ -33,37 +41,69 @@ public LuaSettingsControl() public void Initialize(LuaEditorConfiguration config) { InitializePreview(); - FillFontList(); - UpdateSchemeList(); + ConfigureThemePresetUi(); + UpdateThemeList(); UpdateControlsWithSettings(config); + UpdatePreview(); } private void InitializePreview() { editorPreview = new LuaEditor(new Version(0, 0)) { - Text = - "if _G[k] then\n" + - " print(\"WARNING! Key \"..k..\" already exists in global environment!\")\n" + - "else\n" + - " _G[k] = v\n" + - " if \"table\" == type(v) then\n" + - " if nil == v.__type then\n" + - " ShortenInner(v)\n" + - " end\n" + - " end\n" + - "end", + Text = PreviewText, IsReadOnly = true, HorizontalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Hidden, VerticalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Hidden }; editorPreview.TextArea.Margin = new Thickness(3); - elementHost.Child = editorPreview; } + private void ConfigureThemePresetUi() + { + int previewBottom = groupBox_Preview.Bottom; + + groupBox_Colors.Enabled = true; + groupBox_Colors.Text = "Theme"; + darkLabel4.Text = "Preset:"; + darkLabel4.Location = new System.Drawing.Point(12, 23); + comboBox_ColorSchemes.DropDownStyle = ComboBoxStyle.DropDownList; + comboBox_ColorSchemes.Location = new System.Drawing.Point(12, 42); + comboBox_ColorSchemes.Width = groupBox_Colors.ClientSize.Width - 24; + groupBox_Colors.Height = 77; + + Control[] hiddenControls = + { + button_ImportScheme, + button_SaveScheme, + button_DeleteScheme, + button_OpenSchemesFolder, + colorButton_Background, + colorButton_Foreground, + colorButton_Comments, + colorButton_SpecialOperators, + colorButton_Values, + colorButton_Statements, + colorButton_Operators, + darkLabel5, + darkLabel6, + darkLabel7, + darkLabel8, + darkLabel10, + darkLabel11, + darkLabel12 + }; + + for (int i = 0; i < hiddenControls.Length; i++) + hiddenControls[i].Visible = false; + + groupBox_Preview.Top = groupBox_Colors.Bottom + 9; + groupBox_Preview.Height = previewBottom - groupBox_Preview.Top; + } + private void FillFontList() { var fontList = new List(); @@ -74,127 +114,62 @@ private void FillFontList() comboBox_FontFamily.Items.AddRange(fontList.ToArray()); } - private void UpdateSchemeList() + private void UpdateThemeList() { - string cachedSelectedItem = null; - - if (comboBox_ColorSchemes.SelectedItem != null) - cachedSelectedItem = comboBox_ColorSchemes.SelectedItem.ToString(); + string cachedSelectedItem = comboBox_ColorSchemes.SelectedItem?.ToString(); comboBox_ColorSchemes.Items.Clear(); - foreach (string file in Directory.GetFiles(DefaultPaths.LuaColorConfigsDirectory, "*.luasch", SearchOption.TopDirectoryOnly)) - comboBox_ColorSchemes.Items.Add(Path.GetFileNameWithoutExtension(file)); + foreach (LuaTheme theme in LuaThemeRepository.GetAvailableThemes()) + comboBox_ColorSchemes.Items.Add(theme.Name); - if (cachedSelectedItem != null) + if (!string.IsNullOrWhiteSpace(cachedSelectedItem) && comboBox_ColorSchemes.Items.Contains(cachedSelectedItem)) comboBox_ColorSchemes.SelectedItem = cachedSelectedItem; + else if (comboBox_ColorSchemes.Items.Contains(ConfigurationDefaults.SelectedThemeName)) + comboBox_ColorSchemes.SelectedItem = ConfigurationDefaults.SelectedThemeName; + else if (comboBox_ColorSchemes.Items.Count > 0) + comboBox_ColorSchemes.SelectedIndex = 0; } #endregion Construction #region Events - private void VisiblePreviewSetting_Changed(object sender, EventArgs e) => - UpdatePreviewTemp(); + private void VisiblePreviewSetting_Changed(object sender, EventArgs e) + => UpdatePreview(); - private void comboBox_FontFamily_SelectedIndexChanged(object sender, EventArgs e) => - UpdatePreviewTemp(false); + private void comboBox_FontFamily_SelectedIndexChanged(object sender, EventArgs e) + => UpdatePreview(); private void comboBox_ColorSchemes_SelectedIndexChanged(object sender, EventArgs e) - { - if (comboBox_ColorSchemes.SelectedItem is null) - return; - - if (comboBox_ColorSchemes.Items.Count == 1) - button_DeleteScheme.Enabled = false; // Disallow deleting the last available scheme - - ToggleSaveSchemeButton(); + => UpdatePreview(); - string fullSchemePath = Path.Combine(DefaultPaths.LuaColorConfigsDirectory, comboBox_ColorSchemes.SelectedItem.ToString() + ".luasch"); - ColorScheme selectedScheme = XmlUtils.ReadXmlFile(fullSchemePath); - - UpdateColorButtons(selectedScheme); - UpdatePreviewColors(selectedScheme); + private void button_Color_Click(object sender, EventArgs e) + { } - private void button_Color_Click(object sender, EventArgs e) => - ChangeColor((DarkButton)sender); - private void menuItem_Bold_Click(object sender, EventArgs e) { - menuItem_Bold.Checked = !menuItem_Bold.Checked; - UpdateButton(sender); } private void menuItem_Italic_Click(object sender, EventArgs e) { - menuItem_Italic.Checked = !menuItem_Italic.Checked; - UpdateButton(sender); } private void button_SaveScheme_Click(object sender, EventArgs e) { - using (var form = new FormSaveSchemeAs(ColorSchemeType.Lua)) - if (form.ShowDialog(this) == DialogResult.OK) - { - ColorScheme currentScheme = CreateCurrentScheme(); - - XmlUtils.WriteXmlFile(form.SchemeFilePath, currentScheme); - - comboBox_ColorSchemes.Items.Add(Path.GetFileNameWithoutExtension(form.SchemeFilePath)); - comboBox_ColorSchemes.SelectedItem = Path.GetFileNameWithoutExtension(form.SchemeFilePath); - - comboBox_ColorSchemes.Items.Remove("~UNTITLED"); - } } private void button_DeleteScheme_Click(object sender, EventArgs e) { - DialogResult result = DarkMessageBox.Show(this, - "Are you sure you want to delete the \"" + comboBox_ColorSchemes.SelectedItem + "\" color scheme?", "Are you sure?", - MessageBoxButtons.YesNo, MessageBoxIcon.Question); - - if (result == DialogResult.Yes) - { - string selectedSchemeFilePath = Path.Combine(DefaultPaths.LuaColorConfigsDirectory, comboBox_ColorSchemes.SelectedItem + ".luasch"); - - if (File.Exists(selectedSchemeFilePath)) - { - Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile(selectedSchemeFilePath, - Microsoft.VisualBasic.FileIO.UIOption.AllDialogs, Microsoft.VisualBasic.FileIO.RecycleOption.SendToRecycleBin); - - comboBox_ColorSchemes.Items.Remove(comboBox_ColorSchemes.SelectedItem); - comboBox_ColorSchemes.SelectedIndex = 0; - } - } } private void button_ImportScheme_Click(object sender, EventArgs e) { - using (var dialog = new OpenFileDialog()) - { - dialog.Filter = "Lua Scheme|*.luasch"; - - if (dialog.ShowDialog(this) == DialogResult.OK) - { - File.Copy(dialog.FileName, Path.Combine(DefaultPaths.LuaColorConfigsDirectory, Path.GetFileName(dialog.FileName)), true); - UpdateSchemeList(); - - comboBox_ColorSchemes.SelectedItem = Path.GetFileNameWithoutExtension(dialog.FileName); - } - } } private void button_OpenSchemesFolder_Click(object sender, EventArgs e) { - var startInfo = new ProcessStartInfo - { - FileName = "explorer.exe", - Arguments = DefaultPaths.LuaColorConfigsDirectory, - UseShellExecute = true - }; - - Process.Start(startInfo); } #endregion Events @@ -203,13 +178,16 @@ private void button_OpenSchemesFolder_Click(object sender, EventArgs e) private void UpdateControlsWithSettings(LuaEditorConfiguration config) { - numeric_FontSize.Value = (decimal)config.FontSize - 4; // -4 because AvalonEdit has a different font size scale + numeric_FontSize.Value = (decimal)config.FontSize - 4; comboBox_FontFamily.SelectedItem = config.FontFamily; numeric_UndoStackSize.Value = config.UndoStackSize; LoadSettingsForCheckBoxes(config); - comboBox_ColorSchemes.SelectedItem = config.SelectedColorSchemeName; + if (comboBox_ColorSchemes.Items.Contains(config.SelectedThemeName)) + comboBox_ColorSchemes.SelectedItem = config.SelectedThemeName; + else if (comboBox_ColorSchemes.Items.Contains(ConfigurationDefaults.SelectedThemeName)) + comboBox_ColorSchemes.SelectedItem = ConfigurationDefaults.SelectedThemeName; } private void LoadSettingsForCheckBoxes(LuaEditorConfiguration config) @@ -235,14 +213,14 @@ private void LoadSettingsForCheckBoxes(LuaEditorConfiguration config) public void ApplySettings(LuaEditorConfiguration config) { - config.FontSize = (double)(numeric_FontSize.Value + 4); // +4 because AvalonEdit has a different font size scale - config.FontFamily = comboBox_FontFamily.SelectedItem.ToString(); + config.FontSize = (double)(numeric_FontSize.Value + 4); + config.FontFamily = comboBox_FontFamily.SelectedItem?.ToString() ?? TextEditorBaseDefaults.FontFamily; config.UndoStackSize = (int)numeric_UndoStackSize.Value; ApplySettingsFromCheckBoxes(config); if (comboBox_ColorSchemes.SelectedItem is not null) - config.SelectedColorSchemeName = comboBox_ColorSchemes.SelectedItem.ToString(); + config.SelectedThemeName = comboBox_ColorSchemes.SelectedItem.ToString(); config.Save(); } @@ -259,7 +237,6 @@ private void ApplySettingsFromCheckBoxes(LuaEditorConfiguration config) config.HighlightCurrentLine = checkBox_HighlightCurrentLine.Checked; config.ShowLineNumbers = checkBox_LineNumbers.Checked; - config.ShowVisualSpaces = checkBox_VisibleSpaces.Checked; config.ShowVisualTabs = checkBox_VisibleTabs.Checked; } @@ -270,11 +247,15 @@ private void ApplySettingsFromCheckBoxes(LuaEditorConfiguration config) public void ResetToDefault() { - numeric_FontSize.Value = (decimal)(TextEditorBaseDefaults.FontSize - 4); // -4 because AvalonEdit has a different font size scale + numeric_FontSize.Value = (decimal)(TextEditorBaseDefaults.FontSize - 4); comboBox_FontFamily.SelectedItem = TextEditorBaseDefaults.FontFamily; numeric_UndoStackSize.Value = TextEditorBaseDefaults.UndoStackSize; - ResetCheckBoxSettings(); + + if (comboBox_ColorSchemes.Items.Contains(ConfigurationDefaults.SelectedThemeName)) + comboBox_ColorSchemes.SelectedItem = ConfigurationDefaults.SelectedThemeName; + + UpdatePreview(); } private void ResetCheckBoxSettings() @@ -289,206 +270,96 @@ private void ResetCheckBoxSettings() checkBox_HighlightCurrentLine.Checked = TextEditorBaseDefaults.HighlightCurrentLine; checkBox_LineNumbers.Checked = TextEditorBaseDefaults.ShowLineNumbers; - checkBox_VisibleSpaces.Checked = TextEditorBaseDefaults.ShowVisualSpaces; checkBox_VisibleTabs.Checked = TextEditorBaseDefaults.ShowVisualTabs; } #endregion Resetting - public void ForcePreviewUpdate() => - editorPreview.Focus(); + public void ForcePreviewUpdate() + => editorPreview.Focus(); - private void ChangeColor(DarkButton targetButton) + private void UpdatePreview() { - colorDialog.Color = targetButton.BackColor; - - if (colorDialog.ShowDialog(this) == DialogResult.OK) - { - targetButton.BackColor = colorDialog.Color; - - if (targetButton.Tag != null) - ((HighlightingObject)targetButton.Tag).HtmlColor = ColorTranslator.ToHtml(colorDialog.Color); - - UpdatePreview(); + if (editorPreview is null) + return; - UpdateColorButtonStyleText(targetButton); - } + LuaEditorConfiguration previewConfig = CreatePreviewConfiguration(); + editorPreview.UpdateSettings(previewConfig); + editorPreview.SetSemanticTokens(PreviewTokens); + ForcePreviewUpdate(); } - private void UpdatePreview() + private LuaEditorConfiguration CreatePreviewConfiguration() { - ColorScheme currentScheme = CreateCurrentScheme(); - - bool itemFound = false; - - foreach (string item in comboBox_ColorSchemes.Items) + var config = new LuaEditorConfiguration { - if (item == "~UNTITLED") - continue; - - ColorScheme itemScheme = XmlUtils.ReadXmlFile(Path.Combine(DefaultPaths.LuaColorConfigsDirectory, item + ".luasch")); - - if (currentScheme == itemScheme) - { - comboBox_ColorSchemes.SelectedItem = item; - itemFound = true; - break; - } - } - - if (!itemFound) - { - if (!comboBox_ColorSchemes.Items.Contains("~UNTITLED")) - comboBox_ColorSchemes.Items.Add("~UNTITLED"); - - XmlUtils.WriteXmlFile(Path.Combine(DefaultPaths.LuaColorConfigsDirectory, "~UNTITLED.luasch"), currentScheme); - - comboBox_ColorSchemes.SelectedItem = "~UNTITLED"; - } + FontSize = (double)(numeric_FontSize.Value + 4), + FontFamily = comboBox_FontFamily.SelectedItem?.ToString() ?? TextEditorBaseDefaults.FontFamily, + UndoStackSize = (int)numeric_UndoStackSize.Value, + AutocompleteEnabled = checkBox_Autocomplete.Checked, + WordWrapping = checkBox_WordWrapping.Checked, + AutoCloseParentheses = checkBox_CloseParentheses.Checked, + AutoCloseBrackets = checkBox_CloseBrackets.Checked, + AutoCloseQuotes = checkBox_CloseQuotes.Checked, + AutoCloseBraces = checkBox_CloseBraces.Checked, + HighlightCurrentLine = checkBox_HighlightCurrentLine.Checked, + ShowLineNumbers = checkBox_LineNumbers.Checked, + ShowVisualSpaces = checkBox_VisibleSpaces.Checked, + ShowVisualTabs = checkBox_VisibleTabs.Checked + }; - UpdatePreviewColors(currentScheme); + config.SelectedThemeName = comboBox_ColorSchemes.SelectedItem?.ToString() ?? ConfigurationDefaults.SelectedThemeName; + return config; } - private void UpdateColorButtons(ColorScheme scheme) + private void buttonContextMenu_Opening(object sender, CancelEventArgs e) { - colorButton_Values.BackColor = ColorTranslator.FromHtml(scheme.Values.HtmlColor); - colorButton_Values.Tag = scheme.Values; - - colorButton_Operators.BackColor = ColorTranslator.FromHtml(scheme.Operators.HtmlColor); - colorButton_Operators.Tag = scheme.Operators; - - colorButton_SpecialOperators.BackColor = ColorTranslator.FromHtml(scheme.SpecialOperators.HtmlColor); - colorButton_SpecialOperators.Tag = scheme.SpecialOperators; - - colorButton_Statements.BackColor = ColorTranslator.FromHtml(scheme.Statements.HtmlColor); - colorButton_Statements.Tag = scheme.Statements; - - colorButton_Comments.BackColor = ColorTranslator.FromHtml(scheme.Comments.HtmlColor); - colorButton_Comments.Tag = scheme.Comments; - - UpdateColorButtonStyleText(colorButton_Values); - UpdateColorButtonStyleText(colorButton_Operators); - UpdateColorButtonStyleText(colorButton_SpecialOperators); - UpdateColorButtonStyleText(colorButton_Statements); - UpdateColorButtonStyleText(colorButton_Comments); - - colorButton_Background.BackColor = ColorTranslator.FromHtml(scheme.Background); - colorButton_Foreground.BackColor = ColorTranslator.FromHtml(scheme.Foreground); + e.Cancel = true; } - private ColorScheme CreateCurrentScheme() + private static IReadOnlyList CreatePreviewTokens() { - return new ColorScheme + return new[] { - Values = (HighlightingObject)colorButton_Values.Tag, - Operators = (HighlightingObject)colorButton_Operators.Tag, - SpecialOperators = (HighlightingObject)colorButton_SpecialOperators.Tag, - Statements = (HighlightingObject)colorButton_Statements.Tag, - Comments = (HighlightingObject)colorButton_Comments.Tag, - Background = ColorTranslator.ToHtml(colorButton_Background.BackColor), - Foreground = ColorTranslator.ToHtml(colorButton_Foreground.BackColor) + CreatePreviewToken(0, "Weapon", "class"), + CreatePreviewToken(1, "Weapon", "class"), + CreatePreviewToken(2, "levelName", "variable", 1, "global"), + CreatePreviewToken(4, "Weapon", "class"), + CreatePreviewToken(4, "new", "method", 1, "declaration"), + CreatePreviewToken(4, "name", "parameter"), + CreatePreviewToken(5, "math", "namespace", 1, "defaultLibrary"), + CreatePreviewToken(5, "max", "function", 1, "defaultLibrary"), + CreatePreviewToken(5, "levelName", "variable", 1, "global"), + CreatePreviewToken(6, "name", "property", 1), + CreatePreviewToken(6, "name", "parameter", 2) }; } - private void buttonContextMenu_Opening(object sender, CancelEventArgs e) - { - var sourceButton = (DarkButton)((DarkContextMenu)sender).SourceControl; - var highlighting = (HighlightingObject)sourceButton.Tag; - - menuItem_Bold.Checked = highlighting.IsBold; - menuItem_Italic.Checked = highlighting.IsItalic; - } - - private void UpdateButton(object sender) + private static LuaSemanticToken CreatePreviewToken(int lineIndex, string tokenText, string tokenType, params string[] modifiers) { - var sourceButton = (DarkButton)((DarkContextMenu)((ToolStripMenuItem)sender).GetCurrentParent()).SourceControl; - var highlighting = (HighlightingObject)sourceButton.Tag; - - highlighting.IsBold = menuItem_Bold.Checked; - highlighting.IsItalic = menuItem_Italic.Checked; - - UpdateColorButtonStyleText(sourceButton); - - UpdatePreview(); + return CreatePreviewToken(lineIndex, tokenText, tokenType, 1, modifiers); } - private void UpdateColorButtonStyleText(DarkButton colorButton) + private static LuaSemanticToken CreatePreviewToken(int lineIndex, string tokenText, string tokenType, int occurrence, params string[] modifiers) { - if (colorButton.Tag == null) - return; - - var highlighting = (HighlightingObject)colorButton.Tag; - - if (highlighting.IsBold && highlighting.IsItalic) - colorButton.Text = "Style: Bold & Italic"; - else if (highlighting.IsBold) - colorButton.Text = "Style: Bold"; - else if (highlighting.IsItalic) - colorButton.Text = "Style: Italic"; - else - colorButton.Text = "Style: Normal"; - - if (colorButton.BackColor.R + (colorButton.BackColor.G * 1.25) + colorButton.BackColor.B > 384) // Green is a much lighter color - colorButton.ForeColor = Color.Black; - else - colorButton.ForeColor = Color.White; + int characterIndex = GetOccurrenceIndex(PreviewLines[lineIndex], tokenText, occurrence); + return new LuaSemanticToken(lineIndex, characterIndex, tokenText.Length, tokenType, modifiers); } - private void UpdatePreviewColors(ColorScheme scheme) + private static int GetOccurrenceIndex(string line, string tokenText, int occurrence) { - editorPreview.Background = new System.Windows.Media.SolidColorBrush - ( - (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString - ( - scheme.Background - ) - ); - - editorPreview.Foreground = new System.Windows.Media.SolidColorBrush - ( - (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString - ( - scheme.Foreground - ) - ); - - editorPreview.SyntaxHighlighting = new SyntaxHighlighting(scheme); - } + int startIndex = -1; - private void ToggleSaveSchemeButton() - { - if (comboBox_ColorSchemes.SelectedItem is null) + for (int currentOccurrence = 0; currentOccurrence < occurrence; currentOccurrence++) { - button_SaveScheme.Enabled = false; - button_SaveScheme.Visible = false; - return; - } - - bool isUntitled = comboBox_ColorSchemes.SelectedItem.ToString().Equals("~UNTITLED", StringComparison.OrdinalIgnoreCase); - - button_SaveScheme.Enabled = isUntitled; - button_SaveScheme.Visible = isUntitled; - - comboBox_ColorSchemes.Width = isUntitled ? 395 : 426; - } + startIndex = line.IndexOf(tokenText, startIndex + 1, StringComparison.Ordinal); - private void UpdatePreviewTemp(bool forceUpdate = true) - { - editorPreview.FontSize = (double)(numeric_FontSize.Value + 4); // +4 because AvalonEdit has a different font size scale - - if (comboBox_FontFamily.SelectedItem != null) - editorPreview.FontFamily = new System.Windows.Media.FontFamily(comboBox_FontFamily.SelectedItem.ToString()); - - editorPreview.WordWrap = checkBox_WordWrapping.Checked; - editorPreview.Options.HighlightCurrentLine = checkBox_HighlightCurrentLine.Checked; - editorPreview.ShowLineNumbers = checkBox_LineNumbers.Checked; - - editorPreview.Options.ShowSpaces = checkBox_VisibleSpaces.Checked; - editorPreview.Options.ShowTabs = checkBox_VisibleTabs.Checked; + if (startIndex < 0) + throw new InvalidOperationException("Failed to locate preview token '" + tokenText + "'."); + } - if (forceUpdate) - ForcePreviewUpdate(); + return startIndex; } } } diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml deleted file mode 100644 index ce37e26aed..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \b(?:TODO|FIXME|HACK|UNDONE)\b - - - - - - - - - @(?:alias|as|async|cast|class|deprecated|diagnostic|enum|field|generic|meta|module|nodiscard|operator|overload|package|param|private|protected|public|return|see|source|type|vararg) - (?<=@param\s)[A-Za-z_][A-Za-z0-9_]* - (?<=@field\s)[A-Za-z_][A-Za-z0-9_]* - (?<=@generic\s)[A-Za-z_][A-Za-z0-9_]* - (?<=@alias\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* - (?<=@class\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* - (?<=@enum\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* - (?<=@module\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* - (?<=@type\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* - (?<=@return\s)[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)* - \b(?:any|boolean|function|integer|lightuserdata|nil|number|string|table|thread|unknown|userdata|void)\b - - \b\d+(?:\.\d+)?\b - - - - - - --- - - - - --\[[=]*\[ - \][=]*] - - - - -- - - - - " - " - - - - ' - ' - - - - \[[=]*\[ - \][=]*] - - - (?<=::)[A-Za-z_][A-Za-z0-9_]*(?=::) - (?<=\bgoto\s)[A-Za-z_][A-Za-z0-9_]* - - <(?:const|close)> - - \.\.\. - - - self - _ENV - - - - true - false - nil - - - - and - break - continue - do - else - elseif - end - for - function - goto - if - in - local - not - or - repeat - return - then - until - using - while - - - (?<=\bfunction\s)(?:[A-Za-z_][A-Za-z0-9_]*(?:[.:][A-Za-z_][A-Za-z0-9_]*)*) - (?<=\blocal\s)[A-Za-z_][A-Za-z0-9_]*(?=\s*=\s*function\b) - - \b(?:_G|_VERSION|bit32|coroutine|debug|Effects|Inventory|io|jit|Logic|math|Misc|Objects|os|package|string|Strings|table|TEN|utf8)\b - - \b(?:assert|collectgarbage|dofile|error|getfenv|getmetatable|ipairs|load|loadfile|loadstring|module|next|pairs|pcall|print|rawequal|rawget|rawlen|rawset|require|select|setfenv|setmetatable|tonumber|tostring|type|unpack|warn|xpcall)\b(?=\s*(?:\(|\{|"|'|\[=*\[)) - - (?<=\.)[A-Za-z_][A-Za-z0-9_]*(?=\s*(?:\(|\{|"|'|\[=*\[)) - (?<=:)[A-Za-z_][A-Za-z0-9_]*(?=\s*(?:\(|\{|"|'|\[=*\[)) - \b[A-Za-z_][A-Za-z0-9_]*(?=\s*(?:\(|\{|"|'|\[=*\[)) - - (?<=\.)[A-Za-z_][A-Za-z0-9_]* - (?<=:)[A-Za-z_][A-Za-z0-9_]* - - - \b0[xX](?:[0-9a-fA-F]+(?:\.[0-9a-fA-F]*)?|\.[0-9a-fA-F]+)(?:[pP][+\-]?\d+)?\b - | - \b\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?\b - | - \B\.\d+(?:[eE][+\-]?\d+)?\b - - - \.\.?|//|==|~=|<=|>=|<<|>>|[=+\-*/%^#<>~&|] - ::|[.,;:()\[\]{}] - - diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch deleted file mode 100644 index 7adfb4be37..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/VS15.luasch +++ /dev/null @@ -1,30 +0,0 @@ - - - - #6A9955 - false - false - - - #569CD6 - false - false - - - #569CD6 - false - false - - - Gainsboro - false - false - - - #569CD6 - false - false - - #202020 - Gainsboro - \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json new file mode 100644 index 0000000000..496d0d6353 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json @@ -0,0 +1,32 @@ +{ + "Name": "Monokai", + "EditorBackground": "#2C2C2A", + "EditorForeground": "#F8F8F2", + "SemanticColors": { + "MutedText": "#75715E", + "Misc": "#F8F8F2", + "Method": "#E6DB74", + "Variable": "#FD971F", + "Property": "#66D9EF", + "Type": "#A6E22E", + "Keyword": "#F92672", + "Constant": "#AE81FF", + "File": "#E6DB74", + "SignatureParameterDocumentation": "#CFCFC2", + "SignatureActiveParameter": "#66D9EF", + "SignatureText": "#F8F8F2" + }, + "TextMateTheme": { + "Rules": [ + { "Scope": "comment", "Foreground": "#75715E" }, + { "Scope": "string", "Foreground": "#E6DB74" }, + { "Scope": "constant.numeric, constant.character.escape, constant.language", "Foreground": "#AE81FF" }, + { "Scope": "keyword, storage", "Foreground": "#F92672" }, + { "Scope": "keyword.operator", "Foreground": "#F8F8F2" }, + { "Scope": "entity.name.function, support.function, support.function.library, support.function.any-method", "Foreground": "#E6DB74" }, + { "Scope": "entity.name.class, support.class, support.type, storage.type.generic", "Foreground": "#A6E22E" }, + { "Scope": "variable.parameter, entity.other.attribute", "Foreground": "#FD971F" }, + { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#66D9EF" } + ] + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json new file mode 100644 index 0000000000..da5e534974 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json @@ -0,0 +1,33 @@ +{ + "Name": "NG_CENTER", + "Aliases": ["NG Center", "NG-Center"], + "EditorBackground": "#FFFFFF", + "EditorForeground": "#000000", + "SemanticColors": { + "MutedText": "#808080", + "Misc": "#000000", + "Method": "#000000", + "Variable": "#000000", + "Property": "#000000", + "Type": "#000000", + "Keyword": "#000000", + "Constant": "#000000", + "File": "#000000", + "SignatureParameterDocumentation": "#808080", + "SignatureActiveParameter": "#000000", + "SignatureText": "#000000" + }, + "TextMateTheme": { + "Rules": [ + { "Scope": "comment", "Foreground": "#808080" }, + { "Scope": "string", "Foreground": "#000000" }, + { "Scope": "constant.numeric, constant.character.escape, constant.language", "Foreground": "#000000", "FontStyle": "italic" }, + { "Scope": "keyword, storage", "Foreground": "#000000", "FontStyle": "bold" }, + { "Scope": "keyword.operator", "Foreground": "#000000" }, + { "Scope": "entity.name.function, support.function, support.function.library, support.function.any-method", "Foreground": "#000000" }, + { "Scope": "entity.name.class, support.class, support.type, storage.type.generic", "Foreground": "#000000", "FontStyle": "italic" }, + { "Scope": "variable.parameter, entity.other.attribute", "Foreground": "#000000", "FontStyle": "italic" }, + { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#000000", "FontStyle": "bold" } + ] + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json new file mode 100644 index 0000000000..08f858d26f --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json @@ -0,0 +1,32 @@ +{ + "Name": "Obsidian", + "EditorBackground": "#283032", + "EditorForeground": "#DCDCDC", + "SemanticColors": { + "MutedText": "#66747B", + "Misc": "#DCDCDC", + "Method": "#93C763", + "Variable": "#8AB7D9", + "Property": "#668BB0", + "Type": "#93C763", + "Keyword": "#A082BD", + "Constant": "#FFCD22", + "File": "#D8C57A", + "SignatureParameterDocumentation": "#A7B6BD", + "SignatureActiveParameter": "#668BB0", + "SignatureText": "#DCDCDC" + }, + "TextMateTheme": { + "Rules": [ + { "Scope": "comment", "Foreground": "#66747B" }, + { "Scope": "string", "Foreground": "#EC7600" }, + { "Scope": "constant.numeric, constant.character.escape, constant.language", "Foreground": "#FFCD22" }, + { "Scope": "keyword, storage", "Foreground": "#A082BD" }, + { "Scope": "keyword.operator", "Foreground": "#DCDCDC" }, + { "Scope": "entity.name.function, support.function, support.function.library, support.function.any-method", "Foreground": "#93C763" }, + { "Scope": "entity.name.class, support.class, support.type, storage.type.generic", "Foreground": "#93C763" }, + { "Scope": "variable.parameter, entity.other.attribute", "Foreground": "#8AB7D9" }, + { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#668BB0" } + ] + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json new file mode 100644 index 0000000000..a6b4b5ffd9 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json @@ -0,0 +1,34 @@ +{ + "Name": "Tomorrow Night", + "Aliases": ["Tomorrow Night Eighties", "SharpLua Classic"], + "EditorBackground": "#2D2D2D", + "EditorForeground": "#CCCCCC", + "SemanticColors": { + "MutedText": "#999999", + "Misc": "#CCCCCC", + "Method": "#FFCC66", + "Variable": "#E6C8FF", + "Property": "#E6C8FF", + "Type": "#66CCCC", + "Keyword": "#6699CC", + "Constant": "#99CC99", + "File": "#F99157", + "SignatureParameterDocumentation": "#999999", + "SignatureActiveParameter": "#FFCC66", + "SignatureText": "#CCCCCC" + }, + "TextMateTheme": { + "Rules": [ + { "Scope": "comment", "Foreground": "#999999" }, + { "Scope": "string", "Foreground": "#F99157" }, + { "Scope": "constant.numeric, constant.character.escape, constant.language.nil", "Foreground": "#99CC99" }, + { "Scope": "keyword, storage", "Foreground": "#6699CC", "FontStyle": "bold" }, + { "Scope": "keyword.control.goto, keyword.control.return, keyword.control.break", "Foreground": "#CC99CC" }, + { "Scope": "keyword.control.local", "Foreground": "#F99157", "FontStyle": "bold" }, + { "Scope": "constant.language.boolean, support.class, support.type, support.variable, variable.language.self", "Foreground": "#66CCCC", "FontStyle": "bold" }, + { "Scope": "entity.name.function, support.function, support.function.library, support.function.any-method", "Foreground": "#FFCC66", "FontStyle": "bold" }, + { "Scope": "entity.name.class, entity.other.attribute, variable.parameter, variable.other.object, support.type.property-name", "Foreground": "#E6C8FF" }, + { "Scope": "keyword.operator, punctuation", "Foreground": "#CCCCCC" } + ] + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json new file mode 100644 index 0000000000..98606ab2c6 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json @@ -0,0 +1,33 @@ +{ + "Name": "VSCode Dark+", + "Aliases": ["VS15", "VSCode", "Dark+"], + "EditorBackground": "#202020", + "EditorForeground": "#DCDCDC", + "SemanticColors": { + "MutedText": "#8C8C8C", + "Misc": "#C8C8C8", + "Method": "#DCDCAA", + "Variable": "#9CDCFE", + "Property": "#4FC1FF", + "Type": "#4EC9B0", + "Keyword": "#C586C0", + "Constant": "#B5CEA8", + "File": "#D7BA7D", + "SignatureParameterDocumentation": "#B4B4B4", + "SignatureActiveParameter": "#56B4EB", + "SignatureText": "#DCDCDC" + }, + "TextMateTheme": { + "Rules": [ + { "Scope": "comment", "Foreground": "#6A9955" }, + { "Scope": "string", "Foreground": "#CE9178" }, + { "Scope": "constant.numeric, constant.character.escape, constant.language", "Foreground": "#B5CEA8" }, + { "Scope": "keyword, storage", "Foreground": "#C586C0" }, + { "Scope": "keyword.operator", "Foreground": "#D4D4D4" }, + { "Scope": "entity.name.function, support.function, support.function.library, support.function.any-method", "Foreground": "#DCDCAA" }, + { "Scope": "entity.name.class, support.class, support.type, storage.type.generic", "Foreground": "#4EC9B0" }, + { "Scope": "variable.parameter, entity.other.attribute", "Foreground": "#9CDCFE" }, + { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#569CD6" } + ] + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json new file mode 100644 index 0000000000..117455dd4b --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json @@ -0,0 +1,33 @@ +{ + "Name": "VSCode Light+", + "Aliases": ["VSCode Light", "Light+"], + "EditorBackground": "#FFFFFF", + "EditorForeground": "#1E1E1E", + "SemanticColors": { + "MutedText": "#616161", + "Misc": "#1E1E1E", + "Method": "#795E26", + "Variable": "#001080", + "Property": "#0451A5", + "Type": "#267F99", + "Keyword": "#0000FF", + "Constant": "#098658", + "File": "#795E26", + "SignatureParameterDocumentation": "#4D4D4C", + "SignatureActiveParameter": "#001080", + "SignatureText": "#1E1E1E" + }, + "TextMateTheme": { + "Rules": [ + { "Scope": "comment", "Foreground": "#008000" }, + { "Scope": "string", "Foreground": "#A31515" }, + { "Scope": "constant.numeric, constant.character.escape, constant.language", "Foreground": "#098658" }, + { "Scope": "keyword, storage", "Foreground": "#0000FF" }, + { "Scope": "keyword.operator", "Foreground": "#1E1E1E" }, + { "Scope": "entity.name.function, support.function, support.function.library, support.function.any-method", "Foreground": "#795E26" }, + { "Scope": "entity.name.class, support.class, support.type, storage.type.generic", "Foreground": "#267F99" }, + { "Scope": "variable.parameter, entity.other.attribute", "Foreground": "#001080" }, + { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#0451A5" } + ] + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json new file mode 100644 index 0000000000..a36074a88a --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json @@ -0,0 +1,33 @@ +{ + "Name": "Visual Studio 2015", + "Aliases": ["Visual Studio 15", "VS 2015"], + "EditorBackground": "#1E1E1E", + "EditorForeground": "#DCDCDC", + "SemanticColors": { + "MutedText": "#7A7A7A", + "Misc": "#DCDCDC", + "Method": "#DCDCAA", + "Variable": "#9CDCFE", + "Property": "#9CDCFE", + "Type": "#4EC9B0", + "Keyword": "#569CD6", + "Constant": "#B5CEA8", + "File": "#D7BA7D", + "SignatureParameterDocumentation": "#B4B4B4", + "SignatureActiveParameter": "#569CD6", + "SignatureText": "#DCDCDC" + }, + "TextMateTheme": { + "Rules": [ + { "Scope": "comment", "Foreground": "#57A64A" }, + { "Scope": "string", "Foreground": "#D69D85" }, + { "Scope": "constant.numeric, constant.character.escape, constant.language", "Foreground": "#B5CEA8" }, + { "Scope": "keyword, storage", "Foreground": "#569CD6" }, + { "Scope": "keyword.operator", "Foreground": "#D4D4D4" }, + { "Scope": "entity.name.function, support.function, support.function.library, support.function.any-method", "Foreground": "#DCDCAA" }, + { "Scope": "entity.name.class, support.class, support.type, storage.type.generic", "Foreground": "#4EC9B0" }, + { "Scope": "variable.parameter, entity.other.attribute", "Foreground": "#9CDCFE" }, + { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#569CD6" } + ] + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index 84e9fa1d5e..cfbe95560f 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -11,24 +11,25 @@ namespace TombLib.Scripting.Lua.Highlighting { internal sealed class LuaSemanticTokensColorizer : DocumentColorizingTransformer { - private static readonly Brush DefaultLibraryBrush = LuaEditorColorPalette.TypeBrush; - private static readonly Brush GlobalVariableBrush = LuaEditorColorPalette.PropertyBrush; - private static readonly Brush TypeBrush = LuaEditorColorPalette.TypeBrush; - private static readonly Brush FunctionBrush = LuaEditorColorPalette.MethodBrush; - private static readonly Brush ParameterBrush = LuaEditorColorPalette.VariableBrush; - private static readonly Brush PropertyBrush = LuaEditorColorPalette.VariableBrush; - private static readonly Brush DecoratorBrush = LuaEditorColorPalette.KeywordBrush; - private static readonly Brush MacroBrush = LuaEditorColorPalette.KeywordBrush; - private static readonly Brush EnumMemberBrush = LuaEditorColorPalette.ConstantBrush; private static readonly TextDecorationCollection DeprecatedDecorations = CreateTextDecorations(TextDecorations.Strikethrough); private static readonly IReadOnlyDictionary> EmptyTokensByLine = new Dictionary>(); + private LuaThemeBrushSet _themeBrushSet; private readonly TextView _textView; private IReadOnlyDictionary> _tokensByLine = EmptyTokensByLine; - public LuaSemanticTokensColorizer(TextView textView) - => _textView = textView ?? throw new ArgumentNullException(nameof(textView)); + public LuaSemanticTokensColorizer(TextView textView, LuaThemeBrushSet themeBrushSet) + { + _textView = textView ?? throw new ArgumentNullException(nameof(textView)); + _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); + } + + public void UpdateTheme(LuaThemeBrushSet themeBrushSet) + { + _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); + _textView.Redraw(); + } public void SetTokens(IReadOnlyList tokens) { @@ -108,25 +109,25 @@ protected override void ColorizeLine(DocumentLine line) } } - private static LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) + private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) { Brush? foreground = token.Type switch { - "namespace" => token.HasModifier("defaultLibrary") ? DefaultLibraryBrush : TypeBrush, - "type" => TypeBrush, - "class" => TypeBrush, - "enum" => TypeBrush, - "interface" => TypeBrush, - "struct" => TypeBrush, - "typeParameter" => TypeBrush, - "function" => token.HasModifier("defaultLibrary") ? DefaultLibraryBrush : FunctionBrush, - "method" => token.HasModifier("defaultLibrary") ? DefaultLibraryBrush : FunctionBrush, - "parameter" => ParameterBrush, - "property" => PropertyBrush, - "event" => PropertyBrush, - "enumMember" => EnumMemberBrush, - "decorator" => DecoratorBrush, - "macro" => MacroBrush, + "namespace" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.TypeBrush, + "type" => _themeBrushSet.TypeBrush, + "class" => _themeBrushSet.TypeBrush, + "enum" => _themeBrushSet.TypeBrush, + "interface" => _themeBrushSet.TypeBrush, + "struct" => _themeBrushSet.TypeBrush, + "typeParameter" => _themeBrushSet.TypeBrush, + "function" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, + "method" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, + "parameter" => _themeBrushSet.VariableBrush, + "property" => _themeBrushSet.VariableBrush, + "event" => _themeBrushSet.VariableBrush, + "enumMember" => _themeBrushSet.ConstantBrush, + "decorator" => _themeBrushSet.KeywordBrush, + "macro" => _themeBrushSet.KeywordBrush, "variable" => ResolveVariableBrush(token), _ => null }; @@ -137,13 +138,13 @@ private static LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) token.HasModifier("deprecated") ? DeprecatedDecorations : null); } - private static Brush? ResolveVariableBrush(LuaSemanticToken token) + private Brush? ResolveVariableBrush(LuaSemanticToken token) { if (token.HasModifier("defaultLibrary")) - return DefaultLibraryBrush; + return _themeBrushSet.TypeBrush; if (token.HasModifier("global")) - return GlobalVariableBrush; + return _themeBrushSet.PropertyBrush; return null; } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index d340d1b339..093a430729 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -56,7 +56,7 @@ private void CloseCompletionWindow() private void InitializeLuaCompletionWindow() { InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); - LuaCompletionWindowStyle.Apply(_completionWindow); + LuaCompletionWindowStyle.Apply(_completionWindow, GetThemeBrushSet()); StyleCompletionTooltip(); MakeCompletionWindowNonActivatable(); } @@ -89,9 +89,10 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) } var completionDataItems = new LuaCompletionData[items.Count]; + var brushSet = GetThemeBrushSet(); for (int i = 0; i < items.Count; i++) - completionDataItems[i] = new LuaCompletionData(items[i]); + completionDataItems[i] = new LuaCompletionData(items[i], brushSet); if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) return; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs index 42c601c15b..b032fd0d19 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs @@ -20,7 +20,9 @@ public void ClearSemanticTokens() private void EnsureSemanticTokensColorizerAttached() { if (_semanticTokensColorizer is null) - _semanticTokensColorizer = new LuaSemanticTokensColorizer(TextArea.TextView); + _semanticTokensColorizer = new LuaSemanticTokensColorizer(TextArea.TextView, GetThemeBrushSet()); + else + _semanticTokensColorizer.UpdateTheme(GetThemeBrushSet()); if (!TextArea.TextView.LineTransformers.Contains(_semanticTokensColorizer)) TextArea.TextView.LineTransformers.Add(_semanticTokensColorizer); diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index 0e2bf509f6..0a8687cfc0 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -13,10 +13,6 @@ namespace TombLib.Scripting.Lua { public sealed partial class LuaEditor { - private static readonly SolidColorBrush SignatureParamDocForeground = LuaEditorColorPalette.SignatureParamDocForeground; - private static readonly SolidColorBrush SignatureActiveParamForeground = LuaEditorColorPalette.SignatureActiveParamForeground; - private static readonly SolidColorBrush SignatureForeground = LuaEditorColorPalette.SignatureForeground; - private CancellationTokenSource? _signatureCancellationTokenSource; private readonly Popup _signaturePopup = new Popup(); @@ -83,15 +79,16 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double contentMaxWidth) { + LuaThemeBrushSet brushSet = GetThemeBrushSet(); var panel = new StackPanel { MaxWidth = contentMaxWidth }; - panel.Children.Add(BuildSignatureBlock(signatureInfo)); + panel.Children.Add(BuildSignatureBlock(signatureInfo, brushSet)); if (!string.IsNullOrWhiteSpace(signatureInfo.Documentation)) { panel.Children.Add(new TextBlock { Text = signatureInfo.Documentation, - Foreground = SignatureParamDocForeground, + Foreground = brushSet.SignatureParamDocForeground, FontFamily = SystemFonts.MessageFontFamily, FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), TextWrapping = TextWrapping.Wrap, @@ -108,7 +105,7 @@ private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double c panel.Children.Add(new TextBlock { Text = activeParam.Label + ": " + activeParam.Documentation, - Foreground = SignatureParamDocForeground, + Foreground = brushSet.SignatureParamDocForeground, FontFamily = SystemFonts.MessageFontFamily, FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), TextWrapping = TextWrapping.Wrap, @@ -187,14 +184,14 @@ private async Task RequestSignatureHelpAsync(int offset) private void ScheduleSignatureHelpRefresh() => Dispatcher.BeginInvoke(new Action(() => _ = RequestSignatureHelpAsync(CaretOffset))); - private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo) + private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo, LuaThemeBrushSet brushSet) { var textBlock = new TextBlock { FontFamily = new FontFamily("Consolas"), FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), TextWrapping = TextWrapping.Wrap, - Foreground = SignatureForeground + Foreground = brushSet.SignatureForeground }; string label = signatureInfo.Label; @@ -226,7 +223,7 @@ private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo) if (i == signatureInfo.ActiveParameter) { run.FontWeight = FontWeights.Bold; - run.Foreground = SignatureActiveParamForeground; + run.Foreground = brushSet.SignatureActiveParamForeground; } textBlock.Inlines.Add(run); diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index 5e68c5c511..10616f95fb 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -1,13 +1,10 @@ using ICSharpCode.AvalonEdit.Highlighting; -using ICSharpCode.AvalonEdit.Highlighting.Xshd; using System; -using System.IO; -using System.Windows.Media; -using System.Xml; using TombLib.Scripting.Bases; using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua { @@ -16,6 +13,7 @@ public sealed partial class LuaEditor : TextEditorBase public override string DefaultFileExtension => ".lua"; private LuaTextMateInstallation? _textMateHighlighting; + private LuaThemeBrushSet? _themeBrushSet; public ILuaIntellisenseProvider? IntellisenseProvider { get; set; } public event Action? DefinitionNavigationRequested; @@ -30,63 +28,27 @@ public LuaEditor(Version engineVersion) : base(engineVersion) public override void UpdateSettings(Bases.ConfigurationBase configuration) { var config = configuration as LuaEditorConfiguration; - ColorScheme colorScheme = config?.ColorScheme ?? new ColorScheme(); + var theme = config?.Theme ?? LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName); + _themeBrushSet = LuaEditorColorPalette.Create(theme); _textMateHighlighting?.Dispose(); _textMateHighlighting = null; - if (!LuaTextMateSyntaxHighlighting.TryInstall(this, out _textMateHighlighting)) - SyntaxHighlighting = LoadFallbackSyntaxHighlighting() ?? new SyntaxHighlighting(colorScheme); - else - SyntaxHighlighting = null; + LuaTextMateSyntaxHighlighting.TryInstall(this, theme.TextMateTheme, out _textMateHighlighting); + SyntaxHighlighting = null; EnsureSemanticTokensColorizerAttached(); - Background = CreateEditorBrush(colorScheme.Background, "#202020"); - Foreground = CreateEditorBrush(colorScheme.Foreground, "Gainsboro"); + Background = _themeBrushSet.EditorBackground; + Foreground = _themeBrushSet.EditorForeground; base.UpdateSettings(configuration); LiveErrorUnderlining = true; } - private static IHighlightingDefinition? LoadFallbackSyntaxHighlighting() + private LuaThemeBrushSet GetThemeBrushSet() { - string fallbackDefinitionPath = Path.Combine( - AppContext.BaseDirectory, - "Configs", - "TextEditors", - "ColorSchemes", - "Lua", - "Default.xml"); - - if (!File.Exists(fallbackDefinitionPath)) - return null; - - using var stream = new FileStream(fallbackDefinitionPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using var reader = new XmlTextReader(stream); - return HighlightingLoader.Load(reader, HighlightingManager.Instance); - } - - private static SolidColorBrush CreateEditorBrush(string colorValue, string fallbackColorValue) - { - try - { - string effectiveColor = string.IsNullOrWhiteSpace(colorValue) ? fallbackColorValue : colorValue; - var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(effectiveColor)); - - if (brush.CanFreeze) - brush.Freeze(); - - return brush; - } - catch - { - var fallbackBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(fallbackColorValue)); - - if (fallbackBrush.CanFreeze) - fallbackBrush.Freeze(); - - return fallbackBrush; - } + _themeBrushSet ??= LuaEditorColorPalette.Create(LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName)); + return _themeBrushSet; } } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs index 44174d0e6a..e914793afb 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs @@ -1,46 +1,43 @@ using System.IO; +using System.Xml.Serialization; using TombLib.Scripting.Bases; -using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Resources; -using TombLib.Utils; namespace TombLib.Scripting.Lua { public sealed class LuaEditorConfiguration : TextEditorConfigBase { public override string DefaultPath { get; } - public ColorScheme ColorScheme = new ColorScheme(); - private string _selectedColorSchemeName = ConfigurationDefaults.SelectedColorSchemeName; + private string _selectedThemeName = ConfigurationDefaults.SelectedThemeName; - public string SelectedColorSchemeName + public string SelectedThemeName { - get => _selectedColorSchemeName; + get => _selectedThemeName; set { - _selectedColorSchemeName = string.IsNullOrWhiteSpace(value) - ? ConfigurationDefaults.SelectedColorSchemeName - : value; + _selectedThemeName = LuaThemeRepository.ResolveThemeName(value); - ColorScheme = LoadColorScheme(_selectedColorSchemeName); + Theme = LuaThemeRepository.GetTheme(_selectedThemeName); } } - public LuaEditorConfiguration() + [XmlIgnore] + public Objects.LuaTheme Theme { get; private set; } = LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName); + + public string SelectedColorSchemeName { - DefaultPath = Path.Combine(DefaultPaths.TextEditorConfigsDirectory, ConfigurationDefaults.ConfigurationFileName); - SelectedColorSchemeName = ConfigurationDefaults.SelectedColorSchemeName; + get => SelectedThemeName; + set => SelectedThemeName = value; } - private static ColorScheme LoadColorScheme(string schemeName) + public LuaEditorConfiguration() { - string schemeFilePath = Path.Combine( - DefaultPaths.LuaColorConfigsDirectory, - schemeName + ConfigurationDefaults.ColorSchemeFileExtension); - - return File.Exists(schemeFilePath) - ? XmlUtils.ReadXmlFile(schemeFilePath) - : new ColorScheme(); + DefaultPath = Path.Combine(DefaultPaths.TextEditorConfigsDirectory, ConfigurationDefaults.ConfigurationFileName); + SelectedThemeName = ConfigurationDefaults.SelectedThemeName; } + + public bool ShouldSerializeSelectedColorSchemeName() + => false; } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs deleted file mode 100644 index b6ec533deb..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Objects/ColorScheme.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using TombLib.Scripting.Bases; -using TombLib.Scripting.Objects; - -namespace TombLib.Scripting.Lua.Objects -{ - public sealed class ColorScheme : ColorSchemeBase - { - public HighlightingObject Comments { get; set; } = CreateDefaultHighlighting("#6A9955"); - public HighlightingObject Values { get; set; } = CreateDefaultHighlighting("#569CD6"); - public HighlightingObject Statements { get; set; } = CreateDefaultHighlighting("#569CD6"); - public HighlightingObject Operators { get; set; } = CreateDefaultHighlighting("Gainsboro"); - public HighlightingObject SpecialOperators { get; set; } = CreateDefaultHighlighting("#569CD6"); - - public ColorScheme() - { - Background = "#202020"; - Foreground = "Gainsboro"; - } - - public static bool operator ==(ColorScheme? left, ColorScheme? right) - => ReferenceEquals(left, right) || left is not null && left.Equals(right); - - public static bool operator !=(ColorScheme? left, ColorScheme? right) - => !(left == right); - - public override bool Equals(object? obj) - { - if (obj is not ColorScheme other) - return false; - - return EqualityComparer.Default.Equals(Comments, other.Comments) - && EqualityComparer.Default.Equals(Values, other.Values) - && EqualityComparer.Default.Equals(Statements, other.Statements) - && EqualityComparer.Default.Equals(Operators, other.Operators) - && EqualityComparer.Default.Equals(SpecialOperators, other.SpecialOperators) - && string.Equals(Background, other.Background, StringComparison.OrdinalIgnoreCase) - && string.Equals(Foreground, other.Foreground, StringComparison.OrdinalIgnoreCase); - } - - public override int GetHashCode() - { - var hashCode = new HashCode(); - hashCode.Add(Comments); - hashCode.Add(Values); - hashCode.Add(Statements); - hashCode.Add(Operators); - hashCode.Add(SpecialOperators); - hashCode.Add(Background ?? string.Empty, StringComparer.OrdinalIgnoreCase); - hashCode.Add(Foreground ?? string.Empty, StringComparer.OrdinalIgnoreCase); - return hashCode.ToHashCode(); - } - - private static HighlightingObject CreateDefaultHighlighting(string htmlColor) - => new HighlightingObject { HtmlColor = htmlColor }; - } -} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index 2e2c33cdd3..967990ce7b 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -11,10 +11,11 @@ using ICSharpCode.AvalonEdit.Editing; using TombLib.Scripting.Rendering; using TombLib.Scripting.Resources; +using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua.Objects { - public sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged + internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged { private const double DescriptionMaxWidth = 540.0; private const double DescriptionTextMaxWidth = 500.0; @@ -22,20 +23,22 @@ public sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged private static readonly SolidColorBrush DescriptionBackgroundBrush = TextEditorColorPalette.ToolTipBackground; private static readonly SolidColorBrush DescriptionForegroundBrush = TextEditorColorPalette.ToolTipForeground; private readonly object _resolveSync = new object(); + private readonly LuaThemeBrushSet _brushSet; private LuaCompletionItem _item; private string? _displayDetail; private object? _cachedDescription; private Task? _resolveTask; - public LuaCompletionData(LuaCompletionItem item) + public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet) { _item = item ?? throw new ArgumentNullException(nameof(item)); + _brushSet = brushSet ?? throw new ArgumentNullException(nameof(brushSet)); _displayDetail = FlattenSingleLineText(_item.Detail); } public event PropertyChangedEventHandler? PropertyChanged; - public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind); + public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind, _brushSet); public string Text => _item.FilterText; public string DisplayText => _item.Label; public string? DisplayDetail => _displayDetail; diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs index 50134b151c..1a3e6e7bbb 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -7,27 +7,29 @@ namespace TombLib.Scripting.Lua.Objects // Geometry paths below are vendored from microsoft/vscode-codicons under the MIT license. internal static class LuaCompletionIconFactory { - private static readonly Dictionary Cache = new Dictionary(); + private static readonly Dictionary Cache = new Dictionary(); - public static ImageSource GetIcon(LuaCompletionIconKind kind) + public static ImageSource GetIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) { + string cacheKey = brushSet.ThemeName + ":" + kind; + lock (Cache) { - if (Cache.TryGetValue(kind, out ImageSource? image)) + if (Cache.TryGetValue(cacheKey, out ImageSource? image)) return image; - image = CreateIcon(kind); - Cache[kind] = image; + image = CreateIcon(kind, brushSet); + Cache[cacheKey] = image; return image; } } - private static ImageSource CreateIcon(LuaCompletionIconKind kind) + private static ImageSource CreateIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) { var drawingGroup = new DrawingGroup(); foreach (string pathData in GetPathData(kind)) - drawingGroup.Children.Add(CreatePathDrawing(GetBrush(kind), pathData)); + drawingGroup.Children.Add(CreatePathDrawing(brushSet.GetCompletionItemBrush(kind), pathData)); drawingGroup.Freeze(); @@ -43,25 +45,6 @@ private static GeometryDrawing CreatePathDrawing(Brush brush, string pathData) return new GeometryDrawing(brush, null, geometry); } - private static Brush GetBrush(LuaCompletionIconKind kind) - { - return kind switch - { - LuaCompletionIconKind.Variable => LuaEditorColorPalette.VariableBrush, - LuaCompletionIconKind.Field => LuaEditorColorPalette.PropertyBrush, - LuaCompletionIconKind.Method => LuaEditorColorPalette.MethodBrush, - LuaCompletionIconKind.Property => LuaEditorColorPalette.PropertyBrush, - LuaCompletionIconKind.Class => LuaEditorColorPalette.TypeBrush, - LuaCompletionIconKind.Keyword => LuaEditorColorPalette.KeywordBrush, - LuaCompletionIconKind.Constant => LuaEditorColorPalette.ConstantBrush, - LuaCompletionIconKind.Parameter => LuaEditorColorPalette.VariableBrush, - LuaCompletionIconKind.Namespace => LuaEditorColorPalette.TypeBrush, - LuaCompletionIconKind.File => LuaEditorColorPalette.FileBrush, - LuaCompletionIconKind.Folder => LuaEditorColorPalette.FileBrush, - _ => LuaEditorColorPalette.MiscBrush - }; - } - private static string[] GetPathData(LuaCompletionIconKind kind) { return kind switch diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs index d813a2eeeb..54ac1050c4 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs @@ -9,11 +9,9 @@ namespace TombLib.Scripting.Lua.Objects { internal static class LuaCompletionWindowStyle { - private static readonly Brush DetailBrush = LuaEditorColorPalette.MutedTextBrush; - private static readonly DataTemplate ItemTemplate = CreateItemTemplate(); private static readonly Style ItemContainerStyle = CreateItemContainerStyle(); - public static void Apply(CompletionWindow window) + public static void Apply(CompletionWindow window, LuaThemeBrushSet brushSet) { if (window is null) return; @@ -27,11 +25,11 @@ public static void Apply(CompletionWindow window) window.CompletionList.ListBox.IsTabStop = false; window.CompletionList.ListBox.FontFamily = window.TextArea.FontFamily; window.CompletionList.ListBox.FontSize = window.TextArea.FontSize; - window.CompletionList.ListBox.ItemTemplate = ItemTemplate; + window.CompletionList.ListBox.ItemTemplate = CreateItemTemplate(brushSet.MutedTextBrush); window.CompletionList.ListBox.ItemContainerStyle = ItemContainerStyle; } - private static DataTemplate CreateItemTemplate() + private static DataTemplate CreateItemTemplate(Brush detailBrush) { var template = new DataTemplate(typeof(LuaCompletionData)); @@ -48,7 +46,7 @@ private static DataTemplate CreateItemTemplate() var detail = new FrameworkElementFactory(typeof(TextBlock)); detail.SetValue(DockPanel.DockProperty, Dock.Right); - detail.SetValue(TextBlock.ForegroundProperty, DetailBrush); + detail.SetValue(TextBlock.ForegroundProperty, detailBrush); detail.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); detail.SetValue(FrameworkElement.MarginProperty, new Thickness(12.0, 0.0, 0.0, 0.0)); detail.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs new file mode 100644 index 0000000000..ef2bc068ed --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using TombLib.Scripting.Highlighting; + +namespace TombLib.Scripting.Lua.Objects +{ + public sealed class LuaTheme + { + public string Name { get; set; } = string.Empty; + public List Aliases { get; set; } = new List(); + public string EditorBackground { get; set; } = "#202020"; + public string EditorForeground { get; set; } = "Gainsboro"; + public TextMateTokenTheme TextMateTheme { get; set; } = new TextMateTokenTheme(); + public LuaThemeSemanticColors SemanticColors { get; set; } = new LuaThemeSemanticColors(); + + public LuaTheme Normalize(string fallbackName) + { + if (string.IsNullOrWhiteSpace(Name)) + Name = fallbackName; + + if (string.IsNullOrWhiteSpace(EditorBackground)) + EditorBackground = "#202020"; + + if (string.IsNullOrWhiteSpace(EditorForeground)) + EditorForeground = "Gainsboro"; + + Aliases ??= new List(); + TextMateTheme ??= new TextMateTokenTheme(); + SemanticColors ??= new LuaThemeSemanticColors(); + SemanticColors.Normalize(); + + return this; + } + } + + public sealed class LuaThemeSemanticColors + { + public string MutedText { get; set; } = "#8C8C8C"; + public string Misc { get; set; } = "#C8C8C8"; + public string Method { get; set; } = "#DCDCAA"; + public string Variable { get; set; } = "#9CDCFE"; + public string Property { get; set; } = "#4FC1FF"; + public string Type { get; set; } = "#4EC9B0"; + public string Keyword { get; set; } = "#C586C0"; + public string Constant { get; set; } = "#B5CEA8"; + public string File { get; set; } = "#D7BA7D"; + public string SignatureParameterDocumentation { get; set; } = "#B4B4B4"; + public string SignatureActiveParameter { get; set; } = "#56B4EB"; + public string SignatureText { get; set; } = "#D4D4D4"; + + public void Normalize() + { + MutedText = NormalizeValue(MutedText, "#8C8C8C"); + Misc = NormalizeValue(Misc, "#C8C8C8"); + Method = NormalizeValue(Method, "#DCDCAA"); + Variable = NormalizeValue(Variable, "#9CDCFE"); + Property = NormalizeValue(Property, "#4FC1FF"); + Type = NormalizeValue(Type, "#4EC9B0"); + Keyword = NormalizeValue(Keyword, "#C586C0"); + Constant = NormalizeValue(Constant, "#B5CEA8"); + File = NormalizeValue(File, "#D7BA7D"); + SignatureParameterDocumentation = NormalizeValue(SignatureParameterDocumentation, "#B4B4B4"); + SignatureActiveParameter = NormalizeValue(SignatureActiveParameter, "#56B4EB"); + SignatureText = NormalizeValue(SignatureText, "#D4D4D4"); + } + + private static string NormalizeValue(string value, string fallbackValue) + { + if (string.IsNullOrWhiteSpace(value)) + return fallbackValue; + + return value; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs b/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs deleted file mode 100644 index 69aaaa0e66..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Objects/SyntaxHighlighting.cs +++ /dev/null @@ -1,71 +0,0 @@ -using ICSharpCode.AvalonEdit.Highlighting; -using System; -using System.Collections.Generic; -using System.Text.RegularExpressions; -using System.Windows; -using System.Windows.Media; -using TombLib.Scripting.Objects; -using TombLib.Scripting.Lua.Resources; - -namespace TombLib.Scripting.Lua.Objects -{ - public sealed class SyntaxHighlighting : IHighlightingDefinition - { - private static readonly IReadOnlyList EmptyHighlightingColors = Array.Empty(); - private static readonly IDictionary EmptyProperties = new Dictionary(); - - private readonly ColorScheme _scheme; - private readonly HighlightingRuleSet _mainRuleSet; - - public SyntaxHighlighting(ColorScheme scheme) - { - _scheme = scheme ?? new ColorScheme(); - _mainRuleSet = CreateMainRuleSet(); - } - - public HighlightingRuleSet MainRuleSet => _mainRuleSet; - - public string Name => "Lua Rules"; - - public IEnumerable NamedHighlightingColors => EmptyHighlightingColors; - public IDictionary Properties => EmptyProperties; - - public HighlightingColor? GetNamedColor(string name) - => null; - - public HighlightingRuleSet? GetNamedRuleSet(string name) - => string.Equals(name, Name, StringComparison.Ordinal) ? _mainRuleSet : null; - - private HighlightingRuleSet CreateMainRuleSet() - { - var ruleSet = new HighlightingRuleSet - { - Name = Name - }; - - ruleSet.Rules.Add(CreateRule(Patterns.Comments, _scheme.Comments)); - ruleSet.Rules.Add(CreateRule(Patterns.Values, _scheme.Values, RegexOptions.IgnoreCase)); - ruleSet.Rules.Add(CreateRule(Patterns.Statements, _scheme.Statements, RegexOptions.IgnoreCase)); - ruleSet.Rules.Add(CreateRule(Patterns.Operators, _scheme.Operators, RegexOptions.IgnoreCase)); - ruleSet.Rules.Add(CreateRule(Patterns.SpecialOperators, _scheme.SpecialOperators, RegexOptions.IgnoreCase)); - - return ruleSet; - } - - private static HighlightingRule CreateRule(string pattern, HighlightingObject highlighting, RegexOptions options = RegexOptions.None) - { - highlighting ??= new HighlightingObject(); - - return new HighlightingRule - { - Regex = new Regex(pattern, RegexOptions.Compiled | options), - Color = new HighlightingColor - { - Foreground = new SimpleHighlightingBrush((Color)ColorConverter.ConvertFromString(highlighting.HtmlColor)), - FontWeight = highlighting.IsBold ? FontWeights.Bold : FontWeights.Normal, - FontStyle = highlighting.IsItalic ? FontStyles.Italic : FontStyles.Normal - } - }; - } - } -} diff --git a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs index ac4ef80066..30e3442307 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs @@ -3,8 +3,7 @@ public struct ConfigurationDefaults { public const string ConfigurationFileName = "LuaConfiguration.xml"; - public const string ColorSchemeFileExtension = ".luasch"; - public const string SelectedColorSchemeName = "VS15"; + public const string SelectedThemeName = "VSCode Dark+"; } } diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs index a1bfc55206..81a61cc0da 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs @@ -1,4 +1,5 @@ using System.Windows.Media; +using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Resources; using static TombLib.WPF.BrushHelpers; @@ -6,18 +7,118 @@ namespace TombLib.Scripting.Lua.Resources { internal static class LuaEditorColorPalette { - public static readonly Brush MutedTextBrush = CreateFrozenBrush("#8C8C8C"); - public static readonly Brush MiscBrush = CreateFrozenBrush("#C8C8C8"); - public static readonly Brush MethodBrush = CreateFrozenBrush("#DCDCAA"); - public static readonly Brush VariableBrush = CreateFrozenBrush("#9CDCFE"); - public static readonly Brush PropertyBrush = CreateFrozenBrush("#4FC1FF"); - public static readonly Brush TypeBrush = CreateFrozenBrush("#4EC9B0"); - public static readonly Brush KeywordBrush = CreateFrozenBrush("#C586C0"); - public static readonly Brush ConstantBrush = CreateFrozenBrush("#B5CEA8"); - public static readonly Brush FileBrush = CreateFrozenBrush("#D7BA7D"); - - public static readonly SolidColorBrush SignatureParamDocForeground = CreateFrozenBrush(Color.FromRgb(180, 180, 180)); - public static readonly SolidColorBrush SignatureActiveParamForeground = CreateFrozenBrush(Color.FromRgb(86, 180, 235)); - public static readonly SolidColorBrush SignatureForeground = TextEditorColorPalette.ToolTipForeground; + public static LuaThemeBrushSet Create(LuaTheme theme) + { + LuaTheme effectiveTheme = (theme ?? new LuaTheme()).Normalize(ConfigurationDefaults.SelectedThemeName); + LuaThemeSemanticColors semanticColors = effectiveTheme.SemanticColors; + + return new LuaThemeBrushSet( + effectiveTheme.Name, + CreateBrush(effectiveTheme.EditorBackground, "#202020"), + CreateBrush(effectiveTheme.EditorForeground, "Gainsboro"), + CreateBrush(semanticColors.MutedText, "#8C8C8C"), + CreateBrush(semanticColors.Misc, "#C8C8C8"), + CreateBrush(semanticColors.Method, "#DCDCAA"), + CreateBrush(semanticColors.Variable, "#9CDCFE"), + CreateBrush(semanticColors.Property, "#4FC1FF"), + CreateBrush(semanticColors.Type, "#4EC9B0"), + CreateBrush(semanticColors.Keyword, "#C586C0"), + CreateBrush(semanticColors.Constant, "#B5CEA8"), + CreateBrush(semanticColors.File, "#D7BA7D"), + CreateBrush(semanticColors.SignatureParameterDocumentation, "#B4B4B4"), + CreateBrush(semanticColors.SignatureActiveParameter, "#56B4EB"), + CreateBrush(semanticColors.SignatureText, ColorToString(TextEditorColorPalette.ToolTipForeground.Color))); + } + + private static SolidColorBrush CreateBrush(string colorValue, string fallbackColorValue) + { + try + { + string effectiveColorValue = string.IsNullOrWhiteSpace(colorValue) + ? fallbackColorValue + : colorValue; + + return CreateFrozenBrush(effectiveColorValue); + } + catch + { + return CreateFrozenBrush(fallbackColorValue); + } + } + + private static string ColorToString(Color color) + => $"#{color.R:X2}{color.G:X2}{color.B:X2}"; + } + + internal sealed class LuaThemeBrushSet + { + public LuaThemeBrushSet( + string themeName, + SolidColorBrush editorBackground, + SolidColorBrush editorForeground, + SolidColorBrush mutedText, + SolidColorBrush misc, + SolidColorBrush method, + SolidColorBrush variable, + SolidColorBrush property, + SolidColorBrush type, + SolidColorBrush keyword, + SolidColorBrush constant, + SolidColorBrush file, + SolidColorBrush signatureParamDoc, + SolidColorBrush signatureActiveParam, + SolidColorBrush signatureForeground) + { + ThemeName = themeName; + EditorBackground = editorBackground; + EditorForeground = editorForeground; + MutedTextBrush = mutedText; + MiscBrush = misc; + MethodBrush = method; + VariableBrush = variable; + PropertyBrush = property; + TypeBrush = type; + KeywordBrush = keyword; + ConstantBrush = constant; + FileBrush = file; + SignatureParamDocForeground = signatureParamDoc; + SignatureActiveParamForeground = signatureActiveParam; + SignatureForeground = signatureForeground; + } + + public string ThemeName { get; } + public SolidColorBrush EditorBackground { get; } + public SolidColorBrush EditorForeground { get; } + public SolidColorBrush MutedTextBrush { get; } + public SolidColorBrush MiscBrush { get; } + public SolidColorBrush MethodBrush { get; } + public SolidColorBrush VariableBrush { get; } + public SolidColorBrush PropertyBrush { get; } + public SolidColorBrush TypeBrush { get; } + public SolidColorBrush KeywordBrush { get; } + public SolidColorBrush ConstantBrush { get; } + public SolidColorBrush FileBrush { get; } + public SolidColorBrush SignatureParamDocForeground { get; } + public SolidColorBrush SignatureActiveParamForeground { get; } + public SolidColorBrush SignatureForeground { get; } + + public Brush GetCompletionItemBrush(Objects.LuaCompletionIconKind kind) + { + return kind switch + { + Objects.LuaCompletionIconKind.Variable => VariableBrush, + Objects.LuaCompletionIconKind.Field => PropertyBrush, + Objects.LuaCompletionIconKind.Method => MethodBrush, + Objects.LuaCompletionIconKind.Property => PropertyBrush, + Objects.LuaCompletionIconKind.Class => TypeBrush, + Objects.LuaCompletionIconKind.Keyword => KeywordBrush, + Objects.LuaCompletionIconKind.Constant => ConstantBrush, + Objects.LuaCompletionIconKind.Parameter => VariableBrush, + Objects.LuaCompletionIconKind.Namespace => TypeBrush, + Objects.LuaCompletionIconKind.File => FileBrush, + Objects.LuaCompletionIconKind.Folder => FileBrush, + _ => MiscBrush + }; + } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs new file mode 100644 index 0000000000..44761fc0be --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using TombLib.Scripting.Highlighting; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.Resources +{ + public static class LuaThemeRepository + { + private static readonly Lazy Catalog = new Lazy(LoadCatalog); + + public static IReadOnlyList GetAvailableThemes() + => Catalog.Value.Themes; + + public static string ResolveThemeName(string themeName) + { + LuaTheme theme = GetTheme(themeName); + return theme.Name; + } + + public static LuaTheme GetTheme(string themeName) + { + LuaThemeCatalog catalog = Catalog.Value; + + if (!string.IsNullOrWhiteSpace(themeName) + && catalog.ThemesByLookupName.TryGetValue(themeName, out LuaTheme? theme) + && theme is not null) + { + return theme; + } + + return catalog.DefaultTheme; + } + + private static LuaThemeCatalog LoadCatalog() + { + var themes = new List(); + string themesDirectory = DefaultPaths.LuaThemeConfigsDirectory; + var serializerOptions = new JsonSerializerOptions + { + AllowTrailingCommas = true, + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip + }; + + if (Directory.Exists(themesDirectory)) + { + foreach (string filePath in Directory.GetFiles(themesDirectory, "*.json", SearchOption.TopDirectoryOnly)) + { + try + { + string fileContent = File.ReadAllText(filePath); + LuaTheme? theme = JsonSerializer.Deserialize(fileContent, serializerOptions); + + if (theme is not null) + themes.Add(theme.Normalize(Path.GetFileNameWithoutExtension(filePath))); + } + catch + { + } + } + } + + if (themes.Count == 0) + themes.Add(CreateFallbackTheme()); + + var orderedThemes = themes + .OrderByDescending(theme => string.Equals(theme.Name, ConfigurationDefaults.SelectedThemeName, StringComparison.OrdinalIgnoreCase)) + .ThenBy(theme => theme.Name, StringComparer.OrdinalIgnoreCase) + .ToList(); + + var themesByLookupName = new Dictionary(StringComparer.OrdinalIgnoreCase); + + for (int i = 0; i < orderedThemes.Count; i++) + { + LuaTheme theme = orderedThemes[i]; + AddLookupName(themesByLookupName, theme.Name, theme); + + for (int aliasIndex = 0; aliasIndex < theme.Aliases.Count; aliasIndex++) + AddLookupName(themesByLookupName, theme.Aliases[aliasIndex], theme); + } + + LuaTheme defaultTheme = themesByLookupName.TryGetValue(ConfigurationDefaults.SelectedThemeName, out LuaTheme? configuredTheme) + && configuredTheme is not null + ? configuredTheme + : orderedThemes[0]; + + return new LuaThemeCatalog(orderedThemes, themesByLookupName, defaultTheme); + } + + private static void AddLookupName(IDictionary themesByLookupName, string lookupName, LuaTheme theme) + { + if (string.IsNullOrWhiteSpace(lookupName) || themesByLookupName.ContainsKey(lookupName)) + return; + + themesByLookupName[lookupName] = theme; + } + + private static LuaTheme CreateFallbackTheme() + { + return new LuaTheme + { + Name = ConfigurationDefaults.SelectedThemeName, + Aliases = new List { "VS15", "VSCode", "Dark+" }, + EditorBackground = "#202020", + EditorForeground = "#DCDCDC", + TextMateTheme = new TextMateTokenTheme + { + Rules = new List + { + new TextMateTokenThemeRule { Scope = "comment", Foreground = "#6A9955" }, + new TextMateTokenThemeRule { Scope = "string", Foreground = "#CE9178" }, + new TextMateTokenThemeRule { Scope = "constant.numeric, constant.character.escape, constant.language", Foreground = "#B5CEA8" }, + new TextMateTokenThemeRule { Scope = "keyword, storage", Foreground = "#C586C0" }, + new TextMateTokenThemeRule { Scope = "keyword.operator", Foreground = "#D4D4D4" }, + new TextMateTokenThemeRule { Scope = "entity.name.function, support.function, support.function.library, support.function.any-method", Foreground = "#DCDCAA" }, + new TextMateTokenThemeRule { Scope = "entity.name.class, support.class, support.type, storage.type.generic", Foreground = "#4EC9B0" }, + new TextMateTokenThemeRule { Scope = "variable.parameter, entity.other.attribute", Foreground = "#9CDCFE" }, + new TextMateTokenThemeRule { Scope = "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", Foreground = "#569CD6" } + } + } + }.Normalize(ConfigurationDefaults.SelectedThemeName); + } + + private sealed class LuaThemeCatalog + { + public LuaThemeCatalog(IReadOnlyList themes, IReadOnlyDictionary themesByLookupName, LuaTheme defaultTheme) + { + Themes = themes; + ThemesByLookupName = themesByLookupName; + DefaultTheme = defaultTheme; + } + + public IReadOnlyList Themes { get; } + public IReadOnlyDictionary ThemesByLookupName { get; } + public LuaTheme DefaultTheme { get; } + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index 9a9086cc57..e059239f18 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -40,10 +40,7 @@ - - PreserveNewest - - + PreserveNewest diff --git a/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs index e79c7b2a18..2f7d852f7d 100644 --- a/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs +++ b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs @@ -11,24 +11,28 @@ namespace TombLib.Scripting.Highlighting { public static class LuaTextMateSyntaxHighlighting { - private static readonly Lazy GrammarState = new Lazy(LoadGrammarState); + private static readonly Lazy GrammarState = new Lazy(LoadGrammarState); + private static readonly TextMateTokenTheme DefaultTheme = CreateDefaultTheme(); public static bool TryInstall(TextEditor editor, out LuaTextMateInstallation installation) + => TryInstall(editor, DefaultTheme, out installation); + + public static bool TryInstall(TextEditor editor, TextMateTokenTheme theme, out LuaTextMateInstallation installation) { installation = null; if (editor?.Document is null) return false; - LuaTextMateGrammarState grammarState = GrammarState.Value; + IGrammar grammar = GrammarState.Value; - if (grammarState?.Grammar is null || grammarState.Theme is null) + if (grammar is null) return false; var documentLines = new TextMateDocumentLineList(editor.Document); var model = new TMModel(documentLines); - model.SetGrammar(grammarState.Grammar); - var styleResolver = new TextMateThemeStyleResolver(grammarState.Theme); + model.SetGrammar(grammar); + var styleResolver = new TextMateThemeStyleResolver(theme ?? DefaultTheme); var transformer = new TextMateColorizingTransformer(editor.TextArea.TextView, model, styleResolver); editor.TextArea.TextView.LineTransformers.Add(transformer); @@ -36,7 +40,7 @@ public static bool TryInstall(TextEditor editor, out LuaTextMateInstallation ins return true; } - private static LuaTextMateGrammarState LoadGrammarState() + private static IGrammar LoadGrammarState() { string grammarFilePath = Path.Combine(AppContext.BaseDirectory, "Configs", "TextEditors", "Grammars", "Lua", "lua.tmLanguage.json"); @@ -44,24 +48,26 @@ private static LuaTextMateGrammarState LoadGrammarState() return null; var registry = new Registry(new RegistryOptions(ThemeName.DarkPlus)); - IGrammar grammar = registry.LoadGrammarFromPathSync(grammarFilePath, 0, new Dictionary()); - Theme theme = registry.GetTheme(); - - return grammar is null || theme is null - ? null - : new LuaTextMateGrammarState(grammar, theme); + return registry.LoadGrammarFromPathSync(grammarFilePath, 0, new Dictionary()); } - private sealed class LuaTextMateGrammarState + private static TextMateTokenTheme CreateDefaultTheme() { - public LuaTextMateGrammarState(IGrammar grammar, Theme theme) + return new TextMateTokenTheme { - Grammar = grammar; - Theme = theme; - } - - public IGrammar Grammar { get; } - public Theme Theme { get; } + Rules = new List + { + new TextMateTokenThemeRule { Scope = "comment", Foreground = "#6A9955" }, + new TextMateTokenThemeRule { Scope = "string", Foreground = "#CE9178" }, + new TextMateTokenThemeRule { Scope = "constant.numeric, constant.character.escape, constant.language", Foreground = "#B5CEA8" }, + new TextMateTokenThemeRule { Scope = "keyword, storage", Foreground = "#C586C0" }, + new TextMateTokenThemeRule { Scope = "keyword.operator", Foreground = "#D4D4D4" }, + new TextMateTokenThemeRule { Scope = "entity.name.function, support.function, support.function.library, support.function.any-method", Foreground = "#DCDCAA" }, + new TextMateTokenThemeRule { Scope = "entity.name.class, support.class, support.type, storage.type.generic", Foreground = "#4EC9B0" }, + new TextMateTokenThemeRule { Scope = "variable.parameter, entity.other.attribute", Foreground = "#9CDCFE" }, + new TextMateTokenThemeRule { Scope = "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", Foreground = "#569CD6" } + } + }; } } diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs index 19a373302b..d7b79815f4 100644 --- a/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateThemeStyleResolver.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Windows; using System.Windows.Media; -using TextMateSharp.Themes; -using TextMateFontStyle = TextMateSharp.Themes.FontStyle; using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Highlighting @@ -13,11 +11,16 @@ internal sealed class TextMateThemeStyleResolver private static readonly TextDecorationCollection UnderlineDecorations = CreateTextDecorations(TextDecorations.Underline); private static readonly TextDecorationCollection StrikethroughDecorations = CreateTextDecorations(TextDecorations.Strikethrough); - private readonly Theme _theme; + private readonly List _rules; private readonly Dictionary _cache = new Dictionary(StringComparer.Ordinal); - public TextMateThemeStyleResolver(Theme theme) - => _theme = theme ?? throw new ArgumentNullException(nameof(theme)); + public TextMateThemeStyleResolver(TextMateTokenTheme theme) + { + if (theme is null) + throw new ArgumentNullException(nameof(theme)); + + _rules = CreateRules(theme); + } public TextMateHighlightingStyle Resolve(IList scopes) { @@ -29,60 +32,169 @@ public TextMateHighlightingStyle Resolve(IList scopes) if (_cache.TryGetValue(cacheKey, out TextMateHighlightingStyle cachedStyle)) return cachedStyle; - int foreground = 0; - TextMateFontStyle fontStyle = TextMateFontStyle.NotSet; - TextDecorationCollection textDecorations = null; + Brush foreground = null; + bool? isBold = null; + bool? isItalic = null; + bool? isUnderline = null; + bool? isStrikethrough = null; + + var matches = new List(); + + for (int i = 0; i < _rules.Count; i++) + { + int score = _rules[i].GetMatchScore(scopes); + + if (score >= 0) + matches.Add(new RuleMatch(_rules[i], score)); + } - foreach (ThemeTrieElementRule rule in _theme.Match(scopes)) + matches.Sort((left, right) => right.Score.CompareTo(left.Score)); + + for (int i = 0; i < matches.Count; i++) { - if (foreground == 0 && rule.foreground > 0) - foreground = rule.foreground; + ParsedThemeRule rule = matches[i].Rule; + + if (foreground is null && rule.Foreground is not null) + foreground = rule.Foreground; - if (fontStyle == TextMateFontStyle.NotSet && rule.fontStyle != TextMateFontStyle.NotSet) - fontStyle = rule.fontStyle; + if (!isBold.HasValue && rule.IsBold.HasValue) + isBold = rule.IsBold.Value; - if (foreground > 0 && fontStyle != TextMateFontStyle.NotSet) + if (!isItalic.HasValue && rule.IsItalic.HasValue) + isItalic = rule.IsItalic.Value; + + if (!isUnderline.HasValue && rule.IsUnderline.HasValue) + isUnderline = rule.IsUnderline.Value; + + if (!isStrikethrough.HasValue && rule.IsStrikethrough.HasValue) + isStrikethrough = rule.IsStrikethrough.Value; + + if (foreground is not null + && isBold.HasValue + && isItalic.HasValue + && isUnderline.HasValue + && isStrikethrough.HasValue) break; } - if (fontStyle == TextMateFontStyle.NotSet) - fontStyle = TextMateFontStyle.None; + TextDecorationCollection textDecorations = CreateTextDecorations(isUnderline ?? false, isStrikethrough ?? false); + + TextMateHighlightingStyle style = new TextMateHighlightingStyle( + foreground, + isBold ?? false, + isItalic ?? false, + textDecorations); + + _cache[cacheKey] = style; + return style; + } + + private static List CreateRules(TextMateTokenTheme theme) + { + var rules = new List(); + + if (theme.Rules is null) + return rules; - if ((fontStyle & TextMateFontStyle.Underline) == TextMateFontStyle.Underline - && (fontStyle & TextMateFontStyle.Strikethrough) == TextMateFontStyle.Strikethrough) + for (int i = 0; i < theme.Rules.Count; i++) { - textDecorations = new TextDecorationCollection(); + TextMateTokenThemeRule rawRule = theme.Rules[i]; - foreach (TextDecoration decoration in UnderlineDecorations) - textDecorations.Add(decoration); + if (rawRule is null || string.IsNullOrWhiteSpace(rawRule.Scope)) + continue; - foreach (TextDecoration decoration in StrikethroughDecorations) - textDecorations.Add(decoration); + string[] selectors = rawRule.Scope.Split(','); - textDecorations.Freeze(); + for (int selectorIndex = 0; selectorIndex < selectors.Length; selectorIndex++) + selectors[selectorIndex] = selectors[selectorIndex].Trim(); + + Brush foreground = null; + + if (!string.IsNullOrWhiteSpace(rawRule.Foreground)) + { + try + { + foreground = CreateFrozenBrush(rawRule.Foreground); + } + catch + { + foreground = null; + } + } + + ParseFontStyle(rawRule.FontStyle, out bool? isBold, out bool? isItalic, out bool? isUnderline, out bool? isStrikethrough); + + rules.Add(new ParsedThemeRule(selectors, foreground, isBold, isItalic, isUnderline, isStrikethrough)); } - else if ((fontStyle & TextMateFontStyle.Underline) == TextMateFontStyle.Underline) + + return rules; + } + + private static void ParseFontStyle(string fontStyleValue, out bool? isBold, out bool? isItalic, out bool? isUnderline, out bool? isStrikethrough) + { + isBold = null; + isItalic = null; + isUnderline = null; + isStrikethrough = null; + + if (string.IsNullOrWhiteSpace(fontStyleValue)) + return; + + string[] parts = fontStyleValue.Split(' ', StringSplitOptions.RemoveEmptyEntries); + + for (int i = 0; i < parts.Length; i++) { - textDecorations = UnderlineDecorations; + switch (parts[i].Trim()) + { + case "bold": + isBold = true; + break; + + case "italic": + isItalic = true; + break; + + case "underline": + isUnderline = true; + break; + + case "strikethrough": + isStrikethrough = true; + break; + + case "none": + isBold = false; + isItalic = false; + isUnderline = false; + isStrikethrough = false; + break; + } } - else if ((fontStyle & TextMateFontStyle.Strikethrough) == TextMateFontStyle.Strikethrough) + } + + private static TextDecorationCollection CreateTextDecorations(bool isUnderline, bool isStrikethrough) + { + if (isUnderline && isStrikethrough) { - textDecorations = StrikethroughDecorations; + var decorations = new TextDecorationCollection(); + + foreach (TextDecoration decoration in UnderlineDecorations) + decorations.Add(decoration); + + foreach (TextDecoration decoration in StrikethroughDecorations) + decorations.Add(decoration); + + decorations.Freeze(); + return decorations; } - string foregroundColor = foreground > 0 ? _theme.GetColor(foreground) : null; - Brush brush = !string.IsNullOrWhiteSpace(foregroundColor) - ? CreateFrozenBrush(foregroundColor) - : null; + if (isUnderline) + return UnderlineDecorations; - TextMateHighlightingStyle style = new TextMateHighlightingStyle( - brush, - (fontStyle & TextMateFontStyle.Bold) == TextMateFontStyle.Bold, - (fontStyle & TextMateFontStyle.Italic) == TextMateFontStyle.Italic, - textDecorations); + if (isStrikethrough) + return StrikethroughDecorations; - _cache[cacheKey] = style; - return style; + return null; } private static TextDecorationCollection CreateTextDecorations(TextDecorationCollection source) @@ -91,5 +203,75 @@ private static TextDecorationCollection CreateTextDecorations(TextDecorationColl clone.Freeze(); return clone; } + + private sealed class ParsedThemeRule + { + private readonly string[] _selectors; + + public ParsedThemeRule(string[] selectors, Brush foreground, bool? isBold, bool? isItalic, bool? isUnderline, bool? isStrikethrough) + { + _selectors = selectors; + Foreground = foreground; + IsBold = isBold; + IsItalic = isItalic; + IsUnderline = isUnderline; + IsStrikethrough = isStrikethrough; + } + + public Brush Foreground { get; } + public bool? IsBold { get; } + public bool? IsItalic { get; } + public bool? IsUnderline { get; } + public bool? IsStrikethrough { get; } + + public int GetMatchScore(IList scopes) + { + int bestScore = -1; + + for (int selectorIndex = 0; selectorIndex < _selectors.Length; selectorIndex++) + { + string selector = _selectors[selectorIndex]; + + if (string.IsNullOrWhiteSpace(selector)) + continue; + + for (int scopeIndex = 0; scopeIndex < scopes.Count; scopeIndex++) + { + string scope = scopes[scopeIndex]; + + if (!MatchesScope(selector, scope)) + continue; + + int selectorDepth = selector.Split('.').Length; + int score = (selectorDepth * 1000) + (selector.Length * 10) + scope.Length; + + if (score > bestScore) + bestScore = score; + } + } + + return bestScore; + } + + private static bool MatchesScope(string selector, string scope) + { + if (string.Equals(scope, selector, StringComparison.Ordinal)) + return true; + + return scope.StartsWith(selector + ".", StringComparison.Ordinal); + } + } + + private readonly struct RuleMatch + { + public RuleMatch(ParsedThemeRule rule, int score) + { + Rule = rule; + Score = score; + } + + public ParsedThemeRule Rule { get; } + public int Score { get; } + } } } \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateTokenTheme.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateTokenTheme.cs new file mode 100644 index 0000000000..858617a12b --- /dev/null +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateTokenTheme.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace TombLib.Scripting.Highlighting +{ + public sealed class TextMateTokenTheme + { + public List Rules { get; set; } = new List(); + } + + public sealed class TextMateTokenThemeRule + { + public string Scope { get; set; } = string.Empty; + public string Foreground { get; set; } = string.Empty; + public string FontStyle { get; set; } = string.Empty; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaColorSchemeTests.cs b/TombLib/TombLib.Test/LuaColorSchemeTests.cs deleted file mode 100644 index f8757b255b..0000000000 --- a/TombLib/TombLib.Test/LuaColorSchemeTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -using TombLib.Scripting.Lua.Objects; - -namespace TombLib.Test; - -[TestClass] -public class LuaColorSchemeTests -{ - [TestMethod] - public void DefaultColorScheme_UsesLuaEditorDefaults() - { - var scheme = new ColorScheme(); - - Assert.AreEqual("#202020", scheme.Background); - Assert.AreEqual("Gainsboro", scheme.Foreground); - Assert.AreEqual("#6A9955", scheme.Comments.HtmlColor); - Assert.AreEqual("#569CD6", scheme.Values.HtmlColor); - Assert.AreEqual("#569CD6", scheme.Statements.HtmlColor); - Assert.AreEqual("Gainsboro", scheme.Operators.HtmlColor); - Assert.AreEqual("#569CD6", scheme.SpecialOperators.HtmlColor); - } -} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs b/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs new file mode 100644 index 0000000000..e3bad2f482 --- /dev/null +++ b/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs @@ -0,0 +1,57 @@ +using System.Linq; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Resources; + +namespace TombLib.Test; + +[TestClass] +public class LuaThemeConfigurationTests +{ + [TestMethod] + public void DefaultConfiguration_UsesBundledVsCodeDarkTheme() + { + var config = new LuaEditorConfiguration(); + + Assert.AreEqual("VSCode Dark+", config.SelectedThemeName); + Assert.AreEqual("VSCode Dark+", config.Theme.Name); + Assert.AreEqual("#202020", config.Theme.EditorBackground); + Assert.AreEqual("#DCDCDC", config.Theme.EditorForeground); + Assert.IsTrue(config.Theme.TextMateTheme.Rules.Count > 0); + } + + [TestMethod] + public void LegacyVs15Alias_MapsToVsCodeDarkTheme() + { + var config = new LuaEditorConfiguration + { + SelectedThemeName = "VS15" + }; + + Assert.AreEqual("VSCode Dark+", config.SelectedThemeName); + Assert.AreEqual("VSCode Dark+", config.Theme.Name); + } + + [TestMethod] + public void SwitchingTheme_LoadsBundledPreset() + { + var config = new LuaEditorConfiguration + { + SelectedThemeName = "Visual Studio 15" + }; + + Assert.AreEqual("Visual Studio 2015", config.SelectedThemeName); + Assert.AreEqual("Visual Studio 2015", config.Theme.Name); + Assert.AreEqual("#1E1E1E", config.Theme.EditorBackground); + Assert.AreEqual("#DCDCDC", config.Theme.EditorForeground); + } + + [TestMethod] + public void Repository_ExposesBundledThemes() + { + string[] themeNames = LuaThemeRepository.GetAvailableThemes().Select(theme => theme.Name).ToArray(); + + CollectionAssert.Contains(themeNames, "VSCode Light+"); + CollectionAssert.Contains(themeNames, "NG_CENTER"); + CollectionAssert.Contains(themeNames, "Tomorrow Night"); + } +} \ No newline at end of file From 1eaacc67cb9d898abfe2488c1a9a7e8fa7d2a998 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 14:46:05 +0100 Subject: [PATCH 08/34] Fix hover definition issues --- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 13 +++++++-- .../Utils/LuaEditorInteractionRules.cs | 22 +++++++++++++++ .../LuaEditorInteractionRulesTests.cs | 28 +++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index c913feea62..72ee330c46 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -36,6 +36,12 @@ protected override async void HandleMouseHover(MouseEventArgs e) return; } + if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, hoveredOffset, out int hoverOffset)) + { + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + return; + } + if (!IsIntellisenseAvailable()) { ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); @@ -43,7 +49,7 @@ protected override async void HandleMouseHover(MouseEventArgs e) return; } - string hoveredWord = GetWordFromOffset(hoveredOffset); + string hoveredWord = GetWordFromOffset(hoverOffset); if (string.IsNullOrWhiteSpace(hoveredWord)) { @@ -57,14 +63,15 @@ protected override async void HandleMouseHover(MouseEventArgs e) try { - LuaHoverInfo? hoverInfo = await RequestHoverAsync(hoveredOffset, cancellationToken).ConfigureAwait(true); + LuaHoverInfo? hoverInfo = await RequestHoverAsync(hoverOffset, cancellationToken).ConfigureAwait(true); if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) return; int currentHoveredOffset = GetOffsetFromPoint(Mouse.GetPosition(this)); - if (currentHoveredOffset != hoveredOffset) + if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, currentHoveredOffset, out int currentHoverOffset) + || currentHoverOffset != hoverOffset) return; ShowBestHoverToolTip(hoverInfo, hasDiagnostic, diagnosticMessage, diagnosticSeverity); diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs index de0cff9bb3..ffaa5b5cea 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -13,6 +13,28 @@ public static bool CanRequestHover(TextDocument? document, int offset, bool isCo return !IsInsideCommentOrString(document, offset); } + public static bool TryGetHoverOffset(TextDocument? document, int offset, out int hoverOffset) + { + hoverOffset = 0; + + if (document is null || document.TextLength == 0) + return false; + + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + + if (safeOffset >= document.TextLength) + return false; + + if (IsInsideCommentOrString(document, safeOffset)) + return false; + + if (!LuaLineParser.IsIdentifierCharacter(document.GetCharAt(safeOffset))) + return false; + + hoverOffset = safeOffset; + return true; + } + public static bool IsValidAutocompleteContext(TextDocument? document, int offset, char? triggerCharacter) { if (offset <= 0 || document is null || document.TextLength == 0) diff --git a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs index 2c55412dd9..86eedbf169 100644 --- a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs +++ b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs @@ -87,6 +87,34 @@ public void CanRequestHover_BlocksCommentText() Assert.IsFalse(result); } + [TestMethod] + public void TryGetHoverOffset_ReturnsOffsetWhenPointerIsOnIdentifierText() + { + const string identifier = "targetValue"; + string text = "return " + identifier; + var document = CreateDocument(text); + int identifierStart = text.IndexOf(identifier, StringComparison.Ordinal); + int probeOffset = identifierStart + 2; + + bool result = LuaEditorInteractionRules.TryGetHoverOffset(document, probeOffset, out int hoverOffset); + + Assert.IsTrue(result); + Assert.AreEqual(probeOffset, hoverOffset); + } + + [TestMethod] + public void TryGetHoverOffset_BlocksTrailingWhitespaceAfterIdentifier() + { + const string identifier = "targetValue"; + string text = "return " + identifier; + var document = CreateDocument(text); + int probeOffset = document.TextLength; + + bool result = LuaEditorInteractionRules.TryGetHoverOffset(document, probeOffset, out _); + + Assert.IsFalse(result); + } + [TestMethod] public void TryGetDefinitionStartOffset_ReturnsWordStartFromInsideIdentifier() { From 4f5807a390da991cd76a01f23daa6544378074c3 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 18:29:38 +0100 Subject: [PATCH 09/34] Cleanups and adjustments --- .../Settings/LuaSettingsControl.cs | 2 +- .../Grammars/Lua/lua.tmLanguage.json | 2 +- .../TextEditors/Themes/Lua/Monokai.json | 5 +- .../TextEditors/Themes/Lua/NG_CENTER.json | 5 +- .../TextEditors/Themes/Lua/Obsidian.json | 5 +- .../Themes/Lua/SharpLuaClassic.json | 38 ++++++ .../TextEditors/Themes/Lua/Tomorrow.json | 37 +++++ .../TextEditors/Themes/Lua/TomorrowNight.json | 53 ++++---- .../Themes/Lua/VSCodeDarkPlus.json | 5 +- .../Themes/Lua/VSCodeLightPlus.json | 5 +- .../Themes/Lua/VisualStudio15.json | 5 +- .../LuaSemanticTokensColorizer.cs | 27 ++-- .../TombLib.Scripting.Lua/Objects/LuaTheme.cs | 59 ++++---- .../Resources/ConfigurationDefaults.cs | 2 +- .../Resources/LuaBuiltInThemes.cs | 57 ++++++++ .../Resources/LuaEditorColorPalette.cs | 30 +++-- .../Resources/LuaThemeRepository.cs | 28 +--- .../LuaBuiltInTextMateThemeDefaults.cs | 47 +++++++ .../LuaTextMateSyntaxHighlighting.cs | 20 +-- .../LuaThemeConfigurationTests.cs | 126 +++++++++++++++++- 20 files changed, 412 insertions(+), 146 deletions(-) create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/SharpLuaClassic.json create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Tomorrow.json create mode 100644 TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs create mode 100644 TombLib/TombLib.Scripting/Highlighting/LuaBuiltInTextMateThemeDefaults.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs index e7ebaf2a9f..c4f01d32de 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Settings/LuaSettingsControl.cs @@ -23,7 +23,7 @@ internal partial class LuaSettingsControl : UserControl + "function Weapon:new(name)\n" + " local damage = math.max(levelName and 1 or 0, 1)\n" + " self.name = name\n" - + " return damage\n" + + " return damage, \"mods\\\\ten\\tpreview\", true, TEN\n" + "end"; private static readonly string[] PreviewLines = PreviewText.Replace("\r", string.Empty).Split('\n'); diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json index a2c41e611a..0d30a41f39 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Grammars/Lua/lua.tmLanguage.json @@ -176,7 +176,7 @@ "name": "keyword.control.lua" }, { - "match": "(? ApplyStyle(element, style)); } } @@ -113,7 +113,7 @@ private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) { Brush? foreground = token.Type switch { - "namespace" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.TypeBrush, + "namespace" => _themeBrushSet.TypeBrush, "type" => _themeBrushSet.TypeBrush, "class" => _themeBrushSet.TypeBrush, "enum" => _themeBrushSet.TypeBrush, @@ -123,12 +123,12 @@ private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) "function" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, "method" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, "parameter" => _themeBrushSet.VariableBrush, - "property" => _themeBrushSet.VariableBrush, + "property" => _themeBrushSet.PropertyBrush, "event" => _themeBrushSet.VariableBrush, "enumMember" => _themeBrushSet.ConstantBrush, "decorator" => _themeBrushSet.KeywordBrush, "macro" => _themeBrushSet.KeywordBrush, - "variable" => ResolveVariableBrush(token), + "variable" => token.HasModifier("global") ? _themeBrushSet.PropertyBrush : _themeBrushSet.VariableBrush, _ => null }; @@ -138,17 +138,6 @@ private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) token.HasModifier("deprecated") ? DeprecatedDecorations : null); } - private Brush? ResolveVariableBrush(LuaSemanticToken token) - { - if (token.HasModifier("defaultLibrary")) - return _themeBrushSet.TypeBrush; - - if (token.HasModifier("global")) - return _themeBrushSet.PropertyBrush; - - return null; - } - private static void ApplyStyle(VisualLineElement element, LuaSemanticTokenStyle style) { VisualLineElementTextRunProperties properties = element.TextRunProperties; diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs index ef2bc068ed..de599899a8 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using TombLib.Scripting.Highlighting; +using TombLib.Scripting.Lua.Resources; namespace TombLib.Scripting.Lua.Objects { @@ -7,8 +8,8 @@ public sealed class LuaTheme { public string Name { get; set; } = string.Empty; public List Aliases { get; set; } = new List(); - public string EditorBackground { get; set; } = "#202020"; - public string EditorForeground { get; set; } = "Gainsboro"; + public string EditorBackground { get; set; } = LuaBuiltInThemes.DefaultEditorBackground; + public string EditorForeground { get; set; } = LuaBuiltInThemes.DefaultEditorForeground; public TextMateTokenTheme TextMateTheme { get; set; } = new TextMateTokenTheme(); public LuaThemeSemanticColors SemanticColors { get; set; } = new LuaThemeSemanticColors(); @@ -18,10 +19,10 @@ public LuaTheme Normalize(string fallbackName) Name = fallbackName; if (string.IsNullOrWhiteSpace(EditorBackground)) - EditorBackground = "#202020"; + EditorBackground = LuaBuiltInThemes.DefaultEditorBackground; if (string.IsNullOrWhiteSpace(EditorForeground)) - EditorForeground = "Gainsboro"; + EditorForeground = LuaBuiltInThemes.DefaultEditorForeground; Aliases ??= new List(); TextMateTheme ??= new TextMateTokenTheme(); @@ -34,33 +35,35 @@ public LuaTheme Normalize(string fallbackName) public sealed class LuaThemeSemanticColors { - public string MutedText { get; set; } = "#8C8C8C"; - public string Misc { get; set; } = "#C8C8C8"; - public string Method { get; set; } = "#DCDCAA"; - public string Variable { get; set; } = "#9CDCFE"; - public string Property { get; set; } = "#4FC1FF"; - public string Type { get; set; } = "#4EC9B0"; - public string Keyword { get; set; } = "#C586C0"; - public string Constant { get; set; } = "#B5CEA8"; - public string File { get; set; } = "#D7BA7D"; - public string SignatureParameterDocumentation { get; set; } = "#B4B4B4"; - public string SignatureActiveParameter { get; set; } = "#56B4EB"; - public string SignatureText { get; set; } = "#D4D4D4"; + public string MutedText { get; set; } = LuaBuiltInThemes.DefaultMutedText; + public string Misc { get; set; } = LuaBuiltInThemes.DefaultMisc; + public string Method { get; set; } = LuaBuiltInThemes.DefaultMethod; + public string Variable { get; set; } = LuaBuiltInThemes.DefaultVariable; + public string Property { get; set; } = LuaBuiltInThemes.DefaultProperty; + public string Type { get; set; } = LuaBuiltInThemes.DefaultType; + public string Keyword { get; set; } = LuaBuiltInThemes.DefaultKeyword; + public string LanguageConstant { get; set; } = LuaBuiltInThemes.DefaultLanguageConstant; + public string Constant { get; set; } = LuaBuiltInThemes.DefaultConstant; + public string File { get; set; } = LuaBuiltInThemes.DefaultFile; + public string SignatureParameterDocumentation { get; set; } = LuaBuiltInThemes.DefaultSignatureParameterDocumentation; + public string SignatureActiveParameter { get; set; } = LuaBuiltInThemes.DefaultSignatureActiveParameter; + public string SignatureText { get; set; } = LuaBuiltInThemes.DefaultSignatureText; public void Normalize() { - MutedText = NormalizeValue(MutedText, "#8C8C8C"); - Misc = NormalizeValue(Misc, "#C8C8C8"); - Method = NormalizeValue(Method, "#DCDCAA"); - Variable = NormalizeValue(Variable, "#9CDCFE"); - Property = NormalizeValue(Property, "#4FC1FF"); - Type = NormalizeValue(Type, "#4EC9B0"); - Keyword = NormalizeValue(Keyword, "#C586C0"); - Constant = NormalizeValue(Constant, "#B5CEA8"); - File = NormalizeValue(File, "#D7BA7D"); - SignatureParameterDocumentation = NormalizeValue(SignatureParameterDocumentation, "#B4B4B4"); - SignatureActiveParameter = NormalizeValue(SignatureActiveParameter, "#56B4EB"); - SignatureText = NormalizeValue(SignatureText, "#D4D4D4"); + MutedText = NormalizeValue(MutedText, LuaBuiltInThemes.DefaultMutedText); + Misc = NormalizeValue(Misc, LuaBuiltInThemes.DefaultMisc); + Method = NormalizeValue(Method, LuaBuiltInThemes.DefaultMethod); + Variable = NormalizeValue(Variable, LuaBuiltInThemes.DefaultVariable); + Property = NormalizeValue(Property, LuaBuiltInThemes.DefaultProperty); + Type = NormalizeValue(Type, LuaBuiltInThemes.DefaultType); + Keyword = NormalizeValue(Keyword, LuaBuiltInThemes.DefaultKeyword); + LanguageConstant = NormalizeValue(LanguageConstant, LuaBuiltInThemes.DefaultLanguageConstant); + Constant = NormalizeValue(Constant, LuaBuiltInThemes.DefaultConstant); + File = NormalizeValue(File, LuaBuiltInThemes.DefaultFile); + SignatureParameterDocumentation = NormalizeValue(SignatureParameterDocumentation, LuaBuiltInThemes.DefaultSignatureParameterDocumentation); + SignatureActiveParameter = NormalizeValue(SignatureActiveParameter, LuaBuiltInThemes.DefaultSignatureActiveParameter); + SignatureText = NormalizeValue(SignatureText, LuaBuiltInThemes.DefaultSignatureText); } private static string NormalizeValue(string value, string fallbackValue) diff --git a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs index 30e3442307..079ee4b56c 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs @@ -4,6 +4,6 @@ public struct ConfigurationDefaults { public const string ConfigurationFileName = "LuaConfiguration.xml"; - public const string SelectedThemeName = "VSCode Dark+"; + public const string SelectedThemeName = LuaBuiltInThemes.DefaultThemeName; } } diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs new file mode 100644 index 0000000000..4c27bd4c80 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs @@ -0,0 +1,57 @@ +using System.Collections.Generic; +using TombLib.Scripting.Highlighting; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.Resources +{ + internal static class LuaBuiltInThemes + { + public const string DefaultThemeName = "SharpLua Classic"; + public const string DefaultThemeAlias = "SharpLua"; + + public const string DefaultEditorBackground = LuaBuiltInTextMateThemeDefaults.DefaultEditorBackground; + public const string DefaultEditorForeground = LuaBuiltInTextMateThemeDefaults.DefaultEditorForeground; + + public const string DefaultMutedText = LuaBuiltInTextMateThemeDefaults.DefaultMutedText; + public const string DefaultMisc = LuaBuiltInTextMateThemeDefaults.DefaultMisc; + public const string DefaultMethod = LuaBuiltInTextMateThemeDefaults.DefaultMethod; + public const string DefaultVariable = LuaBuiltInTextMateThemeDefaults.DefaultVariable; + public const string DefaultProperty = LuaBuiltInTextMateThemeDefaults.DefaultProperty; + public const string DefaultType = LuaBuiltInTextMateThemeDefaults.DefaultType; + public const string DefaultKeyword = LuaBuiltInTextMateThemeDefaults.DefaultKeyword; + public const string DefaultLanguageConstant = LuaBuiltInTextMateThemeDefaults.DefaultLanguageConstant; + public const string DefaultConstant = LuaBuiltInTextMateThemeDefaults.DefaultConstant; + public const string DefaultFile = LuaBuiltInTextMateThemeDefaults.DefaultFile; + public const string DefaultSignatureParameterDocumentation = LuaBuiltInTextMateThemeDefaults.DefaultSignatureParameterDocumentation; + public const string DefaultSignatureActiveParameter = LuaBuiltInTextMateThemeDefaults.DefaultSignatureActiveParameter; + public const string DefaultSignatureText = LuaBuiltInTextMateThemeDefaults.DefaultSignatureText; + + public static LuaTheme CreateDefaultTheme() + { + return new LuaTheme + { + Name = DefaultThemeName, + Aliases = new List { DefaultThemeAlias }, + EditorBackground = DefaultEditorBackground, + EditorForeground = DefaultEditorForeground, + SemanticColors = new LuaThemeSemanticColors + { + MutedText = DefaultMutedText, + Misc = DefaultMisc, + Method = DefaultMethod, + Variable = DefaultVariable, + Property = DefaultProperty, + Type = DefaultType, + Keyword = DefaultKeyword, + LanguageConstant = DefaultLanguageConstant, + Constant = DefaultConstant, + File = DefaultFile, + SignatureParameterDocumentation = DefaultSignatureParameterDocumentation, + SignatureActiveParameter = DefaultSignatureActiveParameter, + SignatureText = DefaultSignatureText + }, + TextMateTheme = LuaBuiltInTextMateThemeDefaults.CreateDefaultTextMateTheme() + }; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs index 81a61cc0da..24bb595039 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs @@ -14,19 +14,20 @@ public static LuaThemeBrushSet Create(LuaTheme theme) return new LuaThemeBrushSet( effectiveTheme.Name, - CreateBrush(effectiveTheme.EditorBackground, "#202020"), - CreateBrush(effectiveTheme.EditorForeground, "Gainsboro"), - CreateBrush(semanticColors.MutedText, "#8C8C8C"), - CreateBrush(semanticColors.Misc, "#C8C8C8"), - CreateBrush(semanticColors.Method, "#DCDCAA"), - CreateBrush(semanticColors.Variable, "#9CDCFE"), - CreateBrush(semanticColors.Property, "#4FC1FF"), - CreateBrush(semanticColors.Type, "#4EC9B0"), - CreateBrush(semanticColors.Keyword, "#C586C0"), - CreateBrush(semanticColors.Constant, "#B5CEA8"), - CreateBrush(semanticColors.File, "#D7BA7D"), - CreateBrush(semanticColors.SignatureParameterDocumentation, "#B4B4B4"), - CreateBrush(semanticColors.SignatureActiveParameter, "#56B4EB"), + CreateBrush(effectiveTheme.EditorBackground, LuaBuiltInThemes.DefaultEditorBackground), + CreateBrush(effectiveTheme.EditorForeground, LuaBuiltInThemes.DefaultEditorForeground), + CreateBrush(semanticColors.MutedText, LuaBuiltInThemes.DefaultMutedText), + CreateBrush(semanticColors.Misc, LuaBuiltInThemes.DefaultMisc), + CreateBrush(semanticColors.Method, LuaBuiltInThemes.DefaultMethod), + CreateBrush(semanticColors.Variable, LuaBuiltInThemes.DefaultVariable), + CreateBrush(semanticColors.Property, LuaBuiltInThemes.DefaultProperty), + CreateBrush(semanticColors.Type, LuaBuiltInThemes.DefaultType), + CreateBrush(semanticColors.Keyword, LuaBuiltInThemes.DefaultKeyword), + CreateBrush(semanticColors.LanguageConstant, LuaBuiltInThemes.DefaultLanguageConstant), + CreateBrush(semanticColors.Constant, LuaBuiltInThemes.DefaultConstant), + CreateBrush(semanticColors.File, LuaBuiltInThemes.DefaultFile), + CreateBrush(semanticColors.SignatureParameterDocumentation, LuaBuiltInThemes.DefaultSignatureParameterDocumentation), + CreateBrush(semanticColors.SignatureActiveParameter, LuaBuiltInThemes.DefaultSignatureActiveParameter), CreateBrush(semanticColors.SignatureText, ColorToString(TextEditorColorPalette.ToolTipForeground.Color))); } @@ -63,6 +64,7 @@ public LuaThemeBrushSet( SolidColorBrush property, SolidColorBrush type, SolidColorBrush keyword, + SolidColorBrush languageConstant, SolidColorBrush constant, SolidColorBrush file, SolidColorBrush signatureParamDoc, @@ -79,6 +81,7 @@ public LuaThemeBrushSet( PropertyBrush = property; TypeBrush = type; KeywordBrush = keyword; + LanguageConstantBrush = languageConstant; ConstantBrush = constant; FileBrush = file; SignatureParamDocForeground = signatureParamDoc; @@ -96,6 +99,7 @@ public LuaThemeBrushSet( public SolidColorBrush PropertyBrush { get; } public SolidColorBrush TypeBrush { get; } public SolidColorBrush KeywordBrush { get; } + public SolidColorBrush LanguageConstantBrush { get; } public SolidColorBrush ConstantBrush { get; } public SolidColorBrush FileBrush { get; } public SolidColorBrush SignatureParamDocForeground { get; } diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs index 44761fc0be..0421e5e4b7 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs @@ -65,7 +65,7 @@ private static LuaThemeCatalog LoadCatalog() } if (themes.Count == 0) - themes.Add(CreateFallbackTheme()); + themes.Add(LuaBuiltInThemes.CreateDefaultTheme().Normalize(ConfigurationDefaults.SelectedThemeName)); var orderedThemes = themes .OrderByDescending(theme => string.Equals(theme.Name, ConfigurationDefaults.SelectedThemeName, StringComparison.OrdinalIgnoreCase)) @@ -99,32 +99,6 @@ private static void AddLookupName(IDictionary themesByLookupNa themesByLookupName[lookupName] = theme; } - private static LuaTheme CreateFallbackTheme() - { - return new LuaTheme - { - Name = ConfigurationDefaults.SelectedThemeName, - Aliases = new List { "VS15", "VSCode", "Dark+" }, - EditorBackground = "#202020", - EditorForeground = "#DCDCDC", - TextMateTheme = new TextMateTokenTheme - { - Rules = new List - { - new TextMateTokenThemeRule { Scope = "comment", Foreground = "#6A9955" }, - new TextMateTokenThemeRule { Scope = "string", Foreground = "#CE9178" }, - new TextMateTokenThemeRule { Scope = "constant.numeric, constant.character.escape, constant.language", Foreground = "#B5CEA8" }, - new TextMateTokenThemeRule { Scope = "keyword, storage", Foreground = "#C586C0" }, - new TextMateTokenThemeRule { Scope = "keyword.operator", Foreground = "#D4D4D4" }, - new TextMateTokenThemeRule { Scope = "entity.name.function, support.function, support.function.library, support.function.any-method", Foreground = "#DCDCAA" }, - new TextMateTokenThemeRule { Scope = "entity.name.class, support.class, support.type, storage.type.generic", Foreground = "#4EC9B0" }, - new TextMateTokenThemeRule { Scope = "variable.parameter, entity.other.attribute", Foreground = "#9CDCFE" }, - new TextMateTokenThemeRule { Scope = "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", Foreground = "#569CD6" } - } - } - }.Normalize(ConfigurationDefaults.SelectedThemeName); - } - private sealed class LuaThemeCatalog { public LuaThemeCatalog(IReadOnlyList themes, IReadOnlyDictionary themesByLookupName, LuaTheme defaultTheme) diff --git a/TombLib/TombLib.Scripting/Highlighting/LuaBuiltInTextMateThemeDefaults.cs b/TombLib/TombLib.Scripting/Highlighting/LuaBuiltInTextMateThemeDefaults.cs new file mode 100644 index 0000000000..f895db57d1 --- /dev/null +++ b/TombLib/TombLib.Scripting/Highlighting/LuaBuiltInTextMateThemeDefaults.cs @@ -0,0 +1,47 @@ +using System.Collections.Generic; + +namespace TombLib.Scripting.Highlighting +{ + public static class LuaBuiltInTextMateThemeDefaults + { + public const string DefaultEditorBackground = "#2D2D2D"; + public const string DefaultEditorForeground = "#CCCCCC"; + + public const string DefaultMutedText = "#999999"; + public const string DefaultMisc = "#CCCCCC"; + public const string DefaultMethod = "#FFCC66"; + public const string DefaultVariable = "#E6C8FF"; + public const string DefaultProperty = "#D7B8FF"; + public const string DefaultType = "#66CCCC"; + public const string DefaultKeyword = "#6699CC"; + public const string DefaultLanguageConstant = "#66CCCC"; + public const string DefaultConstant = "#99CC99"; + public const string DefaultFile = "#F99157"; + public const string DefaultSignatureParameterDocumentation = "#999999"; + public const string DefaultSignatureActiveParameter = "#FFCC66"; + public const string DefaultSignatureText = "#CCCCCC"; + + public static TextMateTokenTheme CreateDefaultTextMateTheme() + { + return new TextMateTokenTheme + { + Rules = new List + { + new TextMateTokenThemeRule { Scope = "comment", Foreground = DefaultMutedText }, + new TextMateTokenThemeRule { Scope = "string", Foreground = DefaultFile }, + new TextMateTokenThemeRule { Scope = "constant.numeric", Foreground = DefaultConstant }, + new TextMateTokenThemeRule { Scope = "constant.character.escape", Foreground = DefaultFile }, + new TextMateTokenThemeRule { Scope = "constant.language", Foreground = DefaultLanguageConstant, FontStyle = "bold" }, + new TextMateTokenThemeRule { Scope = "keyword, storage", Foreground = DefaultKeyword, FontStyle = "bold" }, + new TextMateTokenThemeRule { Scope = "keyword.control.goto, keyword.control.return, keyword.control.break", Foreground = "#CC99CC" }, + new TextMateTokenThemeRule { Scope = "keyword.control.local", Foreground = DefaultFile, FontStyle = "bold" }, + new TextMateTokenThemeRule { Scope = "entity.name.class, support.class, support.type, support.variable, variable.language.self", Foreground = DefaultType, FontStyle = "bold" }, + new TextMateTokenThemeRule { Scope = "entity.other.attribute, support.type.property-name", Foreground = DefaultProperty }, + new TextMateTokenThemeRule { Scope = "variable.parameter, variable.other.object", Foreground = DefaultVariable }, + new TextMateTokenThemeRule { Scope = "entity.name.function, support.function, support.function.library, support.function.any-method", Foreground = DefaultMethod, FontStyle = "bold" }, + new TextMateTokenThemeRule { Scope = "keyword.operator, punctuation", Foreground = DefaultMisc } + } + }; + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs index 2f7d852f7d..922aa76b0f 100644 --- a/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs +++ b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs @@ -12,7 +12,7 @@ namespace TombLib.Scripting.Highlighting public static class LuaTextMateSyntaxHighlighting { private static readonly Lazy GrammarState = new Lazy(LoadGrammarState); - private static readonly TextMateTokenTheme DefaultTheme = CreateDefaultTheme(); + private static readonly TextMateTokenTheme DefaultTheme = LuaBuiltInTextMateThemeDefaults.CreateDefaultTextMateTheme(); public static bool TryInstall(TextEditor editor, out LuaTextMateInstallation installation) => TryInstall(editor, DefaultTheme, out installation); @@ -51,24 +51,6 @@ private static IGrammar LoadGrammarState() return registry.LoadGrammarFromPathSync(grammarFilePath, 0, new Dictionary()); } - private static TextMateTokenTheme CreateDefaultTheme() - { - return new TextMateTokenTheme - { - Rules = new List - { - new TextMateTokenThemeRule { Scope = "comment", Foreground = "#6A9955" }, - new TextMateTokenThemeRule { Scope = "string", Foreground = "#CE9178" }, - new TextMateTokenThemeRule { Scope = "constant.numeric, constant.character.escape, constant.language", Foreground = "#B5CEA8" }, - new TextMateTokenThemeRule { Scope = "keyword, storage", Foreground = "#C586C0" }, - new TextMateTokenThemeRule { Scope = "keyword.operator", Foreground = "#D4D4D4" }, - new TextMateTokenThemeRule { Scope = "entity.name.function, support.function, support.function.library, support.function.any-method", Foreground = "#DCDCAA" }, - new TextMateTokenThemeRule { Scope = "entity.name.class, support.class, support.type, storage.type.generic", Foreground = "#4EC9B0" }, - new TextMateTokenThemeRule { Scope = "variable.parameter, entity.other.attribute", Foreground = "#9CDCFE" }, - new TextMateTokenThemeRule { Scope = "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", Foreground = "#569CD6" } - } - }; - } } public sealed class LuaTextMateInstallation : IDisposable diff --git a/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs b/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs index e3bad2f482..f72f15ecc5 100644 --- a/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs +++ b/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs @@ -1,6 +1,7 @@ using System.Linq; using TombLib.Scripting.Lua; using TombLib.Scripting.Lua.Resources; +using TombLib.Scripting.Highlighting; namespace TombLib.Test; @@ -8,14 +9,14 @@ namespace TombLib.Test; public class LuaThemeConfigurationTests { [TestMethod] - public void DefaultConfiguration_UsesBundledVsCodeDarkTheme() + public void DefaultConfiguration_UsesBundledSharpLuaClassicTheme() { var config = new LuaEditorConfiguration(); - Assert.AreEqual("VSCode Dark+", config.SelectedThemeName); - Assert.AreEqual("VSCode Dark+", config.Theme.Name); - Assert.AreEqual("#202020", config.Theme.EditorBackground); - Assert.AreEqual("#DCDCDC", config.Theme.EditorForeground); + Assert.AreEqual("SharpLua Classic", config.SelectedThemeName); + Assert.AreEqual("SharpLua Classic", config.Theme.Name); + Assert.AreEqual("#2D2D2D", config.Theme.EditorBackground); + Assert.AreEqual("#CCCCCC", config.Theme.EditorForeground); Assert.IsTrue(config.Theme.TextMateTheme.Rules.Count > 0); } @@ -50,8 +51,121 @@ public void Repository_ExposesBundledThemes() { string[] themeNames = LuaThemeRepository.GetAvailableThemes().Select(theme => theme.Name).ToArray(); + CollectionAssert.Contains(themeNames, "SharpLua Classic"); + CollectionAssert.Contains(themeNames, "Tomorrow"); + CollectionAssert.Contains(themeNames, "Tomorrow Night"); CollectionAssert.Contains(themeNames, "VSCode Light+"); CollectionAssert.Contains(themeNames, "NG_CENTER"); - CollectionAssert.Contains(themeNames, "Tomorrow Night"); + } + + [TestMethod] + public void SharpLuaClassicTheme_UsesEnhancedLegacyPalette() + { + var config = new LuaEditorConfiguration + { + SelectedThemeName = "SharpLua" + }; + + TextMateTokenThemeRule? classRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "entity.name.class, support.class, support.type, support.variable, variable.language.self", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? attributeRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "entity.other.attribute, support.type.property-name", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? parameterRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "variable.parameter, variable.other.object", System.StringComparison.Ordinal)); + + Assert.AreEqual("SharpLua Classic", config.SelectedThemeName); + Assert.AreEqual("#2D2D2D", config.Theme.EditorBackground); + Assert.AreEqual("#CCCCCC", config.Theme.EditorForeground); + Assert.AreEqual("#66CCCC", config.Theme.SemanticColors.Type); + Assert.AreEqual("#E6C8FF", config.Theme.SemanticColors.Variable); + Assert.AreEqual("#D7B8FF", config.Theme.SemanticColors.Property); + Assert.AreNotEqual(config.Theme.SemanticColors.Variable, config.Theme.SemanticColors.Property); + Assert.AreEqual("#66CCCC", classRule?.Foreground); + Assert.AreEqual("#D7B8FF", attributeRule?.Foreground); + Assert.AreEqual("#E6C8FF", parameterRule?.Foreground); + } + + [TestMethod] + public void VsCodeDarkTheme_SeparatesLanguageConstantsFromNumericConstants() + { + var config = new LuaEditorConfiguration + { + SelectedThemeName = "VSCode Dark+" + }; + + TextMateTokenThemeRule? numericRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.numeric", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? languageRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.language", System.StringComparison.Ordinal)); + + Assert.IsNotNull(numericRule); + Assert.IsNotNull(languageRule); + Assert.AreNotEqual(numericRule.Foreground, languageRule.Foreground); + } + + [TestMethod] + public void VsCodeDarkTheme_UsesFileAccentForEscapeSequences() + { + var config = new LuaEditorConfiguration + { + SelectedThemeName = "VSCode Dark+" + }; + + TextMateTokenThemeRule? numericRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.numeric", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? escapeRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.character.escape", System.StringComparison.Ordinal)); + + Assert.IsNotNull(numericRule); + Assert.IsNotNull(escapeRule); + Assert.AreNotEqual(numericRule.Foreground, escapeRule.Foreground); + Assert.AreEqual(config.Theme.SemanticColors.File, escapeRule.Foreground); + } + + [TestMethod] + public void TomorrowNightTheme_UsesCanonicalPalette() + { + var config = new LuaEditorConfiguration + { + SelectedThemeName = "TomorrowNight" + }; + + TextMateTokenThemeRule? stringRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "string", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? numericRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.numeric", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? languageRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.language", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? functionRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "entity.name.function, support.function, support.function.library, support.function.any-method", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? keywordRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "keyword, storage", System.StringComparison.Ordinal)); + + Assert.AreEqual("Tomorrow Night", config.SelectedThemeName); + Assert.AreEqual("#1D1F21", config.Theme.EditorBackground); + Assert.AreEqual("#C5C8C6", config.Theme.EditorForeground); + Assert.AreEqual("#81A2BE", config.Theme.SemanticColors.Method); + Assert.AreEqual("#CC6666", config.Theme.SemanticColors.Variable); + Assert.AreEqual("#F0C674", config.Theme.SemanticColors.Type); + Assert.AreEqual("#B5BD68", stringRule?.Foreground); + Assert.AreEqual("#DE935F", numericRule?.Foreground); + Assert.AreEqual("#DE935F", languageRule?.Foreground); + Assert.AreEqual("#81A2BE", functionRule?.Foreground); + Assert.AreEqual("#B294BB", keywordRule?.Foreground); + } + + [TestMethod] + public void TomorrowTheme_UsesCanonicalPalette() + { + var config = new LuaEditorConfiguration + { + SelectedThemeName = "Tomorrow Light" + }; + + TextMateTokenThemeRule? stringRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "string", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? numericRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.numeric", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? languageRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "constant.language", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? functionRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "entity.name.function, support.function, support.function.library, support.function.any-method", System.StringComparison.Ordinal)); + TextMateTokenThemeRule? keywordRule = config.Theme.TextMateTheme.Rules.FirstOrDefault(rule => string.Equals(rule.Scope, "keyword, storage", System.StringComparison.Ordinal)); + + Assert.AreEqual("Tomorrow", config.SelectedThemeName); + Assert.AreEqual("#FFFFFF", config.Theme.EditorBackground); + Assert.AreEqual("#4D4D4C", config.Theme.EditorForeground); + Assert.AreEqual("#4271AE", config.Theme.SemanticColors.Method); + Assert.AreEqual("#C82829", config.Theme.SemanticColors.Variable); + Assert.AreEqual("#C99E00", config.Theme.SemanticColors.Type); + Assert.AreEqual("#718C00", stringRule?.Foreground); + Assert.AreEqual("#F5871F", numericRule?.Foreground); + Assert.AreEqual("#F5871F", languageRule?.Foreground); + Assert.AreEqual("#4271AE", functionRule?.Foreground); + Assert.AreEqual("#8959A8", keywordRule?.Foreground); } } \ No newline at end of file From eb9d3b2491190095ede58e94b6483ad0541534b1 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 19:06:23 +0100 Subject: [PATCH 10/34] Cleanups and improvements --- .../LuaSemanticTokensColorizer.cs | 13 ++- .../LuaTextBox.Designer.cs | 47 ---------- TombLib/TombLib.Scripting.Lua/LuaTextBox.cs | 89 ------------------- .../Resources/Keywords.cs | 56 ------------ .../Resources/Patterns.cs | 11 --- 5 files changed, 12 insertions(+), 204 deletions(-) delete mode 100644 TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/LuaTextBox.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/Resources/Keywords.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/Resources/Patterns.cs diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index aa546f0ea6..68263ea124 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -128,7 +128,7 @@ private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) "enumMember" => _themeBrushSet.ConstantBrush, "decorator" => _themeBrushSet.KeywordBrush, "macro" => _themeBrushSet.KeywordBrush, - "variable" => token.HasModifier("global") ? _themeBrushSet.PropertyBrush : _themeBrushSet.VariableBrush, + "variable" => ResolveVariableBrush(token), _ => null }; @@ -138,6 +138,17 @@ private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) token.HasModifier("deprecated") ? DeprecatedDecorations : null); } + private Brush? ResolveVariableBrush(LuaSemanticToken token) + { + if (token.HasModifier("defaultLibrary")) + return _themeBrushSet.TypeBrush; + + if (token.HasModifier("global")) + return _themeBrushSet.PropertyBrush; + + return _themeBrushSet.VariableBrush; + } + private static void ApplyStyle(VisualLineElement element, LuaSemanticTokenStyle style) { VisualLineElementTextRunProperties properties = element.TextRunProperties; diff --git a/TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs b/TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs deleted file mode 100644 index a6efc6bf9b..0000000000 --- a/TombLib/TombLib.Scripting.Lua/LuaTextBox.Designer.cs +++ /dev/null @@ -1,47 +0,0 @@ -#nullable disable - -namespace TombLib.Scripting.Lua -{ - partial class LuaTextBox - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.ehTextEditor = new System.Windows.Forms.Integration.ElementHost(); - this.SuspendLayout(); - // - // ehTextEditor - // - this.ehTextEditor.Dock = System.Windows.Forms.DockStyle.Fill; - this.ehTextEditor.Location = new System.Drawing.Point(0, 0); - this.ehTextEditor.Name = "ehTextEditor"; - this.ehTextEditor.Size = new System.Drawing.Size(150, 150); - this.ehTextEditor.TabIndex = 0; - this.ehTextEditor.Text = "elementHost"; - this.ehTextEditor.Child = null; - // - // LuaTextEditor - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.ehTextEditor); - this.Name = "LuaTextEditor"; - this.ResumeLayout(false); - - } - - #endregion - - private System.Windows.Forms.Integration.ElementHost ehTextEditor; - } -} diff --git a/TombLib/TombLib.Scripting.Lua/LuaTextBox.cs b/TombLib/TombLib.Scripting.Lua/LuaTextBox.cs deleted file mode 100644 index 223b8a1fce..0000000000 --- a/TombLib/TombLib.Scripting.Lua/LuaTextBox.cs +++ /dev/null @@ -1,89 +0,0 @@ -using DarkUI.Config; -using DarkUI.Forms; -using System; -using System.ComponentModel; -using System.Windows.Forms; - -namespace TombLib.Scripting.Lua -{ - public partial class LuaTextBox : UserControl - { - private DarkTranslucentForm? _overlayForm; - private LuaEditor? _textEditor; - - public LuaEditor TextEditor => _textEditor ?? throw new InvalidOperationException("Lua editor is not initialized."); - - public LuaTextBox() - { - InitializeComponent(); - InitializeTextEditor(); - BackColor = Colors.GreyBackground; - } - - private void InitializeTextEditor() - { - if (LicenseManager.UsageMode == LicenseUsageMode.Runtime) - { - _textEditor = new LuaEditor(new Version(0, 0)); - _textEditor.AllowDrop = true; - _textEditor.WordWrap = true; - _textEditor.DragEnter += textEditor_DragEnter; - ehTextEditor.Child = _textEditor; - - _overlayForm = new DarkTranslucentForm(Colors.GreyBackground, 0.01); // 0 won't show form! - _overlayForm.AllowDrop = true; - _overlayForm.DragEnter += overlayForm_DragEnter; - _overlayForm.DragDrop += overlayForm_DragDrop; - _overlayForm.DragLeave += overlayForm_DragLeave; - } - } - - public void Paste(string text) - { - if (_textEditor is null) - return; - - _textEditor.TextArea.PerformTextInput(text); - _textEditor.Focus(); - } - - protected override void OnGotFocus(EventArgs e) - { - base.OnGotFocus(e); - - if (_textEditor is not null) - _textEditor.Focus(); - } - - private void textEditor_DragEnter(object? sender, System.Windows.DragEventArgs e) - { - if (_overlayForm is null) - return; - - _overlayForm.Show(); - _overlayForm.Location = PointToScreen(new System.Drawing.Point(0)); - _overlayForm.Size = ClientSize; - } - - private void overlayForm_DragEnter(object? sender, DragEventArgs e) => - OnDragEnter(e); - - private void overlayForm_DragDrop(object? sender, DragEventArgs e) - { - if (_overlayForm is null) - return; - - _overlayForm.Hide(); - OnDragDrop(e); - } - - private void overlayForm_DragLeave(object? sender, EventArgs e) - { - if (_overlayForm is null) - return; - - _overlayForm.Hide(); - OnDragLeave(e); - } - } -} diff --git a/TombLib/TombLib.Scripting.Lua/Resources/Keywords.cs b/TombLib/TombLib.Scripting.Lua/Resources/Keywords.cs deleted file mode 100644 index 9e1c132b95..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Resources/Keywords.cs +++ /dev/null @@ -1,56 +0,0 @@ -namespace TombLib.Scripting.Lua.Resources -{ - public static class Keywords - { - public static readonly string[] Statements = new string[] - { - "if", - "then", - "else", - "elseif", - "function", - "end", - "for", - "while", - "in", - "repeat", - "until", - "break", - "return", - "local", - "print" - }; - - public static readonly string[] Values = new string[] - { - "true", - "false", - "nil" - }; - - public static readonly string[] Operators = new string[] - { - "%", - @"\+", - @"-", - @"\*", - "/", - @"\^", - @"\=", - @"~\=", - @">", - @"<", - @":", - @"\.", - @"\[", - @"\]" - }; - - public static readonly string[] SpecialOperators = new string[] - { - "and", - "or", - "not", - }; - } -} diff --git a/TombLib/TombLib.Scripting.Lua/Resources/Patterns.cs b/TombLib/TombLib.Scripting.Lua/Resources/Patterns.cs deleted file mode 100644 index f0b14206a0..0000000000 --- a/TombLib/TombLib.Scripting.Lua/Resources/Patterns.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace TombLib.Scripting.Lua.Resources -{ - public struct Patterns - { - public static string Comments => @"--.*$"; - public static string Operators => @"(" + string.Join("|", Keywords.Operators) + @")"; - public static string SpecialOperators => @"\b(" + string.Join("|", Keywords.SpecialOperators) + @")\b"; - public static string Statements => @"\b(" + string.Join("|", Keywords.Statements) + @")\b"; - public static string Values => @"\b(" + string.Join("|", Keywords.Values) + @")\b"; - } -} From 8db72a8f9011fc4739009a553d7cf0a46c3a2663 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 20:13:36 +0100 Subject: [PATCH 11/34] Cleanups --- .../TextEditors/Themes/Lua/Monokai.json | 2 +- .../TextEditors/Themes/Lua/NG_CENTER.json | 2 +- .../TextEditors/Themes/Lua/Obsidian.json | 2 +- .../Themes/Lua/SharpLuaClassic.json | 2 +- .../TextEditors/Themes/Lua/Tomorrow.json | 2 +- .../TextEditors/Themes/Lua/TomorrowNight.json | 2 +- .../Themes/Lua/VSCodeDarkPlus.json | 2 +- .../Themes/Lua/VSCodeLightPlus.json | 2 +- .../Themes/Lua/VisualStudio15.json | 2 +- .../LuaSemanticTokensColorizer.cs | 280 ++++----- .../LuaEditor.Completion.cs | 535 +++++++++--------- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 220 +++---- .../LuaEditor.Intellisense.cs | 285 +++++----- .../LuaEditor.Navigation.cs | 123 ++-- .../LuaEditor.SemanticHighlighting.cs | 41 +- .../LuaEditor.SignatureHelp.cs | 350 ++++++------ TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 87 ++- .../LuaEditorConfiguration.cs | 50 +- TombLib/TombLib.Scripting.Lua/LuaTextBox.resx | 120 ---- .../Objects/LuaCompletionData.cs | 249 ++++---- .../Objects/LuaCompletionIconFactory.cs | 190 +++---- .../Objects/LuaCompletionIconKind.cs | 33 +- .../Objects/LuaCompletionItem.cs | 79 +-- .../Objects/LuaCompletionWindowStyle.cs | 122 ++-- .../Objects/LuaDefinitionLocation.cs | 25 +- .../Objects/LuaHoverInfo.cs | 21 +- .../Objects/LuaSemanticToken.cs | 53 +- .../Objects/LuaSignatureInfo.cs | 47 +- .../TombLib.Scripting.Lua/Objects/LuaTheme.cs | 121 ++-- .../Resources/ConfigurationDefaults.cs | 11 +- .../Resources/LuaBuiltInThemes.cs | 94 +-- .../Resources/LuaEditorColorPalette.cs | 217 ++++--- .../Resources/LuaThemeRepository.cs | 160 +++--- .../Services/ILuaIntellisenseProvider.cs | 46 +- .../TombLib.Scripting.Lua.csproj | 1 + .../Utils/LuaEditorInteractionRules.cs | 192 ++++--- .../Utils/LuaLineParser.cs | 455 +++++++-------- .../Utils/TombEngineLanguageScriptService.cs | 189 +++---- 38 files changed, 2144 insertions(+), 2270 deletions(-) delete mode 100644 TombLib/TombLib.Scripting.Lua/LuaTextBox.resx diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json index 9b7107c6e0..c823e6e601 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Monokai.json @@ -32,4 +32,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#66D9EF" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json index ba262965ae..9be0caecaf 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/NG_CENTER.json @@ -33,4 +33,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#000000", "FontStyle": "bold" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json index 43dc56fdf0..01e1152804 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Obsidian.json @@ -32,4 +32,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#668BB0" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/SharpLuaClassic.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/SharpLuaClassic.json index 02552e7a33..b1e01af470 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/SharpLuaClassic.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/SharpLuaClassic.json @@ -35,4 +35,4 @@ { "Scope": "keyword.operator, punctuation", "Foreground": "#CCCCCC" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Tomorrow.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Tomorrow.json index 12cd0825f3..0c095182dd 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Tomorrow.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/Tomorrow.json @@ -34,4 +34,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#C82829" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json index fd836743bd..8a94532609 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/TomorrowNight.json @@ -34,4 +34,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#CC6666" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json index 2f713937d3..bdf92df4eb 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeDarkPlus.json @@ -33,4 +33,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#569CD6" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json index a8c46cdfb6..23e702bc35 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VSCodeLightPlus.json @@ -33,4 +33,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#0451A5" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json index 93988e9975..eebab04d17 100644 --- a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/Themes/Lua/VisualStudio15.json @@ -33,4 +33,4 @@ { "Scope": "variable.language.self, entity.name.tag, string.tag, storage.type.annotation", "Foreground": "#569CD6" } ] } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index 68263ea124..4207fc8b65 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -1,192 +1,192 @@ +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Rendering; using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media; -using ICSharpCode.AvalonEdit.Document; -using ICSharpCode.AvalonEdit.Rendering; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Resources; -namespace TombLib.Scripting.Lua.Highlighting +namespace TombLib.Scripting.Lua.Highlighting; + +internal sealed class LuaSemanticTokensColorizer : DocumentColorizingTransformer { - internal sealed class LuaSemanticTokensColorizer : DocumentColorizingTransformer + private static readonly TextDecorationCollection DeprecatedDecorations = CreateTextDecorations(TextDecorations.Strikethrough); + + private static readonly IReadOnlyDictionary> EmptyTokensByLine = + new Dictionary>(); + + private LuaThemeBrushSet _themeBrushSet; + private readonly TextView _textView; + private IReadOnlyDictionary> _tokensByLine = EmptyTokensByLine; + + public LuaSemanticTokensColorizer(TextView textView, LuaThemeBrushSet themeBrushSet) { - private static readonly TextDecorationCollection DeprecatedDecorations = CreateTextDecorations(TextDecorations.Strikethrough); - private static readonly IReadOnlyDictionary> EmptyTokensByLine = - new Dictionary>(); + _textView = textView ?? throw new ArgumentNullException(nameof(textView)); + _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); + } - private LuaThemeBrushSet _themeBrushSet; - private readonly TextView _textView; - private IReadOnlyDictionary> _tokensByLine = EmptyTokensByLine; + public void UpdateTheme(LuaThemeBrushSet themeBrushSet) + { + _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); + _textView.Redraw(); + } - public LuaSemanticTokensColorizer(TextView textView, LuaThemeBrushSet themeBrushSet) + public void SetTokens(IReadOnlyList tokens) + { + if (tokens is null || tokens.Count == 0) { - _textView = textView ?? throw new ArgumentNullException(nameof(textView)); - _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); + ClearTokens(); + return; } - public void UpdateTheme(LuaThemeBrushSet themeBrushSet) - { - _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); - _textView.Redraw(); - } + var groupedTokens = new Dictionary>(); - public void SetTokens(IReadOnlyList tokens) + for (int i = 0; i < tokens.Count; i++) { - if (tokens is null || tokens.Count == 0) - { - ClearTokens(); - return; - } - - var groupedTokens = new Dictionary>(); + LuaSemanticToken token = tokens[i]; - for (int i = 0; i < tokens.Count; i++) + if (!groupedTokens.TryGetValue(token.Line, out List? lineTokens) || lineTokens is null) { - LuaSemanticToken token = tokens[i]; - - if (!groupedTokens.TryGetValue(token.Line, out List? lineTokens) || lineTokens is null) - { - lineTokens = new List(); - groupedTokens[token.Line] = lineTokens; - } - - lineTokens.Add(token); + lineTokens = []; + groupedTokens[token.Line] = lineTokens; } - var frozenMap = new Dictionary>(groupedTokens.Count); + lineTokens.Add(token); + } + + var frozenMap = new Dictionary>(groupedTokens.Count); - foreach (KeyValuePair> pair in groupedTokens) + foreach (KeyValuePair> pair in groupedTokens) + { + pair.Value.Sort((left, right) => { - pair.Value.Sort((left, right) => - { - int characterComparison = left.Character.CompareTo(right.Character); + int characterComparison = left.Character.CompareTo(right.Character); - if (characterComparison != 0) - return characterComparison; + if (characterComparison != 0) + return characterComparison; - return left.Length.CompareTo(right.Length); - }); + return left.Length.CompareTo(right.Length); + }); - frozenMap[pair.Key] = pair.Value; - } - - _tokensByLine = frozenMap; - _textView.Redraw(); + frozenMap[pair.Key] = pair.Value; } - public void ClearTokens() - { - if (_tokensByLine.Count == 0) - return; + _tokensByLine = frozenMap; + _textView.Redraw(); + } - _tokensByLine = EmptyTokensByLine; - _textView.Redraw(); - } + public void ClearTokens() + { + if (_tokensByLine.Count == 0) + return; - protected override void ColorizeLine(DocumentLine line) - { - if (!_tokensByLine.TryGetValue(line.LineNumber - 1, out IReadOnlyList? tokens) || tokens is null) - return; + _tokensByLine = EmptyTokensByLine; + _textView.Redraw(); + } - int lineLength = line.Length; + protected override void ColorizeLine(DocumentLine line) + { + if (!_tokensByLine.TryGetValue(line.LineNumber - 1, out IReadOnlyList? tokens) || tokens is null) + return; - for (int i = 0; i < tokens.Count; i++) - { - LuaSemanticToken token = tokens[i]; - int startIndex = Math.Max(0, Math.Min(token.Character, lineLength)); - int endIndex = Math.Max(startIndex, Math.Min(token.Character + token.Length, lineLength)); + int lineLength = line.Length; - if (endIndex <= startIndex) - continue; + for (int i = 0; i < tokens.Count; i++) + { + LuaSemanticToken token = tokens[i]; + int startIndex = Math.Max(0, Math.Min(token.Character, lineLength)); + int endIndex = Math.Max(startIndex, Math.Min(token.Character + token.Length, lineLength)); - LuaSemanticTokenStyle style = ResolveStyle(token); + if (endIndex <= startIndex) + continue; - if (!style.HasFormatting) - continue; + LuaSemanticTokenStyle style = ResolveStyle(token); - ChangeLinePart(line.Offset + startIndex, line.Offset + endIndex, element => ApplyStyle(element, style)); - } - } + if (!style.HasFormatting) + continue; - private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) - { - Brush? foreground = token.Type switch - { - "namespace" => _themeBrushSet.TypeBrush, - "type" => _themeBrushSet.TypeBrush, - "class" => _themeBrushSet.TypeBrush, - "enum" => _themeBrushSet.TypeBrush, - "interface" => _themeBrushSet.TypeBrush, - "struct" => _themeBrushSet.TypeBrush, - "typeParameter" => _themeBrushSet.TypeBrush, - "function" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, - "method" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, - "parameter" => _themeBrushSet.VariableBrush, - "property" => _themeBrushSet.PropertyBrush, - "event" => _themeBrushSet.VariableBrush, - "enumMember" => _themeBrushSet.ConstantBrush, - "decorator" => _themeBrushSet.KeywordBrush, - "macro" => _themeBrushSet.KeywordBrush, - "variable" => ResolveVariableBrush(token), - _ => null - }; - - return new LuaSemanticTokenStyle( - foreground, - token.HasModifier("declaration") && (token.Type == "function" || token.Type == "method"), - token.HasModifier("deprecated") ? DeprecatedDecorations : null); + ChangeLinePart(line.Offset + startIndex, line.Offset + endIndex, element => ApplyStyle(element, style)); } + } - private Brush? ResolveVariableBrush(LuaSemanticToken token) + private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) + { + Brush? foreground = token.Type switch { - if (token.HasModifier("defaultLibrary")) - return _themeBrushSet.TypeBrush; - - if (token.HasModifier("global")) - return _themeBrushSet.PropertyBrush; + "namespace" => _themeBrushSet.TypeBrush, + "type" => _themeBrushSet.TypeBrush, + "class" => _themeBrushSet.TypeBrush, + "enum" => _themeBrushSet.TypeBrush, + "interface" => _themeBrushSet.TypeBrush, + "struct" => _themeBrushSet.TypeBrush, + "typeParameter" => _themeBrushSet.TypeBrush, + "function" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, + "method" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, + "parameter" => _themeBrushSet.VariableBrush, + "property" => _themeBrushSet.PropertyBrush, + "event" => _themeBrushSet.VariableBrush, + "enumMember" => _themeBrushSet.ConstantBrush, + "decorator" => _themeBrushSet.KeywordBrush, + "macro" => _themeBrushSet.KeywordBrush, + "variable" => ResolveVariableBrush(token), + _ => null + }; + + return new LuaSemanticTokenStyle( + foreground, + token.HasModifier("declaration") && (token.Type == "function" || token.Type == "method"), + token.HasModifier("deprecated") ? DeprecatedDecorations : null); + } - return _themeBrushSet.VariableBrush; - } + private Brush? ResolveVariableBrush(LuaSemanticToken token) + { + if (token.HasModifier("defaultLibrary")) + return _themeBrushSet.TypeBrush; - private static void ApplyStyle(VisualLineElement element, LuaSemanticTokenStyle style) - { - VisualLineElementTextRunProperties properties = element.TextRunProperties; + if (token.HasModifier("global")) + return _themeBrushSet.PropertyBrush; - if (style.Foreground is not null) - properties.SetForegroundBrush(style.Foreground); + return _themeBrushSet.VariableBrush; + } - if (style.IsBold) - { - Typeface typeface = properties.Typeface; - properties.SetTypeface(new Typeface(typeface.FontFamily, typeface.Style, FontWeights.Bold, typeface.Stretch)); - } + private static void ApplyStyle(VisualLineElement element, LuaSemanticTokenStyle style) + { + VisualLineElementTextRunProperties properties = element.TextRunProperties; - if (style.TextDecorations is not null) - properties.SetTextDecorations(style.TextDecorations); - } + if (style.Foreground is not null) + properties.SetForegroundBrush(style.Foreground); - private static TextDecorationCollection CreateTextDecorations(TextDecorationCollection source) + if (style.IsBold) { - var clone = source.Clone(); - clone.Freeze(); - return clone; + Typeface typeface = properties.Typeface; + properties.SetTypeface(new Typeface(typeface.FontFamily, typeface.Style, FontWeights.Bold, typeface.Stretch)); } - private readonly struct LuaSemanticTokenStyle - { - public LuaSemanticTokenStyle(Brush? foreground, bool isBold, TextDecorationCollection? textDecorations) - { - Foreground = foreground; - IsBold = isBold; - TextDecorations = textDecorations; - } + if (style.TextDecorations is not null) + properties.SetTextDecorations(style.TextDecorations); + } - public Brush? Foreground { get; } - public bool IsBold { get; } - public TextDecorationCollection? TextDecorations { get; } + private static TextDecorationCollection CreateTextDecorations(TextDecorationCollection source) + { + var clone = source.Clone(); + clone.Freeze(); + return clone; + } - public bool HasFormatting => Foreground is not null || IsBold || TextDecorations is not null; + private readonly struct LuaSemanticTokenStyle + { + public LuaSemanticTokenStyle(Brush? foreground, bool isBold, TextDecorationCollection? textDecorations) + { + Foreground = foreground; + IsBold = isBold; + TextDecorations = textDecorations; } + + public Brush? Foreground { get; } + public bool IsBold { get; } + public TextDecorationCollection? TextDecorations { get; } + + public bool HasFormatting => Foreground is not null || IsBold || TextDecorations is not null; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index 093a430729..c01ef67d80 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -1,5 +1,6 @@ -using System.Collections.Generic; +using ICSharpCode.AvalonEdit.CodeCompletion; using System; +using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; @@ -12,361 +13,361 @@ using System.Windows.Interop; using System.Windows.Media; using System.Windows.Threading; -using ICSharpCode.AvalonEdit.CodeCompletion; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Utils; using TombLib.WPF; -namespace TombLib.Scripting.Lua +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor { - public sealed partial class LuaEditor - { - private const int CompletionWindowMinWidth = 420; - private const int CompletionWindowMaxWidth = 920; - private const int CompletionWindowHeight = 320; - private const double CompletionToolTipHorizontalOffset = 10.0; - private const double CompletionToolTipResolveDelayInMilliseconds = 120.0; - private const double CompletionWindowHorizontalChrome = 52.0; - private const double CompletionItemIconWidth = 24.0; - private const double CompletionItemDetailSpacing = 12.0; + private const int CompletionWindowMinWidth = 420; + private const int CompletionWindowMaxWidth = 920; + private const int CompletionWindowHeight = 320; + private const double CompletionToolTipHorizontalOffset = 10.0; + private const double CompletionToolTipResolveDelayInMilliseconds = 120.0; + private const double CompletionWindowHorizontalChrome = 52.0; + private const double CompletionItemIconWidth = 24.0; + private const double CompletionItemDetailSpacing = 12.0; - private static readonly FieldInfo? CompletionToolTipField = - typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); + private static readonly FieldInfo? CompletionToolTipField = + typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); - private static bool _completionToolTipFieldLoggedMissing; + private static bool _completionToolTipFieldLoggedMissing; - private CancellationTokenSource? _completionCancellationTokenSource; - private int _completionRequestToken; - private int _completionToolTipUpdateToken; + private CancellationTokenSource? _completionCancellationTokenSource; + private int _completionRequestToken; + private int _completionToolTipUpdateToken; - private void CloseCompletionWindow() - { - CancelCompletionToolTipUpdate(); + private void CloseCompletionWindow() + { + CancelCompletionToolTipUpdate(); - if (_completionWindow is null) - return; + if (_completionWindow is null) + return; - if (CompletionToolTipField?.GetValue(_completionWindow) is ToolTip tooltip) - tooltip.IsOpen = false; + if (CompletionToolTipField?.GetValue(_completionWindow) is ToolTip tooltip) + tooltip.IsOpen = false; - _completionWindow.Close(); - _completionWindow = null; - } + _completionWindow.Close(); + _completionWindow = null; + } - private void InitializeLuaCompletionWindow() - { - InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); - LuaCompletionWindowStyle.Apply(_completionWindow, GetThemeBrushSet()); - StyleCompletionTooltip(); - MakeCompletionWindowNonActivatable(); - } + private void InitializeLuaCompletionWindow() + { + InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); + LuaCompletionWindowStyle.Apply(_completionWindow, GetThemeBrushSet()); + StyleCompletionTooltip(); + MakeCompletionWindowNonActivatable(); + } + + private async Task RequestCompletionAsync(int offset, char? triggerCharacter) + { + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionCancellationTokenSource); + int requestToken = ++_completionRequestToken; - private async Task RequestCompletionAsync(int offset, char? triggerCharacter) + try { - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionCancellationTokenSource); - int requestToken = ++_completionRequestToken; + if (!IsIntellisenseAvailable()) + return; - try - { - if (!IsIntellisenseAvailable()) - return; + DismissSignatureHelp(); + CloseDefinitionToolTip(true); - DismissSignatureHelp(); - CloseDefinitionToolTip(true); + (int line, int column) = GetPositionFromOffset(offset); - (int line, int column) = GetPositionFromOffset(offset); - var items = await IntellisenseProvider - .GetCompletionItemsAsync(FilePath, Text, line, column, triggerCharacter, cancellationToken) - .ConfigureAwait(true); + var items = await IntellisenseProvider + .GetCompletionItemsAsync(FilePath, Text, line, column, triggerCharacter, cancellationToken) + .ConfigureAwait(true); - if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) - return; + if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + return; - if (items is null || items.Count == 0) - { - CloseCompletionWindow(); - return; - } + if (items is null || items.Count == 0) + { + CloseCompletionWindow(); + return; + } - var completionDataItems = new LuaCompletionData[items.Count]; - var brushSet = GetThemeBrushSet(); + var completionDataItems = new LuaCompletionData[items.Count]; + var brushSet = GetThemeBrushSet(); - for (int i = 0; i < items.Count; i++) - completionDataItems[i] = new LuaCompletionData(items[i], brushSet); + for (int i = 0; i < items.Count; i++) + completionDataItems[i] = new LuaCompletionData(items[i], brushSet); - if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) - return; + if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + return; - CloseCompletionWindow(); + CloseCompletionWindow(); - InitializeLuaCompletionWindow(); - ResizeCompletionWindow(completionDataItems); - SetCompletionWindowOffsets(offset); + InitializeLuaCompletionWindow(); + ResizeCompletionWindow(completionDataItems); + SetCompletionWindowOffsets(offset); - foreach (LuaCompletionData completionDataItem in completionDataItems) - _completionWindow.CompletionList.CompletionData.Add(completionDataItem); + foreach (LuaCompletionData completionDataItem in completionDataItems) + _completionWindow.CompletionList.CompletionData.Add(completionDataItem); - if (_completionWindow.CompletionList.CompletionData.Count > 0) - { - ShowCompletionWindow(); - ScheduleInitialSelection(); - } - } - catch (OperationCanceledException) + if (_completionWindow.CompletionList.CompletionData.Count > 0) { - } - catch (Exception exception) - { - CloseCompletionWindow(); - WriteDebugFailure("Completion request", exception); + ShowCompletionWindow(); + ScheduleInitialSelection(); } } - - private void StyleCompletionTooltip() + catch (OperationCanceledException) + { } + catch (Exception exception) { - if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) - return; + CloseCompletionWindow(); + WriteDebugFailure("Completion request", exception); + } + } - if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) - { - if (!_completionToolTipFieldLoggedMissing) - { - _completionToolTipFieldLoggedMissing = true; - Debug.WriteLine("[Lua] AvalonEdit completion tooltip styling is unavailable because the internal tooltip field could not be found."); - } + private void StyleCompletionTooltip() + { + if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; - return; + if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) + { + if (!_completionToolTipFieldLoggedMissing) + { + _completionToolTipFieldLoggedMissing = true; + Debug.WriteLine("[Lua] AvalonEdit completion tooltip styling is unavailable because the internal tooltip field could not be found."); } - tooltip.Background = DefaultToolTipBackground; - tooltip.BorderBrush = DefaultToolTipBorder; - tooltip.BorderThickness = new Thickness(0.0); - tooltip.Padding = new Thickness(0.0); - tooltip.PlacementTarget = listBox; - tooltip.Placement = PlacementMode.Right; - tooltip.HorizontalOffset = CompletionToolTipHorizontalOffset; - tooltip.StaysOpen = true; - - listBox.SelectionChanged += (s, e) => ScheduleCompletionTooltipUpdate(tooltip); - listBox.PreviewMouseLeftButtonUp += (s, e) => HandleCompletionListClick(listBox, tooltip, e); + return; } - private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) - { - ListBoxItem? listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); + tooltip.Background = DefaultToolTipBackground; + tooltip.BorderBrush = DefaultToolTipBorder; + tooltip.BorderThickness = new Thickness(0.0); + tooltip.Padding = new Thickness(0.0); + tooltip.PlacementTarget = listBox; + tooltip.Placement = PlacementMode.Right; + tooltip.HorizontalOffset = CompletionToolTipHorizontalOffset; + tooltip.StaysOpen = true; + + listBox.SelectionChanged += (s, e) => ScheduleCompletionTooltipUpdate(tooltip); + listBox.PreviewMouseLeftButtonUp += (s, e) => HandleCompletionListClick(listBox, tooltip, e); + } - if (listBoxItem is null) - return; + private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) + { + ListBoxItem? listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); - if (!ReferenceEquals(listBox.SelectedItem, listBoxItem.DataContext)) - listBox.SelectedItem = listBoxItem.DataContext; + if (listBoxItem is null) + return; - listBox.ScrollIntoView(listBoxItem.DataContext); - ScheduleCompletionTooltipUpdate(tooltip); - } + if (!ReferenceEquals(listBox.SelectedItem, listBoxItem.DataContext)) + listBox.SelectedItem = listBoxItem.DataContext; - private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) - { - int updateToken = ++_completionToolTipUpdateToken; + listBox.ScrollIntoView(listBoxItem.DataContext); + ScheduleCompletionTooltipUpdate(tooltip); + } - Dispatcher.BeginInvoke( - new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, updateToken)), - DispatcherPriority.Background); - } + private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) + { + int updateToken = ++_completionToolTipUpdateToken; + + Dispatcher.BeginInvoke( + new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, updateToken)), + DispatcherPriority.Background); + } - private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken) + private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken) + { + if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; + + if (listBox.SelectedItem is not ICompletionData item) { - if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) - return; + tooltip.IsOpen = false; + return; + } - ICompletionData? item = listBox.SelectedItem as ICompletionData; + try + { + object? description = item.Description; - if (item is null) - { + if (description is not null) + ApplyCompletionToolTipContent(tooltip, description); + else tooltip.IsOpen = false; - return; - } - try + if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) { - object? description = item.Description; + await Task.Delay(TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds)).ConfigureAwait(true); - if (description is not null) - ApplyCompletionToolTipContent(tooltip, description); - else - tooltip.IsOpen = false; + if (updateToken != _completionToolTipUpdateToken) + return; - if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) + object? resolvedDescription = await luaCompletionData.GetDescriptionAsync().ConfigureAwait(true); + + if (updateToken != _completionToolTipUpdateToken) + return; + + if (_completionWindow?.CompletionList.ListBox is not ListBox currentListBox + || !ReferenceEquals(currentListBox, listBox) + || !ReferenceEquals(currentListBox.SelectedItem, item)) { - await Task.Delay(TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds)).ConfigureAwait(true); + return; + } - if (updateToken != _completionToolTipUpdateToken) - return; + if (resolvedDescription is not null) + ApplyCompletionToolTipContent(tooltip, resolvedDescription); + else + tooltip.IsOpen = false; + } + } + catch (Exception exception) + { + tooltip.IsOpen = false; + WriteDebugFailure("Completion tooltip update", exception); + } + } - object? resolvedDescription = await luaCompletionData.GetDescriptionAsync().ConfigureAwait(true); + private void ResizeCompletionWindow(IReadOnlyList completionDataItems) + { + if (_completionWindow is null || completionDataItems is null || completionDataItems.Count == 0) + return; - if (updateToken != _completionToolTipUpdateToken) - return; + double requiredWidth = CompletionWindowMinWidth; - if (_completionWindow?.CompletionList.ListBox is not ListBox currentListBox - || !ReferenceEquals(currentListBox, listBox) - || !ReferenceEquals(currentListBox.SelectedItem, item)) - { - return; - } + for (int i = 0; i < completionDataItems.Count; i++) + requiredWidth = Math.Max(requiredWidth, MeasureCompletionItemWidth(completionDataItems[i])); - if (resolvedDescription is not null) - ApplyCompletionToolTipContent(tooltip, resolvedDescription); - else - tooltip.IsOpen = false; - } - } - catch (Exception exception) - { - tooltip.IsOpen = false; - WriteDebugFailure("Completion tooltip update", exception); - } - } + _completionWindow.Width = Math.Max( + CompletionWindowMinWidth, + Math.Min(CompletionWindowMaxWidth, requiredWidth + CompletionWindowHorizontalChrome)); + } - private void ResizeCompletionWindow(IReadOnlyList completionDataItems) - { - if (_completionWindow is null || completionDataItems is null || completionDataItems.Count == 0) - return; + private double MeasureCompletionItemWidth(LuaCompletionData completionData) + { + double width = CompletionItemIconWidth + MeasureCompletionTextWidth(completionData.DisplayText); + + if (!string.IsNullOrWhiteSpace(completionData.DisplayDetail)) + width += CompletionItemDetailSpacing + MeasureCompletionTextWidth(completionData.DisplayDetail); - double requiredWidth = CompletionWindowMinWidth; + return width; + } - for (int i = 0; i < completionDataItems.Count; i++) - requiredWidth = Math.Max(requiredWidth, MeasureCompletionItemWidth(completionDataItems[i])); + private double MeasureCompletionTextWidth(string text) + { + if (string.IsNullOrWhiteSpace(text)) + return 0.0; - _completionWindow.Width = Math.Max( - CompletionWindowMinWidth, - Math.Min(CompletionWindowMaxWidth, requiredWidth + CompletionWindowHorizontalChrome)); - } + double pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip; - private double MeasureCompletionItemWidth(LuaCompletionData completionData) - { - double width = CompletionItemIconWidth + MeasureCompletionTextWidth(completionData.DisplayText); + var formattedText = new FormattedText( + text, + CultureInfo.CurrentUICulture, + FlowDirection.LeftToRight, + new Typeface(FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), + FontSize, + Foreground, + pixelsPerDip); - if (!string.IsNullOrWhiteSpace(completionData.DisplayDetail)) - width += CompletionItemDetailSpacing + MeasureCompletionTextWidth(completionData.DisplayDetail); + return formattedText.WidthIncludingTrailingWhitespace; + } - return width; - } + private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) + { + tooltip.Content = content; - private double MeasureCompletionTextWidth(string text) + if (!tooltip.IsOpen) { - if (string.IsNullOrWhiteSpace(text)) - return 0.0; - - double pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip; - var formattedText = new FormattedText( - text, - CultureInfo.CurrentUICulture, - FlowDirection.LeftToRight, - new Typeface(FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), - FontSize, - Foreground, - pixelsPerDip); - - return formattedText.WidthIncludingTrailingWhitespace; + tooltip.IsOpen = true; } - - private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) + else { - tooltip.Content = content; - if (!tooltip.IsOpen) - tooltip.IsOpen = true; - else - { - tooltip.InvalidateMeasure(); - tooltip.InvalidateVisual(); - } + tooltip.InvalidateMeasure(); + tooltip.InvalidateVisual(); } + } - private void CancelCompletionToolTipUpdate() - => _completionToolTipUpdateToken++; + private void CancelCompletionToolTipUpdate() + => _completionToolTipUpdateToken++; - private void ScheduleCloseIfEmpty() - => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); + private void ScheduleCloseIfEmpty() + => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); - private void ScheduleInitialSelection() - => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.ContextIdle); + private void ScheduleInitialSelection() + => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.ContextIdle); - private void SelectInitialItem() - { - if (_completionWindow is null) - return; - - _completionWindow.CompletionList.SelectItem(GetCompletionWindowQuery()); - CloseCompletionWindowIfEmpty(); - } + private void SelectInitialItem() + { + if (_completionWindow is null) + return; - private void MakeCompletionWindowNonActivatable() - { - _completionWindow.SourceInitialized += (s, e) => - { - if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) - source.AddHook(CompletionWindowWndProc); - }; - } + _completionWindow.CompletionList.SelectItem(GetCompletionWindowQuery()); + CloseCompletionWindowIfEmpty(); + } - private static IntPtr CompletionWindowWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + private void MakeCompletionWindowNonActivatable() + { + _completionWindow.SourceInitialized += (s, e) => { - const int WM_MOUSEACTIVATE = 0x0021; - const int MA_NOACTIVATE = 3; + if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) + source.AddHook(CompletionWindowWndProc); + }; + } - if (msg == WM_MOUSEACTIVATE) - { - handled = true; - return new IntPtr(MA_NOACTIVATE); - } + private static IntPtr CompletionWindowWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + const int WM_MOUSEACTIVATE = 0x0021; + const int MA_NOACTIVATE = 3; - return IntPtr.Zero; + if (msg == WM_MOUSEACTIVATE) + { + handled = true; + return new IntPtr(MA_NOACTIVATE); } - private bool CloseCompletionWindowIfEmpty() - { - if (_completionWindow is null) - return false; + return IntPtr.Zero; + } - ListBox listBox = _completionWindow.CompletionList.ListBox; + private bool CloseCompletionWindowIfEmpty() + { + if (_completionWindow is null) + return false; - if (listBox is null || listBox.HasItems) - return false; + ListBox listBox = _completionWindow.CompletionList.ListBox; - CloseCompletionWindow(); - return true; - } + if (listBox?.HasItems != false) + return false; - private string GetCompletionWindowQuery() - { - if (_completionWindow is null || Document is null) - return string.Empty; + CloseCompletionWindow(); + return true; + } - int startOffset = Math.Max(0, Math.Min(_completionWindow.StartOffset, Document.TextLength)); - int endOffset = Math.Max(startOffset, Math.Min(_completionWindow.EndOffset, Document.TextLength)); + private string GetCompletionWindowQuery() + { + if (_completionWindow is null || Document is null) + return string.Empty; - return endOffset > startOffset - ? Document.GetText(startOffset, endOffset - startOffset) - : string.Empty; - } + int startOffset = Math.Max(0, Math.Min(_completionWindow.StartOffset, Document.TextLength)); + int endOffset = Math.Max(startOffset, Math.Min(_completionWindow.EndOffset, Document.TextLength)); - private void SetCompletionWindowOffsets(int offset) - { - int startOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + return endOffset > startOffset + ? Document.GetText(startOffset, endOffset - startOffset) + : string.Empty; + } - while (startOffset > 0) - { - char currentChar = Document.GetCharAt(startOffset - 1); + private void SetCompletionWindowOffsets(int offset) + { + int startOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); - if (LuaLineParser.IsIdentifierCharacter(currentChar)) - startOffset--; - else - break; - } + while (startOffset > 0) + { + char currentChar = Document.GetCharAt(startOffset - 1); - _completionWindow.StartOffset = startOffset; - _completionWindow.EndOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + if (LuaLineParser.IsIdentifierCharacter(currentChar)) + startOffset--; + else + break; } + + _completionWindow.StartOffset = startOffset; + _completionWindow.EndOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index 72ee330c46..bc3b893dee 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -10,150 +10,150 @@ using TombLib.Scripting.Objects; using TombLib.Scripting.Rendering; -namespace TombLib.Scripting.Lua -{ - public sealed partial class LuaEditor - { - private CancellationTokenSource? _hoverCancellationTokenSource; - private int _hoverRequestToken; - - protected override async void HandleMouseHover(MouseEventArgs e) - { - int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); +namespace TombLib.Scripting.Lua; - if (hoveredOffset == -1) - return; +public sealed partial class LuaEditor +{ + private CancellationTokenSource? _hoverCancellationTokenSource; + private int _hoverRequestToken; - bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); + protected override async void HandleMouseHover(MouseEventArgs e) + { + int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); - bool isCompletionWindowOpen = _completionWindow is not null; + if (hoveredOffset == -1) + return; - if (!LuaEditorInteractionRules.CanRequestHover(Document, hoveredOffset, isCompletionWindowOpen, _signaturePopup.IsOpen)) - { - if (!isCompletionWindowOpen && !_signaturePopup.IsOpen) - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); - return; - } + bool isCompletionWindowOpen = _completionWindow is not null; - if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, hoveredOffset, out int hoverOffset)) - { + if (!LuaEditorInteractionRules.CanRequestHover(Document, hoveredOffset, isCompletionWindowOpen, _signaturePopup.IsOpen)) + { + if (!isCompletionWindowOpen && !_signaturePopup.IsOpen) ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - return; - } - if (!IsIntellisenseAvailable()) - { - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + return; + } - return; - } + if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, hoveredOffset, out int hoverOffset)) + { + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + return; + } - string hoveredWord = GetWordFromOffset(hoverOffset); + if (!IsIntellisenseAvailable()) + { + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - if (string.IsNullOrWhiteSpace(hoveredWord)) - { - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + return; + } - return; - } + string hoveredWord = GetWordFromOffset(hoverOffset); - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _hoverCancellationTokenSource); - int hoverRequestToken = ++_hoverRequestToken; + if (string.IsNullOrWhiteSpace(hoveredWord)) + { + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - try - { - LuaHoverInfo? hoverInfo = await RequestHoverAsync(hoverOffset, cancellationToken).ConfigureAwait(true); + return; + } - if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) - return; + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _hoverCancellationTokenSource); + int hoverRequestToken = ++_hoverRequestToken; - int currentHoveredOffset = GetOffsetFromPoint(Mouse.GetPosition(this)); + try + { + LuaHoverInfo? hoverInfo = await RequestHoverAsync(hoverOffset, cancellationToken).ConfigureAwait(true); - if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, currentHoveredOffset, out int currentHoverOffset) - || currentHoverOffset != hoverOffset) - return; + if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) + return; - ShowBestHoverToolTip(hoverInfo, hasDiagnostic, diagnosticMessage, diagnosticSeverity); - } - catch (OperationCanceledException) + int currentHoveredOffset = GetOffsetFromPoint(Mouse.GetPosition(this)); + + if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, currentHoveredOffset, out int currentHoverOffset) + || currentHoverOffset != hoverOffset) { + return; } - catch (Exception exception) - { - WriteDebugFailure("Hover request", exception); - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - } + ShowBestHoverToolTip(hoverInfo, hasDiagnostic, diagnosticMessage, diagnosticSeverity); } - - private void ShowDiagnosticToolTipIfAvailable(bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + catch (OperationCanceledException) + { } + catch (Exception exception) { - if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); - } + WriteDebugFailure("Hover request", exception); - private void ShowBestHoverToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) - { - if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) && hasDiagnostic) - ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); - else if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content)) - ShowHoverToolTip(hoverInfo); - else - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); } + } - private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) - { - GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); + private void ShowDiagnosticToolTipIfAvailable(bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + { + if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + } - var panel = new StackPanel { MaxWidth = ToolTipTextMaxWidth }; + private void ShowBestHoverToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + { + if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) && hasDiagnostic) + ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); + else if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content)) + ShowHoverToolTip(hoverInfo); + else + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + } - panel.Children.Add(CreateHoverToolTipContent(hoverInfo)); + private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) + { + GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); - panel.Children.Add(new Border - { - Background = diagnosticBackground, - BorderBrush = diagnosticBorder, - BorderThickness = new Thickness(1.0), - CornerRadius = new CornerRadius(3.0), - Padding = new Thickness(8.0, 4.0, 8.0, 4.0), - Margin = new Thickness(0.0, 6.0, 0.0, 0.0), - Child = new TextBlock - { - Text = diagnosticMessage, - Foreground = ToolTipForeground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = ToolTipTextFontSize, - TextWrapping = TextWrapping.Wrap, - MaxWidth = ToolTipTextMaxWidth - } - }); - - ShowToolTip(panel, DefaultToolTipBorder, DefaultToolTipBackground); - } + var panel = new StackPanel { MaxWidth = ToolTipTextMaxWidth }; - private void ShowHoverToolTip(LuaHoverInfo hoverInfo) - => ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); + panel.Children.Add(CreateHoverToolTipContent(hoverInfo)); - private FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) + panel.Children.Add(new Border { - if (hoverInfo.IsMarkdown) - return MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground); + Background = diagnosticBackground, + BorderBrush = diagnosticBorder, + BorderThickness = new Thickness(1.0), + CornerRadius = new CornerRadius(3.0), + Padding = new Thickness(8.0, 4.0, 8.0, 4.0), + Margin = new Thickness(0.0, 6.0, 0.0, 0.0), + Child = new TextBlock + { + Text = diagnosticMessage, + Foreground = ToolTipForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = ToolTipTextFontSize, + TextWrapping = TextWrapping.Wrap, + MaxWidth = ToolTipTextMaxWidth + } + }); - return MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); - } + ShowToolTip(panel, DefaultToolTipBorder, DefaultToolTipBackground); + } - private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) - { - if (!IsIntellisenseAvailable()) - return null; + private void ShowHoverToolTip(LuaHoverInfo hoverInfo) + => ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); - (int line, int column) = GetPositionFromOffset(offset); + private static FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) + { + if (hoverInfo.IsMarkdown) + return MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground); - return await IntellisenseProvider - .GetHoverAsync(FilePath, Text, line, column, cancellationToken) - .ConfigureAwait(true); - } + return MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); + } + + private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) + { + if (!IsIntellisenseAvailable()) + return null; + + (int line, int column) = GetPositionFromOffset(offset); + + return await IntellisenseProvider + .GetHoverAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index 9d38828273..06f6dc8a13 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -1,202 +1,203 @@ +using ICSharpCode.AvalonEdit.Document; using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Windows; using System.Windows.Input; -using ICSharpCode.AvalonEdit.Document; using TombLib.Scripting.Lua.Utils; -namespace TombLib.Scripting.Lua +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor { - public sealed partial class LuaEditor - { - private Window? _hostWindow; + private Window? _hostWindow; - private void BindLuaIntellisenseEvents() - { - IsKeyboardFocusWithinChanged += LuaEditor_IsKeyboardFocusWithinChanged; - Loaded += LuaEditor_Loaded; - TextArea.TextEntering += TextArea_TextEntering; - TextArea.TextEntered += TextArea_TextEntered; - AddHandler(PreviewKeyDownEvent, new KeyEventHandler(TextEditor_KeyDown), true); - AddHandler(PreviewMouseDownEvent, new MouseButtonEventHandler(TextEditor_PreviewMouseDown), true); - AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(TextEditor_PreviewMouseLeftButtonDown), true); - Unloaded += LuaEditor_Unloaded; - } + private void BindLuaIntellisenseEvents() + { + IsKeyboardFocusWithinChanged += LuaEditor_IsKeyboardFocusWithinChanged; + Loaded += LuaEditor_Loaded; + TextArea.TextEntering += TextArea_TextEntering; + TextArea.TextEntered += TextArea_TextEntered; + AddHandler(PreviewKeyDownEvent, new KeyEventHandler(TextEditor_KeyDown), true); + AddHandler(PreviewMouseDownEvent, new MouseButtonEventHandler(TextEditor_PreviewMouseDown), true); + AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(TextEditor_PreviewMouseLeftButtonDown), true); + Unloaded += LuaEditor_Unloaded; + } - private void LuaEditor_Loaded(object? sender, RoutedEventArgs e) - => AttachHostWindowHandlers(); + private void LuaEditor_Loaded(object? sender, RoutedEventArgs e) + => AttachHostWindowHandlers(); - private void LuaEditor_IsKeyboardFocusWithinChanged(object? sender, DependencyPropertyChangedEventArgs e) + private void LuaEditor_IsKeyboardFocusWithinChanged(object? sender, DependencyPropertyChangedEventArgs e) + { + if (e.NewValue is bool hasKeyboardFocus && !hasKeyboardFocus) { - if (e.NewValue is bool hasKeyboardFocus && !hasKeyboardFocus) - { - CloseCompletionWindow(); - DismissTransientToolTips(); - } + CloseCompletionWindow(); + DismissTransientToolTips(); } + } - private void AttachHostWindowHandlers() - { - Window? window = Window.GetWindow(this); + private void AttachHostWindowHandlers() + { + Window? window = Window.GetWindow(this); - if (window == _hostWindow) - return; + if (window == _hostWindow) + return; - if (_hostWindow is not null) - _hostWindow.Deactivated -= HostWindow_Deactivated; + if (_hostWindow is not null) + _hostWindow.Deactivated -= HostWindow_Deactivated; - _hostWindow = window; + _hostWindow = window; - if (_hostWindow is not null) - _hostWindow.Deactivated += HostWindow_Deactivated; - } + if (_hostWindow is not null) + _hostWindow.Deactivated += HostWindow_Deactivated; + } - private void HostWindow_Deactivated(object? sender, EventArgs e) - { - CloseCompletionWindow(); - DismissTransientToolTips(); - } + private void HostWindow_Deactivated(object? sender, EventArgs e) + { + CloseCompletionWindow(); + DismissTransientToolTips(); + } - private void LuaEditor_Unloaded(object? sender, RoutedEventArgs e) - { - _textMateHighlighting?.Dispose(); - _textMateHighlighting = null; + private void LuaEditor_Unloaded(object? sender, RoutedEventArgs e) + { + _textMateHighlighting?.Dispose(); + _textMateHighlighting = null; - CancelAndDispose(ref _hoverCancellationTokenSource); - CancelAndDispose(ref _completionCancellationTokenSource); + CancelAndDispose(ref _hoverCancellationTokenSource); + CancelAndDispose(ref _completionCancellationTokenSource); - CancelCompletionToolTipUpdate(); + CancelCompletionToolTipUpdate(); - CancelAndDispose(ref _signatureCancellationTokenSource); - CloseCompletionWindow(); + CancelAndDispose(ref _signatureCancellationTokenSource); + CloseCompletionWindow(); - if (_hostWindow is not null) - _hostWindow.Deactivated -= HostWindow_Deactivated; + if (_hostWindow is not null) + _hostWindow.Deactivated -= HostWindow_Deactivated; - _hostWindow = null; + _hostWindow = null; - DismissTransientToolTips(); - ClearDiagnostics(); - ClearSemanticTokens(); + DismissTransientToolTips(); + ClearDiagnostics(); + ClearSemanticTokens(); - IntellisenseProvider?.CloseDocument(FilePath); - } + IntellisenseProvider?.CloseDocument(FilePath); + } - private async void TextArea_TextEntering(object? sender, TextCompositionEventArgs e) + private async void TextArea_TextEntering(object? sender, TextCompositionEventArgs e) + { + if (!AutocompleteEnabled || !IsIntellisenseAvailable()) + return; + + if (e.Text == " " && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) { - if (!AutocompleteEnabled || !IsIntellisenseAvailable()) - return; + e.Handled = true; - if (e.Text == " " && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) - { - e.Handled = true; + if (LuaEditorInteractionRules.IsValidManualCompletionContext(Document, CaretOffset)) + await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); + } + } - if (LuaEditorInteractionRules.IsValidManualCompletionContext(Document, CaretOffset)) - await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); - } + private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs e) + { + if (!IsIntellisenseAvailable()) + return; + + if (e.Text == "(" || e.Text == ",") + { + CloseCompletionWindow(); + await RequestSignatureHelpAsync(CaretOffset).ConfigureAwait(true); + return; } - private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs e) + if (e.Text == ")") { - if (!IsIntellisenseAvailable()) - return; + CloseCompletionWindow(); + DismissSignatureHelp(); + return; + } - if (e.Text == "(" || e.Text == ",") + if (_completionWindow is not null) + { + if (!ShouldKeepCompletionWindowOpen(e.Text)) { CloseCompletionWindow(); - await RequestSignatureHelpAsync(CaretOffset).ConfigureAwait(true); - return; } - - if (e.Text == ")") + else { - CloseCompletionWindow(); - DismissSignatureHelp(); + ScheduleCloseIfEmpty(); return; } - - if (_completionWindow is not null) - { - if (!ShouldKeepCompletionWindowOpen(e.Text)) - CloseCompletionWindow(); - else - { - ScheduleCloseIfEmpty(); - return; - } - } - - if (!AutocompleteEnabled) - return; - - if (TryGetCompletionTrigger(e.Text, out char? triggerCharacter) - && LuaEditorInteractionRules.IsValidAutocompleteContext(Document, CaretOffset, triggerCharacter)) - await RequestCompletionAsync(CaretOffset, triggerCharacter).ConfigureAwait(true); } - [MemberNotNullWhen(true, nameof(IntellisenseProvider))] - private bool IsIntellisenseAvailable() - => IntellisenseProvider is not null && IntellisenseProvider.IsAvailable && !string.IsNullOrWhiteSpace(FilePath); + if (!AutocompleteEnabled) + return; - private static bool TryGetCompletionTrigger(string? inputText, out char? triggerCharacter) + if (TryGetCompletionTrigger(e.Text, out char? triggerCharacter) + && LuaEditorInteractionRules.IsValidAutocompleteContext(Document, CaretOffset, triggerCharacter)) { - triggerCharacter = null; - - if (string.IsNullOrEmpty(inputText) || inputText.Length != 1) - return false; + await RequestCompletionAsync(CaretOffset, triggerCharacter).ConfigureAwait(true); + } + } - char typedChar = inputText[0]; + [MemberNotNullWhen(true, nameof(IntellisenseProvider))] + private bool IsIntellisenseAvailable() + => IntellisenseProvider?.IsAvailable == true && !string.IsNullOrWhiteSpace(FilePath); - if (typedChar == '.' || typedChar == ':') - { - triggerCharacter = typedChar; - return true; - } + private static bool TryGetCompletionTrigger(string? inputText, out char? triggerCharacter) + { + triggerCharacter = null; - return LuaLineParser.IsIdentifierTriggerCharacter(typedChar); - } + if (string.IsNullOrEmpty(inputText) || inputText.Length != 1) + return false; - private static bool ShouldKeepCompletionWindowOpen(string? inputText) - => inputText?.Length == 1 && LuaLineParser.IsIdentifierCharacter(inputText[0]); + char typedChar = inputText[0]; - private void DismissTransientToolTips() + if (typedChar == '.' || typedChar == ':') { - CancelAndDispose(ref _hoverCancellationTokenSource); - _hoverRequestToken++; - DismissSignatureHelp(); - CloseDefinitionToolTip(true); + triggerCharacter = typedChar; + return true; } - private (int line, int column) GetPositionFromOffset(int offset) - { - int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); - TextLocation location = Document.GetLocation(safeOffset); + return LuaLineParser.IsIdentifierTriggerCharacter(typedChar); + } - return (location.Line - 1, location.Column - 1); - } + private static bool ShouldKeepCompletionWindowOpen(string? inputText) + => inputText?.Length == 1 && LuaLineParser.IsIdentifierCharacter(inputText[0]); - private static CancellationToken ResetCancellationTokenSource(ref CancellationTokenSource? cancellationTokenSource) - { - CancelAndDispose(ref cancellationTokenSource); - cancellationTokenSource = new CancellationTokenSource(); - return cancellationTokenSource.Token; - } + private void DismissTransientToolTips() + { + CancelAndDispose(ref _hoverCancellationTokenSource); + _hoverRequestToken++; + DismissSignatureHelp(); + CloseDefinitionToolTip(true); + } - private static void CancelAndDispose(ref CancellationTokenSource? cancellationTokenSource) - { - if (cancellationTokenSource is null) - return; + private (int line, int column) GetPositionFromOffset(int offset) + { + int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); + TextLocation location = Document.GetLocation(safeOffset); - cancellationTokenSource.Cancel(); - cancellationTokenSource.Dispose(); - cancellationTokenSource = null; - } + return (location.Line - 1, location.Column - 1); + } - private static void WriteDebugFailure(string area, Exception exception) - { - Debug.WriteLine($"[Lua] {area} failed: {exception}"); - } + private static CancellationToken ResetCancellationTokenSource(ref CancellationTokenSource? cancellationTokenSource) + { + CancelAndDispose(ref cancellationTokenSource); + cancellationTokenSource = new CancellationTokenSource(); + return cancellationTokenSource.Token; } -} \ No newline at end of file + + private static void CancelAndDispose(ref CancellationTokenSource? cancellationTokenSource) + { + if (cancellationTokenSource is null) + return; + + cancellationTokenSource.Cancel(); + cancellationTokenSource.Dispose(); + cancellationTokenSource = null; + } + + private static void WriteDebugFailure(string area, Exception exception) + => Debug.WriteLine($"[Lua] {area} failed: {exception}"); +} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index 455563b4cc..ca25aea422 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -6,87 +6,86 @@ using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Utils; -namespace TombLib.Scripting.Lua +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor { - public sealed partial class LuaEditor + private async void TextEditor_KeyDown(object? sender, KeyEventArgs e) { - private async void TextEditor_KeyDown(object? sender, KeyEventArgs e) + if (e.Key == Key.Escape && (_completionWindow is not null || _signaturePopup.IsOpen || _specialToolTip.IsOpen)) { - if (e.Key == Key.Escape && (_completionWindow is not null || _signaturePopup.IsOpen || _specialToolTip.IsOpen)) - { - CloseCompletionWindow(); - DismissTransientToolTips(); - e.Handled = true; - return; - } + CloseCompletionWindow(); + DismissTransientToolTips(); + e.Handled = true; + return; + } - if (_signaturePopup.IsOpen && (e.Key == Key.Back || e.Key == Key.Delete)) - ScheduleSignatureHelpRefresh(); + if (_signaturePopup.IsOpen && (e.Key == Key.Back || e.Key == Key.Delete)) + ScheduleSignatureHelpRefresh(); - if (e.Key == Key.F12) - { - if (await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true)) - e.Handled = true; - } + if (e.Key == Key.F12) + { + if (await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true)) + e.Handled = true; } + } - private void TextEditor_PreviewMouseDown(object? sender, MouseButtonEventArgs e) + private void TextEditor_PreviewMouseDown(object? sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left || e.ChangedButton == MouseButton.Right) { - if (e.ChangedButton == MouseButton.Left || e.ChangedButton == MouseButton.Right) - { - CloseCompletionWindow(); - DismissTransientToolTips(); - } + CloseCompletionWindow(); + DismissTransientToolTips(); } + } - private async void TextEditor_PreviewMouseLeftButtonDown(object? sender, MouseButtonEventArgs e) - { - if (!Keyboard.Modifiers.HasFlag(ModifierKeys.Control) || e.ChangedButton != MouseButton.Left) - return; + private async void TextEditor_PreviewMouseLeftButtonDown(object? sender, MouseButtonEventArgs e) + { + if (!Keyboard.Modifiers.HasFlag(ModifierKeys.Control) || e.ChangedButton != MouseButton.Left) + return; - int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); + int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); - if (hoveredOffset == -1) - return; + if (hoveredOffset == -1) + return; - if (await TryNavigateToDefinitionAsync(hoveredOffset, CancellationToken.None).ConfigureAwait(true)) - e.Handled = true; - } + if (await TryNavigateToDefinitionAsync(hoveredOffset, CancellationToken.None).ConfigureAwait(true)) + e.Handled = true; + } - private async Task TryNavigateToDefinitionAsync(int offset, CancellationToken cancellationToken) + private async Task TryNavigateToDefinitionAsync(int offset, CancellationToken cancellationToken) + { + if (!IsIntellisenseAvailable()) + return false; + + try { - if (!IsIntellisenseAvailable()) + if (!LuaEditorInteractionRules.TryGetDefinitionStartOffset(Document, offset, out int definitionOffset)) return false; - try - { - if (!LuaEditorInteractionRules.TryGetDefinitionStartOffset(Document, offset, out int definitionOffset)) - return false; - - (int line, int column) = GetPositionFromOffset(definitionOffset); + (int line, int column) = GetPositionFromOffset(definitionOffset); - LuaDefinitionLocation? definitionLocation = await IntellisenseProvider - .GetDefinitionAsync(FilePath, Text, line, column, cancellationToken) - .ConfigureAwait(true); + LuaDefinitionLocation? definitionLocation = await IntellisenseProvider + .GetDefinitionAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); - if (definitionLocation is null) - return false; - - DefinitionNavigationRequested?.Invoke(definitionLocation); - return true; - } - catch (OperationCanceledException) - { - return false; - } - catch (Exception exception) - { - Debug.WriteLine($"[Lua] Go to definition failed: {exception}"); + if (definitionLocation is null) return false; - } - } - public async void NavigateToDefinitionAtCaretAsync() - => await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true); + DefinitionNavigationRequested?.Invoke(definitionLocation); + return true; + } + catch (OperationCanceledException) + { + return false; + } + catch (Exception exception) + { + Debug.WriteLine($"[Lua] Go to definition failed: {exception}"); + return false; + } } -} \ No newline at end of file + + public async void NavigateToDefinitionAtCaretAsync() + => await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true); +} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs index b032fd0d19..8995157f51 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs @@ -2,30 +2,29 @@ using TombLib.Scripting.Lua.Highlighting; using TombLib.Scripting.Lua.Objects; -namespace TombLib.Scripting.Lua +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor { - public sealed partial class LuaEditor - { - private LuaSemanticTokensColorizer? _semanticTokensColorizer; + private LuaSemanticTokensColorizer? _semanticTokensColorizer; - public void SetSemanticTokens(IReadOnlyList tokens) - { - EnsureSemanticTokensColorizerAttached(); - _semanticTokensColorizer!.SetTokens(tokens); - } + public void SetSemanticTokens(IReadOnlyList tokens) + { + EnsureSemanticTokensColorizerAttached(); + _semanticTokensColorizer!.SetTokens(tokens); + } - public void ClearSemanticTokens() - => _semanticTokensColorizer?.ClearTokens(); + public void ClearSemanticTokens() + => _semanticTokensColorizer?.ClearTokens(); - private void EnsureSemanticTokensColorizerAttached() - { - if (_semanticTokensColorizer is null) - _semanticTokensColorizer = new LuaSemanticTokensColorizer(TextArea.TextView, GetThemeBrushSet()); - else - _semanticTokensColorizer.UpdateTheme(GetThemeBrushSet()); + private void EnsureSemanticTokensColorizerAttached() + { + if (_semanticTokensColorizer is null) + _semanticTokensColorizer = new LuaSemanticTokensColorizer(TextArea.TextView, GetThemeBrushSet()); + else + _semanticTokensColorizer.UpdateTheme(GetThemeBrushSet()); - if (!TextArea.TextView.LineTransformers.Contains(_semanticTokensColorizer)) - TextArea.TextView.LineTransformers.Add(_semanticTokensColorizer); - } + if (!TextArea.TextView.LineTransformers.Contains(_semanticTokensColorizer)) + TextArea.TextView.LineTransformers.Add(_semanticTokensColorizer); } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index 0a8687cfc0..9bd5827c54 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -9,85 +9,107 @@ using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Resources; -namespace TombLib.Scripting.Lua +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor { - public sealed partial class LuaEditor + private CancellationTokenSource? _signatureCancellationTokenSource; + + private readonly Popup _signaturePopup = new(); + private readonly Border _signaturePopupBorder = new(); + private readonly ContentPresenter _signaturePopupPresenter = new(); + + private void InitializeSignaturePopup() { - private CancellationTokenSource? _signatureCancellationTokenSource; + _signaturePopup.AllowsTransparency = true; + _signaturePopup.PopupAnimation = PopupAnimation.None; + _signaturePopup.StaysOpen = true; + _signaturePopup.Placement = PlacementMode.RelativePoint; + + _signaturePopupBorder.SnapsToDevicePixels = true; + _signaturePopupBorder.CornerRadius = new CornerRadius(3.0); + _signaturePopupBorder.BorderThickness = new Thickness(1.0); + _signaturePopupBorder.Padding = new Thickness(8.0, 6.0, 8.0, 6.0); + _signaturePopupBorder.BorderBrush = DefaultToolTipBorder; + _signaturePopupBorder.Background = DefaultToolTipBackground; + _signaturePopupBorder.Child = _signaturePopupPresenter; + + _signaturePopup.Child = _signaturePopupBorder; + } - private readonly Popup _signaturePopup = new Popup(); - private readonly Border _signaturePopupBorder = new Border(); - private readonly ContentPresenter _signaturePopupPresenter = new ContentPresenter(); + private void DismissSignatureHelp() + { + CancelAndDispose(ref _signatureCancellationTokenSource); - private void InitializeSignaturePopup() - { - _signaturePopup.AllowsTransparency = true; - _signaturePopup.PopupAnimation = PopupAnimation.None; - _signaturePopup.StaysOpen = true; - _signaturePopup.Placement = PlacementMode.RelativePoint; - - _signaturePopupBorder.SnapsToDevicePixels = true; - _signaturePopupBorder.CornerRadius = new CornerRadius(3.0); - _signaturePopupBorder.BorderThickness = new Thickness(1.0); - _signaturePopupBorder.Padding = new Thickness(8.0, 6.0, 8.0, 6.0); - _signaturePopupBorder.BorderBrush = DefaultToolTipBorder; - _signaturePopupBorder.Background = DefaultToolTipBackground; - _signaturePopupBorder.Child = _signaturePopupPresenter; - - _signaturePopup.Child = _signaturePopupBorder; - } + if (_signaturePopup.IsOpen) + _signaturePopup.IsOpen = false; - private void DismissSignatureHelp() - { - CancelAndDispose(ref _signatureCancellationTokenSource); + _signaturePopupPresenter.Content = null; + } - if (_signaturePopup.IsOpen) - _signaturePopup.IsOpen = false; + private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) + { + double availablePopupWidth = Math.Max(0.0, Math.Min(500.0, ActualWidth - 16.0)); - _signaturePopupPresenter.Content = null; - } + double popupHorizontalPadding = _signaturePopupBorder.Padding.Left + + _signaturePopupBorder.Padding.Right + + _signaturePopupBorder.BorderThickness.Left + + _signaturePopupBorder.BorderThickness.Right; + + double popupVerticalPadding = _signaturePopupBorder.Padding.Top + + _signaturePopupBorder.Padding.Bottom + + _signaturePopupBorder.BorderThickness.Top + + _signaturePopupBorder.BorderThickness.Bottom; + + double contentMaxWidth = Math.Max(0.0, availablePopupWidth - popupHorizontalPadding); + + StackPanel panel = CreateSignaturePanel(signatureInfo, contentMaxWidth); + + panel.Measure(new Size(contentMaxWidth, double.PositiveInfinity)); - private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) + Size popupSize = new( + Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), + panel.DesiredSize.Height + popupVerticalPadding); + + if (_signaturePopup.IsOpen) + _signaturePopup.IsOpen = false; + + _signaturePopupPresenter.Content = panel; + _signaturePopupPresenter.InvalidateMeasure(); + _signaturePopupBorder.InvalidateMeasure(); + PositionSignaturePopup(popupSize); + + _signaturePopup.IsOpen = true; + } + + private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double contentMaxWidth) + { + LuaThemeBrushSet brushSet = GetThemeBrushSet(); + var panel = new StackPanel { MaxWidth = contentMaxWidth }; + panel.Children.Add(BuildSignatureBlock(signatureInfo, brushSet)); + + if (!string.IsNullOrWhiteSpace(signatureInfo.Documentation)) { - double availablePopupWidth = Math.Max(0.0, Math.Min(500.0, ActualWidth - 16.0)); - double popupHorizontalPadding = _signaturePopupBorder.Padding.Left - + _signaturePopupBorder.Padding.Right - + _signaturePopupBorder.BorderThickness.Left - + _signaturePopupBorder.BorderThickness.Right; - double popupVerticalPadding = _signaturePopupBorder.Padding.Top - + _signaturePopupBorder.Padding.Bottom - + _signaturePopupBorder.BorderThickness.Top - + _signaturePopupBorder.BorderThickness.Bottom; - double contentMaxWidth = Math.Max(0.0, availablePopupWidth - popupHorizontalPadding); - - StackPanel panel = CreateSignaturePanel(signatureInfo, contentMaxWidth); - - panel.Measure(new Size(contentMaxWidth, double.PositiveInfinity)); - Size popupSize = new Size( - Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), - panel.DesiredSize.Height + popupVerticalPadding); - - if (_signaturePopup.IsOpen) - _signaturePopup.IsOpen = false; - - _signaturePopupPresenter.Content = panel; - _signaturePopupPresenter.InvalidateMeasure(); - _signaturePopupBorder.InvalidateMeasure(); - PositionSignaturePopup(popupSize); - _signaturePopup.IsOpen = true; + panel.Children.Add(new TextBlock + { + Text = signatureInfo.Documentation, + Foreground = brushSet.SignatureParamDocForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), + TextWrapping = TextWrapping.Wrap, + Margin = new Thickness(0.0, 4.0, 0.0, 0.0) + }); } - private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double contentMaxWidth) + if (signatureInfo.ActiveParameter < signatureInfo.Parameters.Count) { - LuaThemeBrushSet brushSet = GetThemeBrushSet(); - var panel = new StackPanel { MaxWidth = contentMaxWidth }; - panel.Children.Add(BuildSignatureBlock(signatureInfo, brushSet)); + LuaParameterInfo activeParam = signatureInfo.Parameters[signatureInfo.ActiveParameter]; - if (!string.IsNullOrWhiteSpace(signatureInfo.Documentation)) + if (!string.IsNullOrWhiteSpace(activeParam.Documentation)) { panel.Children.Add(new TextBlock { - Text = signatureInfo.Documentation, + Text = activeParam.Label + ": " + activeParam.Documentation, Foreground = brushSet.SignatureParamDocForeground, FontFamily = SystemFonts.MessageFontFamily, FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), @@ -95,142 +117,126 @@ private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double c Margin = new Thickness(0.0, 4.0, 0.0, 0.0) }); } + } - if (signatureInfo.ActiveParameter < signatureInfo.Parameters.Count) - { - LuaParameterInfo activeParam = signatureInfo.Parameters[signatureInfo.ActiveParameter]; + return panel; + } - if (!string.IsNullOrWhiteSpace(activeParam.Documentation)) - { - panel.Children.Add(new TextBlock - { - Text = activeParam.Label + ": " + activeParam.Documentation, - Foreground = brushSet.SignatureParamDocForeground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), - TextWrapping = TextWrapping.Wrap, - Margin = new Thickness(0.0, 4.0, 0.0, 0.0) - }); - } - } + private void PositionSignaturePopup(Size popupSize) + { + AttachHostWindowHandlers(); + _signaturePopup.PlacementTarget = this; + TextArea.TextView.EnsureVisualLines(); - return panel; - } + Rect caretRectangle = TextArea.Caret.CalculateCaretRectangle(); + Vector scrollOffset = TextArea.TextView.ScrollOffset; - private void PositionSignaturePopup(Size popupSize) - { - AttachHostWindowHandlers(); - _signaturePopup.PlacementTarget = this; - TextArea.TextView.EnsureVisualLines(); - - Rect caretRectangle = TextArea.Caret.CalculateCaretRectangle(); - Vector scrollOffset = TextArea.TextView.ScrollOffset; - Point caretViewportPoint = new Point( - caretRectangle.X - scrollOffset.X, - caretRectangle.Y - scrollOffset.Y); - Point editorPoint = TextArea.TextView.TranslatePoint(caretViewportPoint, this); - double lineHeight = Math.Max(TextArea.TextView.DefaultLineHeight, caretRectangle.Height); - double lineSlack = Math.Max(0.0, lineHeight - caretRectangle.Height); - double horizontalOffset = Math.Max(0.0, editorPoint.X + 2.0f); - double maxHorizontalOffset = Math.Max(0.0, ActualWidth - popupSize.Width - 8.0f); - horizontalOffset = Math.Min(horizontalOffset, maxHorizontalOffset); - - double verticalOffset = editorPoint.Y - popupSize.Height - lineSlack - 8.0f; - - if (verticalOffset < 0.0) - verticalOffset = Math.Min(Math.Max(0.0, ActualHeight - popupSize.Height), editorPoint.Y + lineHeight + 4.0f); - - _signaturePopup.HorizontalOffset = horizontalOffset; - _signaturePopup.VerticalOffset = verticalOffset; - } + Point caretViewportPoint = new( + caretRectangle.X - scrollOffset.X, + caretRectangle.Y - scrollOffset.Y); + + Point editorPoint = TextArea.TextView.TranslatePoint(caretViewportPoint, this); + double lineHeight = Math.Max(TextArea.TextView.DefaultLineHeight, caretRectangle.Height); + double lineSlack = Math.Max(0.0, lineHeight - caretRectangle.Height); + double horizontalOffset = Math.Max(0.0, editorPoint.X + 2.0f); + double maxHorizontalOffset = Math.Max(0.0, ActualWidth - popupSize.Width - 8.0f); + horizontalOffset = Math.Min(horizontalOffset, maxHorizontalOffset); + + double verticalOffset = editorPoint.Y - popupSize.Height - lineSlack - 8.0f; + + if (verticalOffset < 0.0) + verticalOffset = Math.Min(Math.Max(0.0, ActualHeight - popupSize.Height), editorPoint.Y + lineHeight + 4.0f); - private async Task RequestSignatureHelpAsync(int offset) + _signaturePopup.HorizontalOffset = horizontalOffset; + _signaturePopup.VerticalOffset = verticalOffset; + } + + private async Task RequestSignatureHelpAsync(int offset) + { + if (!IsIntellisenseAvailable()) { - if (!IsIntellisenseAvailable()) - { - DismissSignatureHelp(); - return; - } + DismissSignatureHelp(); + return; + } - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _signatureCancellationTokenSource); + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _signatureCancellationTokenSource); - try - { - (int line, int column) = GetPositionFromOffset(offset); - LuaSignatureInfo? signatureInfo = await IntellisenseProvider - .GetSignatureHelpAsync(FilePath, Text, line, column, cancellationToken) - .ConfigureAwait(true); + try + { + (int line, int column) = GetPositionFromOffset(offset); - if (cancellationToken.IsCancellationRequested) - return; + LuaSignatureInfo? signatureInfo = await IntellisenseProvider + .GetSignatureHelpAsync(FilePath, Text, line, column, cancellationToken) + .ConfigureAwait(true); - if (signatureInfo is null) - { - DismissSignatureHelp(); - return; - } + if (cancellationToken.IsCancellationRequested) + return; - ShowSignatureToolTip(signatureInfo); - } - catch (OperationCanceledException) - { - } - catch (Exception exception) + if (signatureInfo is null) { - WriteDebugFailure("Signature help", exception); + DismissSignatureHelp(); + return; } + + ShowSignatureToolTip(signatureInfo); } + catch (OperationCanceledException) + { } + catch (Exception exception) + { + WriteDebugFailure("Signature help", exception); + } + } - private void ScheduleSignatureHelpRefresh() - => Dispatcher.BeginInvoke(new Action(() => _ = RequestSignatureHelpAsync(CaretOffset))); + private void ScheduleSignatureHelpRefresh() + => Dispatcher.BeginInvoke(new Action(() => _ = RequestSignatureHelpAsync(CaretOffset))); - private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo, LuaThemeBrushSet brushSet) + private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo, LuaThemeBrushSet brushSet) + { + var textBlock = new TextBlock { - var textBlock = new TextBlock - { - FontFamily = new FontFamily("Consolas"), - FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), - TextWrapping = TextWrapping.Wrap, - Foreground = brushSet.SignatureForeground - }; - - string label = signatureInfo.Label; - int paramStart = label.IndexOf('('); + FontFamily = new FontFamily("Consolas"), + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), + TextWrapping = TextWrapping.Wrap, + Foreground = brushSet.SignatureForeground + }; - if (paramStart < 0 || signatureInfo.Parameters.Count == 0) - { - textBlock.Text = label; - return textBlock; - } + string label = signatureInfo.Label; + int paramStart = label.IndexOf('('); - textBlock.Inlines.Add(new Run(label[..(paramStart + 1)])); + if (paramStart < 0 || signatureInfo.Parameters.Count == 0) + { + textBlock.Text = label; + return textBlock; + } - string paramSection = label[(paramStart + 1)..]; - int closingParen = paramSection.LastIndexOf(')'); + textBlock.Inlines.Add(new Run(label[..(paramStart + 1)])); - if (closingParen >= 0) - paramSection = paramSection[..closingParen]; + string paramSection = label[(paramStart + 1)..]; + int closingParen = paramSection.LastIndexOf(')'); - string[] parameterNames = paramSection.Split(','); + if (closingParen >= 0) + paramSection = paramSection[..closingParen]; - for (int i = 0; i < parameterNames.Length; i++) - { - if (i > 0) - textBlock.Inlines.Add(new Run(", ")); + string[] parameterNames = paramSection.Split(','); - var run = new Run(parameterNames[i].Trim()); + for (int i = 0; i < parameterNames.Length; i++) + { + if (i > 0) + textBlock.Inlines.Add(new Run(", ")); - if (i == signatureInfo.ActiveParameter) - { - run.FontWeight = FontWeights.Bold; - run.Foreground = brushSet.SignatureActiveParamForeground; - } + var run = new Run(parameterNames[i].Trim()); - textBlock.Inlines.Add(run); + if (i == signatureInfo.ActiveParameter) + { + run.FontWeight = FontWeights.Bold; + run.Foreground = brushSet.SignatureActiveParamForeground; } - textBlock.Inlines.Add(new Run(")")); - return textBlock; + textBlock.Inlines.Add(run); } + + textBlock.Inlines.Add(new Run(")")); + return textBlock; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index 10616f95fb..34799c0333 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -1,54 +1,53 @@ -using ICSharpCode.AvalonEdit.Highlighting; using System; using TombLib.Scripting.Bases; using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Lua.Services; using TombLib.Scripting.Lua.Resources; +using TombLib.Scripting.Lua.Services; + +namespace TombLib.Scripting.Lua; -namespace TombLib.Scripting.Lua +public sealed partial class LuaEditor : TextEditorBase { - public sealed partial class LuaEditor : TextEditorBase + public override string DefaultFileExtension => ".lua"; + + private LuaTextMateInstallation? _textMateHighlighting; + private LuaThemeBrushSet? _themeBrushSet; + + public ILuaIntellisenseProvider? IntellisenseProvider { get; set; } + + public event Action? DefinitionNavigationRequested; + + public LuaEditor(Version engineVersion) : base(engineVersion) + { + CommentPrefix = "--"; + InitializeSignaturePopup(); + BindLuaIntellisenseEvents(); + } + + public override void UpdateSettings(Bases.ConfigurationBase configuration) + { + var config = configuration as LuaEditorConfiguration; + var theme = config?.Theme ?? LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName); + _themeBrushSet = LuaEditorColorPalette.Create(theme); + _textMateHighlighting?.Dispose(); + _textMateHighlighting = null; + + LuaTextMateSyntaxHighlighting.TryInstall(this, theme.TextMateTheme, out _textMateHighlighting); + SyntaxHighlighting = null; + + EnsureSemanticTokensColorizerAttached(); + + Background = _themeBrushSet.EditorBackground; + Foreground = _themeBrushSet.EditorForeground; + + base.UpdateSettings(configuration); + LiveErrorUnderlining = true; + } + + private LuaThemeBrushSet GetThemeBrushSet() { - public override string DefaultFileExtension => ".lua"; - - private LuaTextMateInstallation? _textMateHighlighting; - private LuaThemeBrushSet? _themeBrushSet; - - public ILuaIntellisenseProvider? IntellisenseProvider { get; set; } - public event Action? DefinitionNavigationRequested; - - public LuaEditor(Version engineVersion) : base(engineVersion) - { - CommentPrefix = "--"; - InitializeSignaturePopup(); - BindLuaIntellisenseEvents(); - } - - public override void UpdateSettings(Bases.ConfigurationBase configuration) - { - var config = configuration as LuaEditorConfiguration; - var theme = config?.Theme ?? LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName); - _themeBrushSet = LuaEditorColorPalette.Create(theme); - _textMateHighlighting?.Dispose(); - _textMateHighlighting = null; - - LuaTextMateSyntaxHighlighting.TryInstall(this, theme.TextMateTheme, out _textMateHighlighting); - SyntaxHighlighting = null; - - EnsureSemanticTokensColorizerAttached(); - - Background = _themeBrushSet.EditorBackground; - Foreground = _themeBrushSet.EditorForeground; - - base.UpdateSettings(configuration); - LiveErrorUnderlining = true; - } - - private LuaThemeBrushSet GetThemeBrushSet() - { - _themeBrushSet ??= LuaEditorColorPalette.Create(LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName)); - return _themeBrushSet; - } + _themeBrushSet ??= LuaEditorColorPalette.Create(LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName)); + return _themeBrushSet; } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs index e914793afb..c3a3b633f0 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs @@ -3,41 +3,37 @@ using TombLib.Scripting.Bases; using TombLib.Scripting.Lua.Resources; -namespace TombLib.Scripting.Lua +namespace TombLib.Scripting.Lua; + +public sealed class LuaEditorConfiguration : TextEditorConfigBase { - public sealed class LuaEditorConfiguration : TextEditorConfigBase - { - public override string DefaultPath { get; } + public override string DefaultPath { get; } - private string _selectedThemeName = ConfigurationDefaults.SelectedThemeName; + private string _selectedThemeName = ConfigurationDefaults.SelectedThemeName; - public string SelectedThemeName + public string SelectedThemeName + { + get => _selectedThemeName; + set { - get => _selectedThemeName; - set - { - _selectedThemeName = LuaThemeRepository.ResolveThemeName(value); + _selectedThemeName = LuaThemeRepository.ResolveThemeName(value); - Theme = LuaThemeRepository.GetTheme(_selectedThemeName); - } + Theme = LuaThemeRepository.GetTheme(_selectedThemeName); } + } - [XmlIgnore] - public Objects.LuaTheme Theme { get; private set; } = LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName); - - public string SelectedColorSchemeName - { - get => SelectedThemeName; - set => SelectedThemeName = value; - } + [XmlIgnore] + public Objects.LuaTheme Theme { get; private set; } = LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName); - public LuaEditorConfiguration() - { - DefaultPath = Path.Combine(DefaultPaths.TextEditorConfigsDirectory, ConfigurationDefaults.ConfigurationFileName); - SelectedThemeName = ConfigurationDefaults.SelectedThemeName; - } + public string SelectedColorSchemeName + { + get => SelectedThemeName; + set => SelectedThemeName = value; + } - public bool ShouldSerializeSelectedColorSchemeName() - => false; + public LuaEditorConfiguration() + { + DefaultPath = Path.Combine(DefaultPaths.TextEditorConfigsDirectory, ConfigurationDefaults.ConfigurationFileName); + SelectedThemeName = ConfigurationDefaults.SelectedThemeName; } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaTextBox.resx b/TombLib/TombLib.Scripting.Lua/LuaTextBox.resx deleted file mode 100644 index 1af7de150c..0000000000 --- a/TombLib/TombLib.Scripting.Lua/LuaTextBox.resx +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index 967990ce7b..fb427e5f92 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -1,3 +1,6 @@ +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Editing; using System; using System.ComponentModel; using System.Runtime.CompilerServices; @@ -6,164 +9,162 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Media; -using ICSharpCode.AvalonEdit.CodeCompletion; -using ICSharpCode.AvalonEdit.Document; -using ICSharpCode.AvalonEdit.Editing; +using TombLib.Scripting.Lua.Resources; using TombLib.Scripting.Rendering; using TombLib.Scripting.Resources; -using TombLib.Scripting.Lua.Resources; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged { - internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged - { - private const double DescriptionMaxWidth = 540.0; - private const double DescriptionTextMaxWidth = 500.0; - private static readonly SolidColorBrush DescriptionBorderBrush = TextEditorColorPalette.ToolTipBorder; - private static readonly SolidColorBrush DescriptionBackgroundBrush = TextEditorColorPalette.ToolTipBackground; - private static readonly SolidColorBrush DescriptionForegroundBrush = TextEditorColorPalette.ToolTipForeground; - private readonly object _resolveSync = new object(); - private readonly LuaThemeBrushSet _brushSet; - private LuaCompletionItem _item; - private string? _displayDetail; - private object? _cachedDescription; - private Task? _resolveTask; - - public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet) - { - _item = item ?? throw new ArgumentNullException(nameof(item)); - _brushSet = brushSet ?? throw new ArgumentNullException(nameof(brushSet)); - _displayDetail = FlattenSingleLineText(_item.Detail); - } + private const double DescriptionMaxWidth = 540.0; + private const double DescriptionTextMaxWidth = 500.0; - public event PropertyChangedEventHandler? PropertyChanged; + private static readonly SolidColorBrush DescriptionBorderBrush = TextEditorColorPalette.ToolTipBorder; + private static readonly SolidColorBrush DescriptionBackgroundBrush = TextEditorColorPalette.ToolTipBackground; + private static readonly SolidColorBrush DescriptionForegroundBrush = TextEditorColorPalette.ToolTipForeground; - public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind, _brushSet); - public string Text => _item.FilterText; - public string DisplayText => _item.Label; - public string? DisplayDetail => _displayDetail; - public Visibility DetailVisibility => string.IsNullOrEmpty(_displayDetail) ? Visibility.Collapsed : Visibility.Visible; - public object Content => DisplayText; - public object? Description => _cachedDescription ??= BuildDescriptionContent(); - public double Priority => _item.Priority; - public bool CanResolve => _item.CanResolve; + private readonly object _resolveSync = new(); - public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) - => textArea.Document.Replace(completionSegment, _item.InsertText); + private readonly LuaThemeBrushSet _brushSet; + private LuaCompletionItem _item; + private string? _displayDetail; + private object? _cachedDescription; + private Task? _resolveTask; - public async Task GetDescriptionAsync(CancellationToken cancellationToken = default) - { - if (!CanResolve) - return Description; + public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet) + { + _item = item ?? throw new ArgumentNullException(nameof(item)); + _brushSet = brushSet ?? throw new ArgumentNullException(nameof(brushSet)); + _displayDetail = FlattenSingleLineText(_item.Detail); + } - Task resolveTask; + public event PropertyChangedEventHandler? PropertyChanged; - lock (_resolveSync) - { - if (!CanResolve) - return Description; + public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind, _brushSet); + public string Text => _item.FilterText; + public string DisplayText => _item.Label; + public string? DisplayDetail => _displayDetail; + public Visibility DetailVisibility => string.IsNullOrEmpty(_displayDetail) ? Visibility.Collapsed : Visibility.Visible; + public object Content => DisplayText; + public object? Description => _cachedDescription ??= BuildDescriptionContent(); + public double Priority => _item.Priority; + public bool CanResolve => _item.CanResolve; - if (_resolveTask is null || _resolveTask.IsCanceled || _resolveTask.IsFaulted) - _resolveTask = _item.ResolveAsync(cancellationToken); + public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) + => textArea.Document.Replace(completionSegment, _item.InsertText); - resolveTask = _resolveTask; - } + public async Task GetDescriptionAsync(CancellationToken cancellationToken = default) + { + if (!CanResolve) + return Description; - try - { - LuaCompletionItem resolvedItem = cancellationToken.CanBeCanceled - ? await resolveTask.WaitAsync(cancellationToken).ConfigureAwait(true) - : await resolveTask.ConfigureAwait(true); + Task resolveTask; - ApplyResolvedItem(resolvedItem); + lock (_resolveSync) + { + if (!CanResolve) return Description; - } - catch - { - lock (_resolveSync) - { - if (ReferenceEquals(_resolveTask, resolveTask)) - _resolveTask = null; - } - throw; - } + if (_resolveTask?.IsCanceled != false || _resolveTask.IsFaulted) + _resolveTask = _item.ResolveAsync(cancellationToken); + + resolveTask = _resolveTask; } - private static string? FlattenSingleLineText(string? text) + try { - if (string.IsNullOrWhiteSpace(text)) - return null; + LuaCompletionItem resolvedItem = cancellationToken.CanBeCanceled + ? await resolveTask.WaitAsync(cancellationToken).ConfigureAwait(true) + : await resolveTask.ConfigureAwait(true); - string[] lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); - return lines.Length == 0 ? null : string.Join(" ", lines).Trim(); + ApplyResolvedItem(resolvedItem); + return Description; } - - private object? BuildDescriptionContent() + catch { - bool hasDetail = !string.IsNullOrWhiteSpace(_item.Detail); - bool hasDescription = !string.IsNullOrWhiteSpace(_item.Description); + lock (_resolveSync) + { + if (ReferenceEquals(_resolveTask, resolveTask)) + _resolveTask = null; + } - if (!hasDetail && !hasDescription) - return null; + throw; + } + } - var panel = new StackPanel - { - MaxWidth = DescriptionMaxWidth - }; + private static string? FlattenSingleLineText(string? text) + { + if (string.IsNullOrWhiteSpace(text)) + return null; - if (hasDetail) - { - panel.Children.Add(new TextBlock - { - Text = _item.Detail, - Foreground = DescriptionForegroundBrush, - TextWrapping = TextWrapping.Wrap, - MaxWidth = DescriptionTextMaxWidth, - FontWeight = FontWeights.SemiBold, - Margin = hasDescription - ? new Thickness(0.0, 0.0, 0.0, 8.0) - : new Thickness(0.0) - }); - } + string[] lines = text.Split(['\r', '\n'], StringSplitOptions.RemoveEmptyEntries); + return lines.Length == 0 ? null : string.Join(" ", lines).Trim(); + } - if (hasDescription) - { - string descriptionText = _item.Description!; + private object? BuildDescriptionContent() + { + bool hasDetail = !string.IsNullOrWhiteSpace(_item.Detail); + bool hasDescription = !string.IsNullOrWhiteSpace(_item.Description); - panel.Children.Add(_item.IsDescriptionMarkdown - ? MarkdownToolTipRenderer.CreateContent(descriptionText, DescriptionForegroundBrush, DescriptionBackgroundBrush, false) - : MarkdownToolTipRenderer.CreatePlainTextContent(descriptionText, DescriptionForegroundBrush, false)); - } + if (!hasDetail && !hasDescription) + return null; - return new Border + var panel = new StackPanel + { + MaxWidth = DescriptionMaxWidth + }; + + if (hasDetail) + { + panel.Children.Add(new TextBlock { - Background = DescriptionBackgroundBrush, - BorderBrush = DescriptionBorderBrush, - BorderThickness = new Thickness(1.0), - Padding = new Thickness(8.0, 6.0, 8.0, 6.0), - Child = panel, - MaxWidth = DescriptionMaxWidth - }; + Text = _item.Detail, + Foreground = DescriptionForegroundBrush, + TextWrapping = TextWrapping.Wrap, + MaxWidth = DescriptionTextMaxWidth, + FontWeight = FontWeights.SemiBold, + Margin = hasDescription + ? new Thickness(0.0, 0.0, 0.0, 8.0) + : new Thickness(0.0) + }); } - private void ApplyResolvedItem(LuaCompletionItem resolvedItem) + if (hasDescription) { - if (resolvedItem is null || ReferenceEquals(resolvedItem, _item)) - return; - - _item = resolvedItem; - _displayDetail = FlattenSingleLineText(_item.Detail); - _cachedDescription = null; + string descriptionText = _item.Description!; - OnPropertyChanged(nameof(Image)); - OnPropertyChanged(nameof(DisplayDetail)); - OnPropertyChanged(nameof(DetailVisibility)); - OnPropertyChanged(nameof(Description)); + panel.Children.Add(_item.IsDescriptionMarkdown + ? MarkdownToolTipRenderer.CreateContent(descriptionText, DescriptionForegroundBrush, DescriptionBackgroundBrush, false) + : MarkdownToolTipRenderer.CreatePlainTextContent(descriptionText, DescriptionForegroundBrush, false)); } - private void OnPropertyChanged([CallerMemberName] string? propertyName = null) - => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + return new Border + { + Background = DescriptionBackgroundBrush, + BorderBrush = DescriptionBorderBrush, + BorderThickness = new Thickness(1.0), + Padding = new Thickness(8.0, 6.0, 8.0, 6.0), + Child = panel, + MaxWidth = DescriptionMaxWidth + }; + } + + private void ApplyResolvedItem(LuaCompletionItem resolvedItem) + { + if (resolvedItem is null || ReferenceEquals(resolvedItem, _item)) + return; + + _item = resolvedItem; + _displayDetail = FlattenSingleLineText(_item.Detail); + _cachedDescription = null; + OnPropertyChanged(nameof(Image)); + OnPropertyChanged(nameof(DisplayDetail)); + OnPropertyChanged(nameof(DetailVisibility)); + OnPropertyChanged(nameof(Description)); } -} \ No newline at end of file + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs index 1a3e6e7bbb..286f95a38a 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -2,113 +2,111 @@ using System.Windows.Media; using TombLib.Scripting.Lua.Resources; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +// Geometry paths below are vendored from microsoft/vscode-codicons under the MIT license. +internal static class LuaCompletionIconFactory { - // Geometry paths below are vendored from microsoft/vscode-codicons under the MIT license. - internal static class LuaCompletionIconFactory + private static readonly Dictionary Cache = []; + + public static ImageSource GetIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) { - private static readonly Dictionary Cache = new Dictionary(); + string cacheKey = brushSet.ThemeName + ":" + kind; - public static ImageSource GetIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) + lock (Cache) { - string cacheKey = brushSet.ThemeName + ":" + kind; - - lock (Cache) - { - if (Cache.TryGetValue(cacheKey, out ImageSource? image)) - return image; - - image = CreateIcon(kind, brushSet); - Cache[cacheKey] = image; + if (Cache.TryGetValue(cacheKey, out ImageSource? image)) return image; - } + + image = CreateIcon(kind, brushSet); + Cache[cacheKey] = image; + return image; } + } - private static ImageSource CreateIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) - { - var drawingGroup = new DrawingGroup(); + private static ImageSource CreateIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) + { + var drawingGroup = new DrawingGroup(); - foreach (string pathData in GetPathData(kind)) - drawingGroup.Children.Add(CreatePathDrawing(brushSet.GetCompletionItemBrush(kind), pathData)); + foreach (string pathData in GetPathData(kind)) + drawingGroup.Children.Add(CreatePathDrawing(brushSet.GetCompletionItemBrush(kind), pathData)); - drawingGroup.Freeze(); + drawingGroup.Freeze(); - var image = new DrawingImage(drawingGroup); - image.Freeze(); - return image; - } + var image = new DrawingImage(drawingGroup); + image.Freeze(); + return image; + } - private static GeometryDrawing CreatePathDrawing(Brush brush, string pathData) - { - Geometry geometry = Geometry.Parse(pathData); - geometry.Freeze(); - return new GeometryDrawing(brush, null, geometry); - } + private static GeometryDrawing CreatePathDrawing(Brush brush, string pathData) + { + Geometry geometry = Geometry.Parse(pathData); + geometry.Freeze(); + return new GeometryDrawing(brush, null, geometry); + } - private static string[] GetPathData(LuaCompletionIconKind kind) + private static string[] GetPathData(LuaCompletionIconKind kind) + { + return kind switch { - return kind switch - { - LuaCompletionIconKind.Variable => new[] - { - "M11.279 5.78975L8.799 5.06575C8.59 5.00575 8.372 5.01475 8.168 5.08975L4.648 6.40975C4.26 6.55575 4 6.93175 4 7.34675V9.13975C4 9.57075 4.274 9.95175 4.684 10.0877L7.165 10.9147C7.268 10.9497 7.376 10.9667 7.483 10.9667C7.611 10.9667 7.739 10.9427 7.859 10.8937L11.376 9.46475C11.755 9.31175 12 8.94775 12 8.53875V6.74975C12 6.30775 11.703 5.91275 11.279 5.78975ZM11 8.53875L7.483 9.96775L5 9.13975V7.34675L8.521 6.02675L11 6.75075V8.53975V8.53875ZM7.48 7.46675L8.807 6.91375C9.06 6.80875 9.355 6.92775 9.461 7.18275C9.566 7.43775 9.446 7.73075 9.191 7.83675L7.999 8.33375V8.62575C7.999 8.90175 7.775 9.12575 7.499 9.12575C7.223 9.12575 6.999 8.90175 6.999 8.62575V8.36075L6.591 8.22475C6.329 8.13775 6.188 7.85475 6.275 7.59275C6.364 7.33075 6.647 7.19175 6.908 7.27675L7.48 7.46675Z", - "M12.5 14H11.5C11.224 14 11 13.776 11 13.5C11 13.224 11.224 13 11.5 13H12.5C12.776 13 13 12.775 13 12.5V3.5C13 3.225 12.776 3 12.5 3H11.5C11.224 3 11 2.776 11 2.5C11 2.224 11.224 2 11.5 2H12.5C13.327 2 14 2.673 14 3.5V12.5C14 13.327 13.327 14 12.5 14ZM5 13.5C5 13.224 4.776 13 4.5 13H3.5C3.224 13 3 12.775 3 12.5V3.5C3 3.225 3.224 3 3.5 3H4.5C4.776 3 5 2.776 5 2.5C5 2.224 4.776 2 4.5 2H3.5C2.673 2 2 2.673 2 3.5V12.5C2 13.327 2.673 14 3.5 14H4.5C4.776 14 5 13.776 5 13.5Z" - }, - LuaCompletionIconKind.Field => new[] - { - "M11.967 6.08899C11.9907 6.15031 12.0021 6.2157 12.0005 6.28143C11.9989 6.34715 11.9843 6.41191 11.9577 6.47201C11.931 6.5321 11.8928 6.58635 11.8451 6.63165C11.7975 6.67695 11.7414 6.7124 11.68 6.73599L7.5 8.34399V10.02C7.5 10.1526 7.44732 10.2798 7.35355 10.3735C7.25979 10.4673 7.13261 10.52 7 10.52C6.86739 10.52 6.74021 10.4673 6.64645 10.3735C6.55268 10.2798 6.5 10.1526 6.5 10.02V8.34299L4.32 7.50499C4.25874 7.48135 4.20273 7.44588 4.15518 7.40059C4.10763 7.35531 4.06946 7.30111 4.04286 7.24107C4.01625 7.18104 4.00173 7.11635 4.00013 7.05071C3.99852 6.98507 4.00986 6.91975 4.0335 6.85849C4.05714 6.79722 4.09261 6.74122 4.13789 6.69367C4.18318 6.64611 4.23738 6.60795 4.29741 6.58134C4.35745 6.55474 4.42213 6.54022 4.48778 6.53861C4.55342 6.53701 4.61874 6.54835 4.68 6.57199L7 7.46399L11.32 5.79999C11.3814 5.77634 11.447 5.76505 11.5128 5.76678C11.5786 5.76852 11.6434 5.78323 11.7035 5.81008C11.7636 5.83694 11.8179 5.8754 11.8631 5.92326C11.9083 5.97112 11.9436 6.02744 11.967 6.08899ZM15 5.79999V9.42899C14.9986 9.73191 14.9061 10.0274 14.7345 10.2771C14.563 10.5268 14.3203 10.7191 14.038 10.829L7.538 13.329C7.19108 13.4626 6.80692 13.4626 6.46 13.329L1.961 11.6C1.67891 11.4899 1.43643 11.2975 1.26506 11.0479C1.09369 10.7982 1.00134 10.5028 1 10.2V6.57099C1.00155 6.26809 1.0941 5.97265 1.26565 5.72301C1.43719 5.47336 1.6798 5.28104 1.962 5.17099L8.462 2.67099C8.80902 2.53798 9.19298 2.53798 9.54 2.67099L14.04 4.40199C14.3215 4.51223 14.5635 4.70438 14.7346 4.95361C14.9058 5.20283 14.9982 5.49766 15 5.79999ZM14 5.79999C14 5.69881 13.9694 5.6 13.912 5.51662C13.8547 5.43324 13.7735 5.36921 13.679 5.33299L9.179 3.60299C9.06398 3.55763 8.93602 3.55763 8.821 3.60299L2.321 6.10299C2.22637 6.13927 2.145 6.20345 2.08767 6.28703C2.03034 6.37061 1.99977 6.46964 2 6.57099V10.2C2.0001 10.3009 2.03071 10.3994 2.08782 10.4825C2.14494 10.5657 2.22587 10.6297 2.32 10.666L6.82 12.398C6.93524 12.4422 7.06276 12.4422 7.178 12.398L13.678 9.89799C13.773 9.8618 13.8547 9.79754 13.9122 9.71375C13.9697 9.62996 14.0004 9.53062 14 9.42899V5.79999Z" - }, - LuaCompletionIconKind.Method => new[] - { - "M4.69684 5.04043C4.44303 4.93166 4.14909 5.04923 4.04031 5.30305C3.93153 5.55686 4.04911 5.8508 4.30292 5.95958L7.49988 7.3297V10.5C7.49988 10.7761 7.72374 11 7.99988 11C8.27603 11 8.49988 10.7761 8.49988 10.5V7.3297L11.6968 5.95958C11.9507 5.8508 12.0682 5.55686 11.9595 5.30305C11.8507 5.04923 11.5567 4.93166 11.3029 5.04043L7.99988 6.45602L4.69684 5.04043ZM9.07694 1.37855C8.38373 1.11193 7.61627 1.11193 6.92306 1.37855L1.96153 3.28683C1.38224 3.50964 1 4.06619 1 4.68685V11.3133C1 11.9339 1.38224 12.4905 1.96153 12.7133L6.92306 14.6216C7.61627 14.8882 8.38373 14.8882 9.07694 14.6216L14.0385 12.7133C14.6178 12.4905 15 11.9339 15 11.3133V4.68685C15 4.06619 14.6178 3.50964 14.0385 3.28683L9.07694 1.37855ZM7.28204 2.3119C7.74418 2.13415 8.25582 2.13415 8.71796 2.3119L13.6795 4.22018C13.8726 4.29445 14 4.47997 14 4.68685V11.3133C14 11.5201 13.8726 11.7057 13.6795 11.7799L8.71796 13.6882C8.25582 13.866 7.74418 13.866 7.28204 13.6882L2.32051 11.7799C2.12741 11.7057 2 11.5201 2 11.3133V4.68685C2 4.47997 2.12741 4.29445 2.32051 4.22018L7.28204 2.3119Z" - }, - LuaCompletionIconKind.Property => new[] - { - "M6.99989 5C6.99989 2.79086 8.79075 1 10.9999 1C11.5087 1 11.9964 1.09524 12.4454 1.26931C12.603 1.3304 12.719 1.46698 12.7539 1.63235C12.7888 1.79773 12.7377 1.96953 12.6182 2.08904L10.7072 4.00012L12.0001 5.29302L13.911 3.38207C14.0305 3.26254 14.2023 3.2115 14.3677 3.24637C14.5331 3.28125 14.6697 3.39732 14.7307 3.55493C14.9047 4.0038 14.9999 4.49138 14.9999 5C14.9999 7.20914 13.209 9 10.9999 9C10.6198 9 10.2514 8.94684 9.90215 8.84736L4.89566 13.9192C4.18171 14.6425 3.03692 14.7101 2.24289 14.0757C1.32876 13.3455 1.24088 11.9872 2.05327 11.1453L7.10411 5.91061C7.03588 5.61771 6.99989 5.31279 6.99989 5ZM10.9999 2C9.34303 2 7.99989 3.34315 7.99989 5C7.99989 5.31548 8.04841 5.61868 8.13805 5.90305C8.19313 6.07781 8.14821 6.26869 8.02099 6.40054L2.7729 11.8396C2.3696 12.2576 2.41323 12.9319 2.86703 13.2944C3.26123 13.6093 3.82955 13.5758 4.18398 13.2167L9.40817 7.9243C9.54702 7.78364 9.75569 7.73797 9.9406 7.80777C10.2693 7.93186 10.6261 8 10.9999 8C12.6567 8 13.9999 6.65685 13.9999 5C13.9999 4.9056 13.9955 4.81228 13.987 4.72023L12.3537 6.35368C12.2599 6.44745 12.1327 6.50013 12.0001 6.50013C11.8675 6.50013 11.7403 6.44745 11.6466 6.35368L9.64655 4.35368C9.45129 4.15842 9.45129 3.84185 9.64655 3.64658L11.2802 2.01289C11.188 2.00436 11.0945 2 10.9999 2Z" - }, - LuaCompletionIconKind.Class => new[] - { - "M13.2069 10.4999C13.0194 10.3125 12.7651 10.2072 12.4999 10.2072C12.2348 10.2072 11.9805 10.3125 11.7929 10.4999L11.2929 10.9999H8.99994V6.99994H10.3629C10.2479 7.1876 10.1989 7.40832 10.2238 7.62701C10.2486 7.84571 10.3458 8.04983 10.4999 8.20694L11.2929 8.99994C11.4805 9.18741 11.7348 9.29273 11.9999 9.29273C12.2651 9.29273 12.5194 9.18741 12.7069 8.99994L13.9999 7.70694C14.1874 7.51941 14.2927 7.2651 14.2927 6.99994C14.2927 6.73478 14.1874 6.48047 13.9999 6.29294L13.2069 5.49994C13.0194 5.31247 12.7651 5.20715 12.4999 5.20715C12.2348 5.20715 11.9805 5.31247 11.7929 5.49994L11.2929 5.99994H6.70694L7.49994 5.20694C7.68741 5.01941 7.79273 4.7651 7.79273 4.49994C7.79273 4.23478 7.68741 3.98047 7.49994 3.79294L6.20694 2.49994C6.01941 2.31247 5.7651 2.20715 5.49994 2.20715C5.23478 2.20715 4.98047 2.31247 4.79294 2.49994L1.49994 5.79294C1.31247 5.98047 1.20715 6.23478 1.20715 6.49994C1.20715 6.7651 1.31247 7.01941 1.49994 7.20694L2.79294 8.49994C2.98047 8.68741 3.23478 8.79273 3.49994 8.79273C3.7651 8.79273 4.01941 8.68741 4.20694 8.49994L5.70694 6.99994H7.99994V11.4999C7.99994 11.6325 8.05262 11.7597 8.14639 11.8535C8.24015 11.9473 8.36733 11.9999 8.49994 11.9999H10.3629C10.2479 12.1876 10.1989 12.4083 10.2238 12.627C10.2486 12.8457 10.3458 13.0498 10.4999 13.2069L11.2929 13.9999C11.4805 14.1874 11.7348 14.2927 11.9999 14.2927C12.2651 14.2927 12.5194 14.1874 12.7069 13.9999L13.9999 12.7069C14.1874 12.5194 14.2927 12.2651 14.2927 11.9999C14.2927 11.7348 14.1874 11.4805 13.9999 11.2929L13.2069 10.4999ZM3.49994 7.79294L2.20694 6.49994L5.49994 3.20694L6.79294 4.49994L3.49994 7.79294ZM13.2929 6.99994L11.9999 8.29294L11.2069 7.49994L12.4999 6.20694L13.2929 6.99994ZM11.9999 13.2929L11.2069 12.4999L12.4999 11.2069L13.2929 11.9999L11.9999 13.2929Z" - }, - LuaCompletionIconKind.Keyword => new[] - { - "M9.5 14C9.77614 14 10 14.2239 10 14.5C10 14.7761 9.77614 15 9.5 15H2.5C2.22386 15 2 14.7761 2 14.5C2 14.2239 2.22386 14 2.5 14H9.5Z", - "M6.5 11C6.77614 11 7 11.2239 7 11.5C7 11.7761 6.77614 12 6.5 12H2.5C2.22386 12 2 11.7761 2 11.5C2 11.2239 2.22386 11 2.5 11H6.5Z", - "M13.5 11C13.7761 11 14 11.2239 14 11.5C14 11.7761 13.7761 12 13.5 12H8.5C8.22386 12 8 11.7761 8 11.5C8 11.2239 8.22386 11 8.5 11H13.5Z", - "M8.5 8C8.77614 8 9 8.22386 9 8.5C9 8.77614 8.77614 9 8.5 9H2.5C2.22386 9 2 8.77614 2 8.5C2 8.22386 2.22386 8 2.5 8H8.5Z", - "M13.5 8C13.7761 8 14 8.22386 14 8.5C14 8.77614 13.7761 9 13.5 9H10.5C10.2239 9 10 8.77614 10 8.5C10 8.22386 10.2239 8 10.5 8H13.5Z", - "M9 2C9.55228 2 10 2.44772 10 3V5C10 5.55228 9.55228 6 9 6H3C2.44772 6 2 5.55228 2 5V3C2 2.44772 2.44772 2 3 2H9ZM3 5H9V3H3V5Z", - "M13.5 4C13.7761 4 14 4.22386 14 4.5C14 4.77614 13.7761 5 13.5 5H11.5C11.2239 5 11 4.77614 11 4.5C11 4.22386 11.2239 4 11.5 4H13.5Z" - }, - LuaCompletionIconKind.Constant => new[] - { - "M4.5 2C3.83696 2 3.20107 2.26339 2.73223 2.73223C2.26339 3.20107 2 3.83696 2 4.5V11.5C2 12.163 2.26339 12.7989 2.73223 13.2678C3.20107 13.7366 3.83696 14 4.5 14H11.5C12.163 14 12.7989 13.7366 13.2678 13.2678C13.7366 12.7989 14 12.163 14 11.5V4.5C14 3.83696 13.7366 3.20107 13.2678 2.73223C12.7989 2.26339 12.163 2 11.5 2H4.5ZM3 4.5C3 4.10218 3.15804 3.72064 3.43934 3.43934C3.72064 3.15804 4.10218 3 4.5 3H11.5C11.8978 3 12.2794 3.15804 12.5607 3.43934C12.842 3.72064 13 4.10218 13 4.5V11.5C13 11.8978 12.842 12.2794 12.5607 12.5607C12.2794 12.842 11.8978 13 11.5 13H4.5C4.10218 13 3.72064 12.842 3.43934 12.5607C3.15804 12.2794 3 11.8978 3 11.5V4.5Z", - "M5 6.5C5 6.36739 5.05268 6.24021 5.14645 6.14645C5.24021 6.05268 5.36739 6 5.5 6H10.5C10.6326 6 10.7598 6.05268 10.8536 6.14645C10.9473 6.24021 11 6.36739 11 6.5C11 6.63261 10.9473 6.75979 10.8536 6.85355C10.7598 6.94732 10.6326 7 10.5 7H5.5C5.36739 7 5.24021 6.94732 5.14645 6.85355C5.05268 6.75979 5 6.63261 5 6.5ZM10.5 9H5.5C5.36739 9 5.24021 9.05268 5.14645 9.14645C5.05268 9.24021 5 9.36739 5 9.5C5 9.63261 5.05268 9.75979 5.14645 9.85355C5.24021 9.94732 5.36739 10 5.5 10H10.5C10.6326 10 10.7598 9.94732 10.8536 9.85355C10.9473 9.75979 11 9.63261 11 9.5C11 9.36739 10.9473 9.24021 10.8536 9.14645C10.7598 9.05268 10.6326 9 10.5 9Z" - }, - LuaCompletionIconKind.Parameter => new[] - { - "M4 3.5C4 3.22386 4.22386 3 4.5 3H11.5C11.7761 3 12 3.22386 12 3.5V4.5C12 4.77614 11.7761 5 11.5 5C11.2239 5 11 4.77614 11 4.5V4H8.5V12H9C9.27614 12 9.5 12.2239 9.5 12.5C9.5 12.7761 9.27614 13 9 13H7C6.72386 13 6.5 12.7761 6.5 12.5C6.5 12.2239 6.72386 12 7 12H7.5V4H5V4.5C5 4.77614 4.77614 5 4.5 5C4.22386 5 4 4.77614 4 4.5V3.5ZM4.35355 6.64645C4.54882 6.84171 4.54882 7.15829 4.35355 7.35355L2.20711 9.5L4.35355 11.6464C4.54882 11.8417 4.54882 12.1583 4.35355 12.3536C4.15829 12.5488 3.84171 12.5488 3.64645 12.3536L1.14645 9.85355C0.951184 9.65829 0.951184 9.34171 1.14645 9.14645L3.64645 6.64645C3.84171 6.45118 4.15829 6.45118 4.35355 6.64645ZM14.8536 9.14645L12.3536 6.64645C12.1583 6.45118 11.8417 6.45118 11.6464 6.64645C11.4512 6.84171 11.4512 7.15829 11.6464 7.35355L13.7929 9.5L11.6464 11.6464C11.4512 11.8417 11.4512 12.1583 11.6464 12.3536C11.8417 12.5488 12.1583 12.5488 12.3536 12.3536L14.8536 9.85355C15.0488 9.65829 15.0488 9.34171 14.8536 9.14645Z" - }, - LuaCompletionIconKind.Namespace => new[] - { - "M5 2C3.89543 2 3 2.89543 3 4V6.00469C3 6.53494 2.99231 6.79889 2.91088 7.00209C2.84826 7.15835 2.71576 7.33309 2.2764 7.55276C2.10701 7.63745 2 7.81058 2 7.99997C2 8.18935 2.10699 8.36249 2.27638 8.44719C2.71569 8.66685 2.84809 8.84151 2.91076 8.99819C2.99233 9.20211 3 9.46732 3 10L3 12C3 13.1046 3.89543 14 5 14C5.27614 14 5.5 13.7761 5.5 13.5C5.5 13.2239 5.27614 13 5 13C4.44772 13 4 12.5523 4 12L4.00003 9.94145C4.00033 9.49235 4.00065 9.03033 3.83924 8.6268C3.74212 8.384 3.59654 8.17962 3.40072 8.00002C3.59646 7.82057 3.74199 7.61645 3.83912 7.37408C4.00065 6.971 4.00033 6.51001 4.00003 6.063L4 4C4 3.44772 4.44772 3 5 3C5.27614 3 5.5 2.77614 5.5 2.5C5.5 2.22386 5.27614 2 5 2ZM11 2C12.1046 2 13 2.89543 13 4V6.00469C13 6.53494 13.0077 6.79889 13.0891 7.00209C13.1517 7.15835 13.2842 7.33309 13.7236 7.55276C13.893 7.63745 14 7.81058 14 7.99997C14 8.18935 13.893 8.36249 13.7236 8.44719C13.2843 8.66685 13.1519 8.84151 13.0892 8.99819C13.0077 9.20211 13 9.46732 13 10V12C13 13.1046 12.1046 14 11 14C10.7239 14 10.5 13.7761 10.5 13.5C10.5 13.2239 10.7239 13 11 13C11.5523 13 12 12.5523 12 12L12 9.94145C11.9997 9.49235 11.9994 9.03033 12.1608 8.6268C12.2579 8.384 12.4035 8.17962 12.5993 8.00002C12.4035 7.82057 12.258 7.61645 12.1609 7.37408C11.9993 6.971 11.9997 6.51001 12 6.063L12 4C12 3.44772 11.5523 3 11 3C10.7239 3 10.5 2.77614 10.5 2.5C10.5 2.22386 10.7239 2 11 2Z" - }, - LuaCompletionIconKind.File => new[] - { - "M5 1C3.89543 1 3 1.89543 3 3V13C3 14.1046 3.89543 15 5 15H11C12.1046 15 13 14.1046 13 13V5.41421C13 5.01639 12.842 4.63486 12.5607 4.35355L9.64645 1.43934C9.36514 1.15804 8.98361 1 8.58579 1H5ZM4 3C4 2.44772 4.44772 2 5 2H8V4.5C8 5.32843 8.67157 6 9.5 6H12V13C12 13.5523 11.5523 14 11 14H5C4.44772 14 4 13.5523 4 13V3ZM11.7929 5H9.5C9.22386 5 9 4.77614 9 4.5V2.20711L11.7929 5Z" - }, - LuaCompletionIconKind.Folder => new[] - { - "M2 4.5V6H5.58579C5.71839 6 5.84557 5.94732 5.93934 5.85355L7.29289 4.5L5.93934 3.14645C5.84557 3.05268 5.71839 3 5.58579 3H3.5C2.67157 3 2 3.67157 2 4.5ZM1 4.5C1 3.11929 2.11929 2 3.5 2H5.58579C5.98361 2 6.36514 2.15804 6.64645 2.43934L8.20711 4H12.5C13.8807 4 15 5.11929 15 6.5V11.5C15 12.8807 13.8807 14 12.5 14H3.5C2.11929 14 1 12.8807 1 11.5V4.5ZM2 7V11.5C2 12.3284 2.67157 13 3.5 13H12.5C13.3284 13 14 12.3284 14 11.5V6.5C14 5.67157 13.3284 5 12.5 5H8.20711L6.64645 6.56066C6.36514 6.84197 5.98361 7 5.58579 7H2Z" - }, - _ => new[] - { - "M11.9999 3C10.1399 3 8.56988 4.27 8.12988 6H9.17988C9.58988 4.84 10.6999 4 11.9999 4C13.6499 4 14.9999 5.35 14.9999 7C14.9999 8.3 14.1599 9.41 12.9999 9.82V10.87C14.7299 10.43 15.9999 8.86 15.9999 7C15.9999 4.79 14.2099 3 11.9999 3Z", - "M10.5 15H5.5C4.673 15 4 14.327 4 13.5V8.5C4 7.673 4.673 7 5.5 7H10.5C11.327 7 12 7.673 12 8.5V13.5C12 14.327 11.327 15 10.5 15ZM5.5 8C5.224 8 5 8.225 5 8.5V13.5C5 13.775 5.224 14 5.5 14H10.5C10.776 14 11 13.775 11 13.5V8.5C11 8.225 10.776 8 10.5 8H5.5Z", - "M4.42973 2.25008C4.24973 1.94008 3.74973 1.94008 3.56973 2.25008L0.0997266 8.25008C0.00972656 8.40008 0.00972656 8.60008 0.0997266 8.75008C0.189727 8.90008 0.359727 9.00008 0.539727 9.00008H2.99973V8.50008C2.99973 8.33008 3.01973 8.16008 3.04973 8.00008H1.39973L3.99973 3.50008L5.44973 6.00008H6.59973L4.42973 2.25008Z" - } - }; - } - + LuaCompletionIconKind.Variable => + [ + "M11.279 5.78975L8.799 5.06575C8.59 5.00575 8.372 5.01475 8.168 5.08975L4.648 6.40975C4.26 6.55575 4 6.93175 4 7.34675V9.13975C4 9.57075 4.274 9.95175 4.684 10.0877L7.165 10.9147C7.268 10.9497 7.376 10.9667 7.483 10.9667C7.611 10.9667 7.739 10.9427 7.859 10.8937L11.376 9.46475C11.755 9.31175 12 8.94775 12 8.53875V6.74975C12 6.30775 11.703 5.91275 11.279 5.78975ZM11 8.53875L7.483 9.96775L5 9.13975V7.34675L8.521 6.02675L11 6.75075V8.53975V8.53875ZM7.48 7.46675L8.807 6.91375C9.06 6.80875 9.355 6.92775 9.461 7.18275C9.566 7.43775 9.446 7.73075 9.191 7.83675L7.999 8.33375V8.62575C7.999 8.90175 7.775 9.12575 7.499 9.12575C7.223 9.12575 6.999 8.90175 6.999 8.62575V8.36075L6.591 8.22475C6.329 8.13775 6.188 7.85475 6.275 7.59275C6.364 7.33075 6.647 7.19175 6.908 7.27675L7.48 7.46675Z", + "M12.5 14H11.5C11.224 14 11 13.776 11 13.5C11 13.224 11.224 13 11.5 13H12.5C12.776 13 13 12.775 13 12.5V3.5C13 3.225 12.776 3 12.5 3H11.5C11.224 3 11 2.776 11 2.5C11 2.224 11.224 2 11.5 2H12.5C13.327 2 14 2.673 14 3.5V12.5C14 13.327 13.327 14 12.5 14ZM5 13.5C5 13.224 4.776 13 4.5 13H3.5C3.224 13 3 12.775 3 12.5V3.5C3 3.225 3.224 3 3.5 3H4.5C4.776 3 5 2.776 5 2.5C5 2.224 4.776 2 4.5 2H3.5C2.673 2 2 2.673 2 3.5V12.5C2 13.327 2.673 14 3.5 14H4.5C4.776 14 5 13.776 5 13.5Z" + ], + LuaCompletionIconKind.Field => + [ + "M11.967 6.08899C11.9907 6.15031 12.0021 6.2157 12.0005 6.28143C11.9989 6.34715 11.9843 6.41191 11.9577 6.47201C11.931 6.5321 11.8928 6.58635 11.8451 6.63165C11.7975 6.67695 11.7414 6.7124 11.68 6.73599L7.5 8.34399V10.02C7.5 10.1526 7.44732 10.2798 7.35355 10.3735C7.25979 10.4673 7.13261 10.52 7 10.52C6.86739 10.52 6.74021 10.4673 6.64645 10.3735C6.55268 10.2798 6.5 10.1526 6.5 10.02V8.34299L4.32 7.50499C4.25874 7.48135 4.20273 7.44588 4.15518 7.40059C4.10763 7.35531 4.06946 7.30111 4.04286 7.24107C4.01625 7.18104 4.00173 7.11635 4.00013 7.05071C3.99852 6.98507 4.00986 6.91975 4.0335 6.85849C4.05714 6.79722 4.09261 6.74122 4.13789 6.69367C4.18318 6.64611 4.23738 6.60795 4.29741 6.58134C4.35745 6.55474 4.42213 6.54022 4.48778 6.53861C4.55342 6.53701 4.61874 6.54835 4.68 6.57199L7 7.46399L11.32 5.79999C11.3814 5.77634 11.447 5.76505 11.5128 5.76678C11.5786 5.76852 11.6434 5.78323 11.7035 5.81008C11.7636 5.83694 11.8179 5.8754 11.8631 5.92326C11.9083 5.97112 11.9436 6.02744 11.967 6.08899ZM15 5.79999V9.42899C14.9986 9.73191 14.9061 10.0274 14.7345 10.2771C14.563 10.5268 14.3203 10.7191 14.038 10.829L7.538 13.329C7.19108 13.4626 6.80692 13.4626 6.46 13.329L1.961 11.6C1.67891 11.4899 1.43643 11.2975 1.26506 11.0479C1.09369 10.7982 1.00134 10.5028 1 10.2V6.57099C1.00155 6.26809 1.0941 5.97265 1.26565 5.72301C1.43719 5.47336 1.6798 5.28104 1.962 5.17099L8.462 2.67099C8.80902 2.53798 9.19298 2.53798 9.54 2.67099L14.04 4.40199C14.3215 4.51223 14.5635 4.70438 14.7346 4.95361C14.9058 5.20283 14.9982 5.49766 15 5.79999ZM14 5.79999C14 5.69881 13.9694 5.6 13.912 5.51662C13.8547 5.43324 13.7735 5.36921 13.679 5.33299L9.179 3.60299C9.06398 3.55763 8.93602 3.55763 8.821 3.60299L2.321 6.10299C2.22637 6.13927 2.145 6.20345 2.08767 6.28703C2.03034 6.37061 1.99977 6.46964 2 6.57099V10.2C2.0001 10.3009 2.03071 10.3994 2.08782 10.4825C2.14494 10.5657 2.22587 10.6297 2.32 10.666L6.82 12.398C6.93524 12.4422 7.06276 12.4422 7.178 12.398L13.678 9.89799C13.773 9.8618 13.8547 9.79754 13.9122 9.71375C13.9697 9.62996 14.0004 9.53062 14 9.42899V5.79999Z" + ], + LuaCompletionIconKind.Method => + [ + "M4.69684 5.04043C4.44303 4.93166 4.14909 5.04923 4.04031 5.30305C3.93153 5.55686 4.04911 5.8508 4.30292 5.95958L7.49988 7.3297V10.5C7.49988 10.7761 7.72374 11 7.99988 11C8.27603 11 8.49988 10.7761 8.49988 10.5V7.3297L11.6968 5.95958C11.9507 5.8508 12.0682 5.55686 11.9595 5.30305C11.8507 5.04923 11.5567 4.93166 11.3029 5.04043L7.99988 6.45602L4.69684 5.04043ZM9.07694 1.37855C8.38373 1.11193 7.61627 1.11193 6.92306 1.37855L1.96153 3.28683C1.38224 3.50964 1 4.06619 1 4.68685V11.3133C1 11.9339 1.38224 12.4905 1.96153 12.7133L6.92306 14.6216C7.61627 14.8882 8.38373 14.8882 9.07694 14.6216L14.0385 12.7133C14.6178 12.4905 15 11.9339 15 11.3133V4.68685C15 4.06619 14.6178 3.50964 14.0385 3.28683L9.07694 1.37855ZM7.28204 2.3119C7.74418 2.13415 8.25582 2.13415 8.71796 2.3119L13.6795 4.22018C13.8726 4.29445 14 4.47997 14 4.68685V11.3133C14 11.5201 13.8726 11.7057 13.6795 11.7799L8.71796 13.6882C8.25582 13.866 7.74418 13.866 7.28204 13.6882L2.32051 11.7799C2.12741 11.7057 2 11.5201 2 11.3133V4.68685C2 4.47997 2.12741 4.29445 2.32051 4.22018L7.28204 2.3119Z" + ], + LuaCompletionIconKind.Property => + [ + "M6.99989 5C6.99989 2.79086 8.79075 1 10.9999 1C11.5087 1 11.9964 1.09524 12.4454 1.26931C12.603 1.3304 12.719 1.46698 12.7539 1.63235C12.7888 1.79773 12.7377 1.96953 12.6182 2.08904L10.7072 4.00012L12.0001 5.29302L13.911 3.38207C14.0305 3.26254 14.2023 3.2115 14.3677 3.24637C14.5331 3.28125 14.6697 3.39732 14.7307 3.55493C14.9047 4.0038 14.9999 4.49138 14.9999 5C14.9999 7.20914 13.209 9 10.9999 9C10.6198 9 10.2514 8.94684 9.90215 8.84736L4.89566 13.9192C4.18171 14.6425 3.03692 14.7101 2.24289 14.0757C1.32876 13.3455 1.24088 11.9872 2.05327 11.1453L7.10411 5.91061C7.03588 5.61771 6.99989 5.31279 6.99989 5ZM10.9999 2C9.34303 2 7.99989 3.34315 7.99989 5C7.99989 5.31548 8.04841 5.61868 8.13805 5.90305C8.19313 6.07781 8.14821 6.26869 8.02099 6.40054L2.7729 11.8396C2.3696 12.2576 2.41323 12.9319 2.86703 13.2944C3.26123 13.6093 3.82955 13.5758 4.18398 13.2167L9.40817 7.9243C9.54702 7.78364 9.75569 7.73797 9.9406 7.80777C10.2693 7.93186 10.6261 8 10.9999 8C12.6567 8 13.9999 6.65685 13.9999 5C13.9999 4.9056 13.9955 4.81228 13.987 4.72023L12.3537 6.35368C12.2599 6.44745 12.1327 6.50013 12.0001 6.50013C11.8675 6.50013 11.7403 6.44745 11.6466 6.35368L9.64655 4.35368C9.45129 4.15842 9.45129 3.84185 9.64655 3.64658L11.2802 2.01289C11.188 2.00436 11.0945 2 10.9999 2Z" + ], + LuaCompletionIconKind.Class => + [ + "M13.2069 10.4999C13.0194 10.3125 12.7651 10.2072 12.4999 10.2072C12.2348 10.2072 11.9805 10.3125 11.7929 10.4999L11.2929 10.9999H8.99994V6.99994H10.3629C10.2479 7.1876 10.1989 7.40832 10.2238 7.62701C10.2486 7.84571 10.3458 8.04983 10.4999 8.20694L11.2929 8.99994C11.4805 9.18741 11.7348 9.29273 11.9999 9.29273C12.2651 9.29273 12.5194 9.18741 12.7069 8.99994L13.9999 7.70694C14.1874 7.51941 14.2927 7.2651 14.2927 6.99994C14.2927 6.73478 14.1874 6.48047 13.9999 6.29294L13.2069 5.49994C13.0194 5.31247 12.7651 5.20715 12.4999 5.20715C12.2348 5.20715 11.9805 5.31247 11.7929 5.49994L11.2929 5.99994H6.70694L7.49994 5.20694C7.68741 5.01941 7.79273 4.7651 7.79273 4.49994C7.79273 4.23478 7.68741 3.98047 7.49994 3.79294L6.20694 2.49994C6.01941 2.31247 5.7651 2.20715 5.49994 2.20715C5.23478 2.20715 4.98047 2.31247 4.79294 2.49994L1.49994 5.79294C1.31247 5.98047 1.20715 6.23478 1.20715 6.49994C1.20715 6.7651 1.31247 7.01941 1.49994 7.20694L2.79294 8.49994C2.98047 8.68741 3.23478 8.79273 3.49994 8.79273C3.7651 8.79273 4.01941 8.68741 4.20694 8.49994L5.70694 6.99994H7.99994V11.4999C7.99994 11.6325 8.05262 11.7597 8.14639 11.8535C8.24015 11.9473 8.36733 11.9999 8.49994 11.9999H10.3629C10.2479 12.1876 10.1989 12.4083 10.2238 12.627C10.2486 12.8457 10.3458 13.0498 10.4999 13.2069L11.2929 13.9999C11.4805 14.1874 11.7348 14.2927 11.9999 14.2927C12.2651 14.2927 12.5194 14.1874 12.7069 13.9999L13.9999 12.7069C14.1874 12.5194 14.2927 12.2651 14.2927 11.9999C14.2927 11.7348 14.1874 11.4805 13.9999 11.2929L13.2069 10.4999ZM3.49994 7.79294L2.20694 6.49994L5.49994 3.20694L6.79294 4.49994L3.49994 7.79294ZM13.2929 6.99994L11.9999 8.29294L11.2069 7.49994L12.4999 6.20694L13.2929 6.99994ZM11.9999 13.2929L11.2069 12.4999L12.4999 11.2069L13.2929 11.9999L11.9999 13.2929Z" + ], + LuaCompletionIconKind.Keyword => + [ + "M9.5 14C9.77614 14 10 14.2239 10 14.5C10 14.7761 9.77614 15 9.5 15H2.5C2.22386 15 2 14.7761 2 14.5C2 14.2239 2.22386 14 2.5 14H9.5Z", + "M6.5 11C6.77614 11 7 11.2239 7 11.5C7 11.7761 6.77614 12 6.5 12H2.5C2.22386 12 2 11.7761 2 11.5C2 11.2239 2.22386 11 2.5 11H6.5Z", + "M13.5 11C13.7761 11 14 11.2239 14 11.5C14 11.7761 13.7761 12 13.5 12H8.5C8.22386 12 8 11.7761 8 11.5C8 11.2239 8.22386 11 8.5 11H13.5Z", + "M8.5 8C8.77614 8 9 8.22386 9 8.5C9 8.77614 8.77614 9 8.5 9H2.5C2.22386 9 2 8.77614 2 8.5C2 8.22386 2.22386 8 2.5 8H8.5Z", + "M13.5 8C13.7761 8 14 8.22386 14 8.5C14 8.77614 13.7761 9 13.5 9H10.5C10.2239 9 10 8.77614 10 8.5C10 8.22386 10.2239 8 10.5 8H13.5Z", + "M9 2C9.55228 2 10 2.44772 10 3V5C10 5.55228 9.55228 6 9 6H3C2.44772 6 2 5.55228 2 5V3C2 2.44772 2.44772 2 3 2H9ZM3 5H9V3H3V5Z", + "M13.5 4C13.7761 4 14 4.22386 14 4.5C14 4.77614 13.7761 5 13.5 5H11.5C11.2239 5 11 4.77614 11 4.5C11 4.22386 11.2239 4 11.5 4H13.5Z" + ], + LuaCompletionIconKind.Constant => + [ + "M4.5 2C3.83696 2 3.20107 2.26339 2.73223 2.73223C2.26339 3.20107 2 3.83696 2 4.5V11.5C2 12.163 2.26339 12.7989 2.73223 13.2678C3.20107 13.7366 3.83696 14 4.5 14H11.5C12.163 14 12.7989 13.7366 13.2678 13.2678C13.7366 12.7989 14 12.163 14 11.5V4.5C14 3.83696 13.7366 3.20107 13.2678 2.73223C12.7989 2.26339 12.163 2 11.5 2H4.5ZM3 4.5C3 4.10218 3.15804 3.72064 3.43934 3.43934C3.72064 3.15804 4.10218 3 4.5 3H11.5C11.8978 3 12.2794 3.15804 12.5607 3.43934C12.842 3.72064 13 4.10218 13 4.5V11.5C13 11.8978 12.842 12.2794 12.5607 12.5607C12.2794 12.842 11.8978 13 11.5 13H4.5C4.10218 13 3.72064 12.842 3.43934 12.5607C3.15804 12.2794 3 11.8978 3 11.5V4.5Z", + "M5 6.5C5 6.36739 5.05268 6.24021 5.14645 6.14645C5.24021 6.05268 5.36739 6 5.5 6H10.5C10.6326 6 10.7598 6.05268 10.8536 6.14645C10.9473 6.24021 11 6.36739 11 6.5C11 6.63261 10.9473 6.75979 10.8536 6.85355C10.7598 6.94732 10.6326 7 10.5 7H5.5C5.36739 7 5.24021 6.94732 5.14645 6.85355C5.05268 6.75979 5 6.63261 5 6.5ZM10.5 9H5.5C5.36739 9 5.24021 9.05268 5.14645 9.14645C5.05268 9.24021 5 9.36739 5 9.5C5 9.63261 5.05268 9.75979 5.14645 9.85355C5.24021 9.94732 5.36739 10 5.5 10H10.5C10.6326 10 10.7598 9.94732 10.8536 9.85355C10.9473 9.75979 11 9.63261 11 9.5C11 9.36739 10.9473 9.24021 10.8536 9.14645C10.7598 9.05268 10.6326 9 10.5 9Z" + ], + LuaCompletionIconKind.Parameter => + [ + "M4 3.5C4 3.22386 4.22386 3 4.5 3H11.5C11.7761 3 12 3.22386 12 3.5V4.5C12 4.77614 11.7761 5 11.5 5C11.2239 5 11 4.77614 11 4.5V4H8.5V12H9C9.27614 12 9.5 12.2239 9.5 12.5C9.5 12.7761 9.27614 13 9 13H7C6.72386 13 6.5 12.7761 6.5 12.5C6.5 12.2239 6.72386 12 7 12H7.5V4H5V4.5C5 4.77614 4.77614 5 4.5 5C4.22386 5 4 4.77614 4 4.5V3.5ZM4.35355 6.64645C4.54882 6.84171 4.54882 7.15829 4.35355 7.35355L2.20711 9.5L4.35355 11.6464C4.54882 11.8417 4.54882 12.1583 4.35355 12.3536C4.15829 12.5488 3.84171 12.5488 3.64645 12.3536L1.14645 9.85355C0.951184 9.65829 0.951184 9.34171 1.14645 9.14645L3.64645 6.64645C3.84171 6.45118 4.15829 6.45118 4.35355 6.64645ZM14.8536 9.14645L12.3536 6.64645C12.1583 6.45118 11.8417 6.45118 11.6464 6.64645C11.4512 6.84171 11.4512 7.15829 11.6464 7.35355L13.7929 9.5L11.6464 11.6464C11.4512 11.8417 11.4512 12.1583 11.6464 12.3536C11.8417 12.5488 12.1583 12.5488 12.3536 12.3536L14.8536 9.85355C15.0488 9.65829 15.0488 9.34171 14.8536 9.14645Z" + ], + LuaCompletionIconKind.Namespace => + [ + "M5 2C3.89543 2 3 2.89543 3 4V6.00469C3 6.53494 2.99231 6.79889 2.91088 7.00209C2.84826 7.15835 2.71576 7.33309 2.2764 7.55276C2.10701 7.63745 2 7.81058 2 7.99997C2 8.18935 2.10699 8.36249 2.27638 8.44719C2.71569 8.66685 2.84809 8.84151 2.91076 8.99819C2.99233 9.20211 3 9.46732 3 10L3 12C3 13.1046 3.89543 14 5 14C5.27614 14 5.5 13.7761 5.5 13.5C5.5 13.2239 5.27614 13 5 13C4.44772 13 4 12.5523 4 12L4.00003 9.94145C4.00033 9.49235 4.00065 9.03033 3.83924 8.6268C3.74212 8.384 3.59654 8.17962 3.40072 8.00002C3.59646 7.82057 3.74199 7.61645 3.83912 7.37408C4.00065 6.971 4.00033 6.51001 4.00003 6.063L4 4C4 3.44772 4.44772 3 5 3C5.27614 3 5.5 2.77614 5.5 2.5C5.5 2.22386 5.27614 2 5 2ZM11 2C12.1046 2 13 2.89543 13 4V6.00469C13 6.53494 13.0077 6.79889 13.0891 7.00209C13.1517 7.15835 13.2842 7.33309 13.7236 7.55276C13.893 7.63745 14 7.81058 14 7.99997C14 8.18935 13.893 8.36249 13.7236 8.44719C13.2843 8.66685 13.1519 8.84151 13.0892 8.99819C13.0077 9.20211 13 9.46732 13 10V12C13 13.1046 12.1046 14 11 14C10.7239 14 10.5 13.7761 10.5 13.5C10.5 13.2239 10.7239 13 11 13C11.5523 13 12 12.5523 12 12L12 9.94145C11.9997 9.49235 11.9994 9.03033 12.1608 8.6268C12.2579 8.384 12.4035 8.17962 12.5993 8.00002C12.4035 7.82057 12.258 7.61645 12.1609 7.37408C11.9993 6.971 11.9997 6.51001 12 6.063L12 4C12 3.44772 11.5523 3 11 3C10.7239 3 10.5 2.77614 10.5 2.5C10.5 2.22386 10.7239 2 11 2Z" + ], + LuaCompletionIconKind.File => + [ + "M5 1C3.89543 1 3 1.89543 3 3V13C3 14.1046 3.89543 15 5 15H11C12.1046 15 13 14.1046 13 13V5.41421C13 5.01639 12.842 4.63486 12.5607 4.35355L9.64645 1.43934C9.36514 1.15804 8.98361 1 8.58579 1H5ZM4 3C4 2.44772 4.44772 2 5 2H8V4.5C8 5.32843 8.67157 6 9.5 6H12V13C12 13.5523 11.5523 14 11 14H5C4.44772 14 4 13.5523 4 13V3ZM11.7929 5H9.5C9.22386 5 9 4.77614 9 4.5V2.20711L11.7929 5Z" + ], + LuaCompletionIconKind.Folder => + [ + "M2 4.5V6H5.58579C5.71839 6 5.84557 5.94732 5.93934 5.85355L7.29289 4.5L5.93934 3.14645C5.84557 3.05268 5.71839 3 5.58579 3H3.5C2.67157 3 2 3.67157 2 4.5ZM1 4.5C1 3.11929 2.11929 2 3.5 2H5.58579C5.98361 2 6.36514 2.15804 6.64645 2.43934L8.20711 4H12.5C13.8807 4 15 5.11929 15 6.5V11.5C15 12.8807 13.8807 14 12.5 14H3.5C2.11929 14 1 12.8807 1 11.5V4.5ZM2 7V11.5C2 12.3284 2.67157 13 3.5 13H12.5C13.3284 13 14 12.3284 14 11.5V6.5C14 5.67157 13.3284 5 12.5 5H8.20711L6.64645 6.56066C6.36514 6.84197 5.98361 7 5.58579 7H2Z" + ], + _ => + [ + "M11.9999 3C10.1399 3 8.56988 4.27 8.12988 6H9.17988C9.58988 4.84 10.6999 4 11.9999 4C13.6499 4 14.9999 5.35 14.9999 7C14.9999 8.3 14.1599 9.41 12.9999 9.82V10.87C14.7299 10.43 15.9999 8.86 15.9999 7C15.9999 4.79 14.2099 3 11.9999 3Z", + "M10.5 15H5.5C4.673 15 4 14.327 4 13.5V8.5C4 7.673 4.673 7 5.5 7H10.5C11.327 7 12 7.673 12 8.5V13.5C12 14.327 11.327 15 10.5 15ZM5.5 8C5.224 8 5 8.225 5 8.5V13.5C5 13.775 5.224 14 5.5 14H10.5C10.776 14 11 13.775 11 13.5V8.5C11 8.225 10.776 8 10.5 8H5.5Z", + "M4.42973 2.25008C4.24973 1.94008 3.74973 1.94008 3.56973 2.25008L0.0997266 8.25008C0.00972656 8.40008 0.00972656 8.60008 0.0997266 8.75008C0.189727 8.90008 0.359727 9.00008 0.539727 9.00008H2.99973V8.50008C2.99973 8.33008 3.01973 8.16008 3.04973 8.00008H1.39973L3.99973 3.50008L5.44973 6.00008H6.59973L4.42973 2.25008Z" + ] + }; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs index b524cc3f0f..ebd5deafe5 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs @@ -1,18 +1,17 @@ -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +public enum LuaCompletionIconKind { - public enum LuaCompletionIconKind - { - Misc, - Variable, - Field, - Method, - Property, - Class, - Keyword, - Constant, - Parameter, - Namespace, - File, - Folder - } -} \ No newline at end of file + Misc, + Variable, + Field, + Method, + Property, + Class, + Keyword, + Constant, + Parameter, + Namespace, + File, + Folder +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index 484ffe51b6..ae3c2fc39b 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -2,47 +2,48 @@ using System.Threading; using System.Threading.Tasks; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +public sealed class LuaCompletionItem { - public sealed class LuaCompletionItem - { - private readonly Func>? _resolveAsync; + private readonly Func>? _resolveAsync; - public LuaCompletionItem( - string label, - string? insertText = null, - string? detail = null, - string? description = null, - string? filterText = null, - double priority = 0.0, - LuaCompletionIconKind iconKind = LuaCompletionIconKind.Misc, - bool isDescriptionMarkdown = false, - Func>? resolveAsync = null) - { - Label = label ?? throw new ArgumentNullException(nameof(label)); - InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; - Detail = string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); - Description = string.IsNullOrWhiteSpace(description) ? null : description.Trim(); - FilterText = string.IsNullOrWhiteSpace(filterText) ? label : filterText; - Priority = priority; - IconKind = iconKind; - IsDescriptionMarkdown = isDescriptionMarkdown; - _resolveAsync = resolveAsync; - } + public LuaCompletionItem( + string label, + string? insertText = null, + string? detail = null, + string? description = null, + string? filterText = null, + double priority = 0.0, + LuaCompletionIconKind iconKind = LuaCompletionIconKind.Misc, + bool isDescriptionMarkdown = false, + Func>? resolveAsync = null) + { + Label = label ?? throw new ArgumentNullException(nameof(label)); + InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; + Detail = string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); + Description = string.IsNullOrWhiteSpace(description) ? null : description.Trim(); + FilterText = string.IsNullOrWhiteSpace(filterText) ? label : filterText; + Priority = priority; + IconKind = iconKind; + IsDescriptionMarkdown = isDescriptionMarkdown; + _resolveAsync = resolveAsync; + } - public string Label { get; } - public string InsertText { get; } - public string? Detail { get; } - public string? Description { get; } - public string FilterText { get; } - public double Priority { get; } - public LuaCompletionIconKind IconKind { get; } - public bool IsDescriptionMarkdown { get; } - public bool CanResolve => _resolveAsync is not null; + public string Label { get; } + public string InsertText { get; } + public string? Detail { get; } + public string? Description { get; } + public string FilterText { get; } + public double Priority { get; } + public LuaCompletionIconKind IconKind { get; } + public bool IsDescriptionMarkdown { get; } + public bool CanResolve => _resolveAsync is not null; - public Task ResolveAsync(CancellationToken cancellationToken = default) - => _resolveAsync is null - ? Task.FromResult(this) - : _resolveAsync(cancellationToken); + public Task ResolveAsync(CancellationToken cancellationToken = default) + { + return _resolveAsync is null + ? Task.FromResult(this) + : _resolveAsync(cancellationToken); } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs index 54ac1050c4..68e1044b8a 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs @@ -1,80 +1,78 @@ +using ICSharpCode.AvalonEdit.CodeCompletion; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; -using ICSharpCode.AvalonEdit.CodeCompletion; using TombLib.Scripting.Lua.Resources; -namespace TombLib.Scripting.Lua.Objects -{ - internal static class LuaCompletionWindowStyle - { - private static readonly Style ItemContainerStyle = CreateItemContainerStyle(); +namespace TombLib.Scripting.Lua.Objects; - public static void Apply(CompletionWindow window, LuaThemeBrushSet brushSet) - { - if (window is null) - return; +internal static class LuaCompletionWindowStyle +{ + private static readonly Style ItemContainerStyle = CreateItemContainerStyle(); - window.FontFamily = window.TextArea.FontFamily; - window.FontSize = window.TextArea.FontSize; - window.CompletionList.HorizontalContentAlignment = HorizontalAlignment.Stretch; - window.CompletionList.ListBox.HorizontalContentAlignment = HorizontalAlignment.Stretch; - window.CompletionList.ListBox.BorderThickness = new Thickness(0.0); - window.CompletionList.ListBox.Focusable = false; - window.CompletionList.ListBox.IsTabStop = false; - window.CompletionList.ListBox.FontFamily = window.TextArea.FontFamily; - window.CompletionList.ListBox.FontSize = window.TextArea.FontSize; - window.CompletionList.ListBox.ItemTemplate = CreateItemTemplate(brushSet.MutedTextBrush); - window.CompletionList.ListBox.ItemContainerStyle = ItemContainerStyle; - } + public static void Apply(CompletionWindow window, LuaThemeBrushSet brushSet) + { + if (window is null) + return; - private static DataTemplate CreateItemTemplate(Brush detailBrush) - { - var template = new DataTemplate(typeof(LuaCompletionData)); + window.FontFamily = window.TextArea.FontFamily; + window.FontSize = window.TextArea.FontSize; + window.CompletionList.HorizontalContentAlignment = HorizontalAlignment.Stretch; + window.CompletionList.ListBox.HorizontalContentAlignment = HorizontalAlignment.Stretch; + window.CompletionList.ListBox.BorderThickness = new Thickness(0.0); + window.CompletionList.ListBox.Focusable = false; + window.CompletionList.ListBox.IsTabStop = false; + window.CompletionList.ListBox.FontFamily = window.TextArea.FontFamily; + window.CompletionList.ListBox.FontSize = window.TextArea.FontSize; + window.CompletionList.ListBox.ItemTemplate = CreateItemTemplate(brushSet.MutedTextBrush); + window.CompletionList.ListBox.ItemContainerStyle = ItemContainerStyle; + } - var panel = new FrameworkElementFactory(typeof(DockPanel)); - panel.SetValue(DockPanel.LastChildFillProperty, true); + private static DataTemplate CreateItemTemplate(Brush detailBrush) + { + var template = new DataTemplate(typeof(LuaCompletionData)); - var icon = new FrameworkElementFactory(typeof(Image)); - icon.SetValue(DockPanel.DockProperty, Dock.Left); - icon.SetValue(FrameworkElement.WidthProperty, 16.0); - icon.SetValue(FrameworkElement.HeightProperty, 16.0); - icon.SetValue(FrameworkElement.MarginProperty, new Thickness(0.0, 0.0, 8.0, 0.0)); - icon.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); - icon.SetBinding(Image.SourceProperty, new Binding(nameof(LuaCompletionData.Image))); + var panel = new FrameworkElementFactory(typeof(DockPanel)); + panel.SetValue(DockPanel.LastChildFillProperty, true); - var detail = new FrameworkElementFactory(typeof(TextBlock)); - detail.SetValue(DockPanel.DockProperty, Dock.Right); - detail.SetValue(TextBlock.ForegroundProperty, detailBrush); - detail.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); - detail.SetValue(FrameworkElement.MarginProperty, new Thickness(12.0, 0.0, 0.0, 0.0)); - detail.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); - detail.SetBinding(TextBlock.TextProperty, new Binding(nameof(LuaCompletionData.DisplayDetail))); - detail.SetBinding(UIElement.VisibilityProperty, new Binding(nameof(LuaCompletionData.DetailVisibility))); + var icon = new FrameworkElementFactory(typeof(Image)); + icon.SetValue(DockPanel.DockProperty, Dock.Left); + icon.SetValue(FrameworkElement.WidthProperty, 16.0); + icon.SetValue(FrameworkElement.HeightProperty, 16.0); + icon.SetValue(FrameworkElement.MarginProperty, new Thickness(0.0, 0.0, 8.0, 0.0)); + icon.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); + icon.SetBinding(Image.SourceProperty, new Binding(nameof(LuaCompletionData.Image))); - var label = new FrameworkElementFactory(typeof(TextBlock)); - label.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); - label.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); - label.SetBinding(TextBlock.TextProperty, new Binding(nameof(LuaCompletionData.DisplayText))); + var detail = new FrameworkElementFactory(typeof(TextBlock)); + detail.SetValue(DockPanel.DockProperty, Dock.Right); + detail.SetValue(TextBlock.ForegroundProperty, detailBrush); + detail.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); + detail.SetValue(FrameworkElement.MarginProperty, new Thickness(12.0, 0.0, 0.0, 0.0)); + detail.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); + detail.SetBinding(TextBlock.TextProperty, new Binding(nameof(LuaCompletionData.DisplayDetail))); + detail.SetBinding(UIElement.VisibilityProperty, new Binding(nameof(LuaCompletionData.DetailVisibility))); - panel.AppendChild(icon); - panel.AppendChild(detail); - panel.AppendChild(label); + var label = new FrameworkElementFactory(typeof(TextBlock)); + label.SetValue(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis); + label.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center); + label.SetBinding(TextBlock.TextProperty, new Binding(nameof(LuaCompletionData.DisplayText))); - template.VisualTree = panel; - return template; - } + panel.AppendChild(icon); + panel.AppendChild(detail); + panel.AppendChild(label); - private static Style CreateItemContainerStyle() - { - var style = new Style(typeof(ListBoxItem)); - style.Setters.Add(new Setter(UIElement.FocusableProperty, false)); - style.Setters.Add(new Setter(Control.PaddingProperty, new Thickness(8.0, 3.0, 8.0, 3.0))); - style.Setters.Add(new Setter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)); - style.Setters.Add(new Setter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Center)); - return style; - } + template.VisualTree = panel; + return template; + } + private static Style CreateItemContainerStyle() + { + var style = new Style(typeof(ListBoxItem)); + style.Setters.Add(new Setter(UIElement.FocusableProperty, false)); + style.Setters.Add(new Setter(Control.PaddingProperty, new Thickness(8.0, 3.0, 8.0, 3.0))); + style.Setters.Add(new Setter(Control.HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch)); + style.Setters.Add(new Setter(Control.VerticalContentAlignmentProperty, VerticalAlignment.Center)); + return style; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs index 2cb16f5dcb..a75175b8ad 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs @@ -1,18 +1,17 @@ using System; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +public sealed class LuaDefinitionLocation { - public sealed class LuaDefinitionLocation + public LuaDefinitionLocation(string filePath, int lineNumber, int columnNumber) { - public LuaDefinitionLocation(string filePath, int lineNumber, int columnNumber) - { - FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); - LineNumber = Math.Max(1, lineNumber); - ColumnNumber = Math.Max(1, columnNumber); - } - - public string FilePath { get; } - public int LineNumber { get; } - public int ColumnNumber { get; } + FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); + LineNumber = Math.Max(1, lineNumber); + ColumnNumber = Math.Max(1, columnNumber); } -} \ No newline at end of file + + public string FilePath { get; } + public int LineNumber { get; } + public int ColumnNumber { get; } +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs index 0ae97ad068..81424fbb03 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs @@ -1,16 +1,15 @@ using System; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +public sealed class LuaHoverInfo { - public sealed class LuaHoverInfo + public LuaHoverInfo(string content, bool isMarkdown) { - public LuaHoverInfo(string content, bool isMarkdown) - { - Content = content ?? throw new ArgumentNullException(nameof(content)); - IsMarkdown = isMarkdown; - } - - public string Content { get; } - public bool IsMarkdown { get; } + Content = content ?? throw new ArgumentNullException(nameof(content)); + IsMarkdown = isMarkdown; } -} \ No newline at end of file + + public string Content { get; } + public bool IsMarkdown { get; } +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs index e92f84e034..727863ed70 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs @@ -1,37 +1,36 @@ using System; using System.Collections.Generic; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +public sealed class LuaSemanticToken { - public sealed class LuaSemanticToken + public LuaSemanticToken(int line, int character, int length, string type, IReadOnlyList modifiers) { - public LuaSemanticToken(int line, int character, int length, string type, IReadOnlyList modifiers) - { - Line = Math.Max(0, line); - Character = Math.Max(0, character); - Length = Math.Max(0, length); - Type = type ?? string.Empty; - Modifiers = modifiers ?? Array.Empty(); - } - - public int Line { get; } - public int Character { get; } - public int Length { get; } - public string Type { get; } - public IReadOnlyList Modifiers { get; } - - public bool HasModifier(string modifier) - { - if (string.IsNullOrWhiteSpace(modifier) || Modifiers.Count == 0) - return false; + Line = Math.Max(0, line); + Character = Math.Max(0, character); + Length = Math.Max(0, length); + Type = type ?? string.Empty; + Modifiers = modifiers ?? []; + } - for (int i = 0; i < Modifiers.Count; i++) - { - if (string.Equals(Modifiers[i], modifier, StringComparison.Ordinal)) - return true; - } + public int Line { get; } + public int Character { get; } + public int Length { get; } + public string Type { get; } + public IReadOnlyList Modifiers { get; } + public bool HasModifier(string modifier) + { + if (string.IsNullOrWhiteSpace(modifier) || Modifiers.Count == 0) return false; + + for (int i = 0; i < Modifiers.Count; i++) + { + if (string.Equals(Modifiers[i], modifier, StringComparison.Ordinal)) + return true; } + + return false; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs index cdb5417a57..48239a7432 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs @@ -1,34 +1,33 @@ using System; using System.Collections.Generic; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +public sealed class LuaSignatureInfo { - public sealed class LuaSignatureInfo + public LuaSignatureInfo(string label, string? documentation, IReadOnlyList parameters, + int activeParameter) { - public LuaSignatureInfo(string label, string? documentation, IReadOnlyList parameters, - int activeParameter) - { - Label = label ?? throw new ArgumentNullException(nameof(label)); - Documentation = documentation; - Parameters = parameters ?? Array.Empty(); - ActiveParameter = Math.Max(0, activeParameter); - } - - public string Label { get; } - public string? Documentation { get; } - public IReadOnlyList Parameters { get; } - public int ActiveParameter { get; } + Label = label ?? throw new ArgumentNullException(nameof(label)); + Documentation = documentation; + Parameters = parameters ?? []; + ActiveParameter = Math.Max(0, activeParameter); } - public sealed class LuaParameterInfo - { - public LuaParameterInfo(string label, string? documentation) - { - Label = label ?? string.Empty; - Documentation = documentation; - } + public string Label { get; } + public string? Documentation { get; } + public IReadOnlyList Parameters { get; } + public int ActiveParameter { get; } +} - public string Label { get; } - public string? Documentation { get; } +public sealed class LuaParameterInfo +{ + public LuaParameterInfo(string label, string? documentation) + { + Label = label ?? string.Empty; + Documentation = documentation; } + + public string Label { get; } + public string? Documentation { get; } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs index de599899a8..1cd399426a 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs @@ -2,76 +2,75 @@ using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Resources; -namespace TombLib.Scripting.Lua.Objects +namespace TombLib.Scripting.Lua.Objects; + +public sealed class LuaTheme { - public sealed class LuaTheme - { - public string Name { get; set; } = string.Empty; - public List Aliases { get; set; } = new List(); - public string EditorBackground { get; set; } = LuaBuiltInThemes.DefaultEditorBackground; - public string EditorForeground { get; set; } = LuaBuiltInThemes.DefaultEditorForeground; - public TextMateTokenTheme TextMateTheme { get; set; } = new TextMateTokenTheme(); - public LuaThemeSemanticColors SemanticColors { get; set; } = new LuaThemeSemanticColors(); + public string Name { get; set; } = string.Empty; + public List Aliases { get; set; } = []; + public string EditorBackground { get; set; } = LuaBuiltInThemes.DefaultEditorBackground; + public string EditorForeground { get; set; } = LuaBuiltInThemes.DefaultEditorForeground; + public TextMateTokenTheme TextMateTheme { get; set; } = new TextMateTokenTheme(); + public LuaThemeSemanticColors SemanticColors { get; set; } = new LuaThemeSemanticColors(); - public LuaTheme Normalize(string fallbackName) - { - if (string.IsNullOrWhiteSpace(Name)) - Name = fallbackName; + public LuaTheme Normalize(string fallbackName) + { + if (string.IsNullOrWhiteSpace(Name)) + Name = fallbackName; - if (string.IsNullOrWhiteSpace(EditorBackground)) - EditorBackground = LuaBuiltInThemes.DefaultEditorBackground; + if (string.IsNullOrWhiteSpace(EditorBackground)) + EditorBackground = LuaBuiltInThemes.DefaultEditorBackground; - if (string.IsNullOrWhiteSpace(EditorForeground)) - EditorForeground = LuaBuiltInThemes.DefaultEditorForeground; + if (string.IsNullOrWhiteSpace(EditorForeground)) + EditorForeground = LuaBuiltInThemes.DefaultEditorForeground; - Aliases ??= new List(); - TextMateTheme ??= new TextMateTokenTheme(); - SemanticColors ??= new LuaThemeSemanticColors(); - SemanticColors.Normalize(); + Aliases ??= []; + TextMateTheme ??= new TextMateTokenTheme(); + SemanticColors ??= new LuaThemeSemanticColors(); + SemanticColors.Normalize(); - return this; - } + return this; } +} - public sealed class LuaThemeSemanticColors - { - public string MutedText { get; set; } = LuaBuiltInThemes.DefaultMutedText; - public string Misc { get; set; } = LuaBuiltInThemes.DefaultMisc; - public string Method { get; set; } = LuaBuiltInThemes.DefaultMethod; - public string Variable { get; set; } = LuaBuiltInThemes.DefaultVariable; - public string Property { get; set; } = LuaBuiltInThemes.DefaultProperty; - public string Type { get; set; } = LuaBuiltInThemes.DefaultType; - public string Keyword { get; set; } = LuaBuiltInThemes.DefaultKeyword; - public string LanguageConstant { get; set; } = LuaBuiltInThemes.DefaultLanguageConstant; - public string Constant { get; set; } = LuaBuiltInThemes.DefaultConstant; - public string File { get; set; } = LuaBuiltInThemes.DefaultFile; - public string SignatureParameterDocumentation { get; set; } = LuaBuiltInThemes.DefaultSignatureParameterDocumentation; - public string SignatureActiveParameter { get; set; } = LuaBuiltInThemes.DefaultSignatureActiveParameter; - public string SignatureText { get; set; } = LuaBuiltInThemes.DefaultSignatureText; +public sealed class LuaThemeSemanticColors +{ + public string MutedText { get; set; } = LuaBuiltInThemes.DefaultMutedText; + public string Misc { get; set; } = LuaBuiltInThemes.DefaultMisc; + public string Method { get; set; } = LuaBuiltInThemes.DefaultMethod; + public string Variable { get; set; } = LuaBuiltInThemes.DefaultVariable; + public string Property { get; set; } = LuaBuiltInThemes.DefaultProperty; + public string Type { get; set; } = LuaBuiltInThemes.DefaultType; + public string Keyword { get; set; } = LuaBuiltInThemes.DefaultKeyword; + public string LanguageConstant { get; set; } = LuaBuiltInThemes.DefaultLanguageConstant; + public string Constant { get; set; } = LuaBuiltInThemes.DefaultConstant; + public string File { get; set; } = LuaBuiltInThemes.DefaultFile; + public string SignatureParameterDocumentation { get; set; } = LuaBuiltInThemes.DefaultSignatureParameterDocumentation; + public string SignatureActiveParameter { get; set; } = LuaBuiltInThemes.DefaultSignatureActiveParameter; + public string SignatureText { get; set; } = LuaBuiltInThemes.DefaultSignatureText; - public void Normalize() - { - MutedText = NormalizeValue(MutedText, LuaBuiltInThemes.DefaultMutedText); - Misc = NormalizeValue(Misc, LuaBuiltInThemes.DefaultMisc); - Method = NormalizeValue(Method, LuaBuiltInThemes.DefaultMethod); - Variable = NormalizeValue(Variable, LuaBuiltInThemes.DefaultVariable); - Property = NormalizeValue(Property, LuaBuiltInThemes.DefaultProperty); - Type = NormalizeValue(Type, LuaBuiltInThemes.DefaultType); - Keyword = NormalizeValue(Keyword, LuaBuiltInThemes.DefaultKeyword); - LanguageConstant = NormalizeValue(LanguageConstant, LuaBuiltInThemes.DefaultLanguageConstant); - Constant = NormalizeValue(Constant, LuaBuiltInThemes.DefaultConstant); - File = NormalizeValue(File, LuaBuiltInThemes.DefaultFile); - SignatureParameterDocumentation = NormalizeValue(SignatureParameterDocumentation, LuaBuiltInThemes.DefaultSignatureParameterDocumentation); - SignatureActiveParameter = NormalizeValue(SignatureActiveParameter, LuaBuiltInThemes.DefaultSignatureActiveParameter); - SignatureText = NormalizeValue(SignatureText, LuaBuiltInThemes.DefaultSignatureText); - } + public void Normalize() + { + MutedText = NormalizeValue(MutedText, LuaBuiltInThemes.DefaultMutedText); + Misc = NormalizeValue(Misc, LuaBuiltInThemes.DefaultMisc); + Method = NormalizeValue(Method, LuaBuiltInThemes.DefaultMethod); + Variable = NormalizeValue(Variable, LuaBuiltInThemes.DefaultVariable); + Property = NormalizeValue(Property, LuaBuiltInThemes.DefaultProperty); + Type = NormalizeValue(Type, LuaBuiltInThemes.DefaultType); + Keyword = NormalizeValue(Keyword, LuaBuiltInThemes.DefaultKeyword); + LanguageConstant = NormalizeValue(LanguageConstant, LuaBuiltInThemes.DefaultLanguageConstant); + Constant = NormalizeValue(Constant, LuaBuiltInThemes.DefaultConstant); + File = NormalizeValue(File, LuaBuiltInThemes.DefaultFile); + SignatureParameterDocumentation = NormalizeValue(SignatureParameterDocumentation, LuaBuiltInThemes.DefaultSignatureParameterDocumentation); + SignatureActiveParameter = NormalizeValue(SignatureActiveParameter, LuaBuiltInThemes.DefaultSignatureActiveParameter); + SignatureText = NormalizeValue(SignatureText, LuaBuiltInThemes.DefaultSignatureText); + } - private static string NormalizeValue(string value, string fallbackValue) - { - if (string.IsNullOrWhiteSpace(value)) - return fallbackValue; + private static string NormalizeValue(string value, string fallbackValue) + { + if (string.IsNullOrWhiteSpace(value)) + return fallbackValue; - return value; - } + return value; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs index 079ee4b56c..63dc6c5006 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs @@ -1,9 +1,8 @@ -namespace TombLib.Scripting.Lua.Resources +namespace TombLib.Scripting.Lua.Resources; + +public static class ConfigurationDefaults { - public struct ConfigurationDefaults - { - public const string ConfigurationFileName = "LuaConfiguration.xml"; + public const string ConfigurationFileName = "LuaConfiguration.xml"; - public const string SelectedThemeName = LuaBuiltInThemes.DefaultThemeName; - } + public const string SelectedThemeName = LuaBuiltInThemes.DefaultThemeName; } diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs index 4c27bd4c80..a52b1bf921 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs @@ -1,57 +1,57 @@ -using System.Collections.Generic; using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Objects; -namespace TombLib.Scripting.Lua.Resources +namespace TombLib.Scripting.Lua.Resources; + +internal static class LuaBuiltInThemes { - internal static class LuaBuiltInThemes - { - public const string DefaultThemeName = "SharpLua Classic"; - public const string DefaultThemeAlias = "SharpLua"; + public const string DefaultThemeName = "SharpLua Classic"; + public const string DefaultThemeAlias = "SharpLua"; - public const string DefaultEditorBackground = LuaBuiltInTextMateThemeDefaults.DefaultEditorBackground; - public const string DefaultEditorForeground = LuaBuiltInTextMateThemeDefaults.DefaultEditorForeground; + public const string DefaultEditorBackground = LuaBuiltInTextMateThemeDefaults.DefaultEditorBackground; + public const string DefaultEditorForeground = LuaBuiltInTextMateThemeDefaults.DefaultEditorForeground; - public const string DefaultMutedText = LuaBuiltInTextMateThemeDefaults.DefaultMutedText; - public const string DefaultMisc = LuaBuiltInTextMateThemeDefaults.DefaultMisc; - public const string DefaultMethod = LuaBuiltInTextMateThemeDefaults.DefaultMethod; - public const string DefaultVariable = LuaBuiltInTextMateThemeDefaults.DefaultVariable; - public const string DefaultProperty = LuaBuiltInTextMateThemeDefaults.DefaultProperty; - public const string DefaultType = LuaBuiltInTextMateThemeDefaults.DefaultType; - public const string DefaultKeyword = LuaBuiltInTextMateThemeDefaults.DefaultKeyword; - public const string DefaultLanguageConstant = LuaBuiltInTextMateThemeDefaults.DefaultLanguageConstant; - public const string DefaultConstant = LuaBuiltInTextMateThemeDefaults.DefaultConstant; - public const string DefaultFile = LuaBuiltInTextMateThemeDefaults.DefaultFile; - public const string DefaultSignatureParameterDocumentation = LuaBuiltInTextMateThemeDefaults.DefaultSignatureParameterDocumentation; - public const string DefaultSignatureActiveParameter = LuaBuiltInTextMateThemeDefaults.DefaultSignatureActiveParameter; - public const string DefaultSignatureText = LuaBuiltInTextMateThemeDefaults.DefaultSignatureText; + public const string DefaultMutedText = LuaBuiltInTextMateThemeDefaults.DefaultMutedText; + public const string DefaultMisc = LuaBuiltInTextMateThemeDefaults.DefaultMisc; + public const string DefaultMethod = LuaBuiltInTextMateThemeDefaults.DefaultMethod; + public const string DefaultVariable = LuaBuiltInTextMateThemeDefaults.DefaultVariable; + public const string DefaultProperty = LuaBuiltInTextMateThemeDefaults.DefaultProperty; + public const string DefaultType = LuaBuiltInTextMateThemeDefaults.DefaultType; + public const string DefaultKeyword = LuaBuiltInTextMateThemeDefaults.DefaultKeyword; + public const string DefaultLanguageConstant = LuaBuiltInTextMateThemeDefaults.DefaultLanguageConstant; + public const string DefaultConstant = LuaBuiltInTextMateThemeDefaults.DefaultConstant; + public const string DefaultFile = LuaBuiltInTextMateThemeDefaults.DefaultFile; + public const string DefaultSignatureParameterDocumentation = LuaBuiltInTextMateThemeDefaults.DefaultSignatureParameterDocumentation; + public const string DefaultSignatureActiveParameter = LuaBuiltInTextMateThemeDefaults.DefaultSignatureActiveParameter; + public const string DefaultSignatureText = LuaBuiltInTextMateThemeDefaults.DefaultSignatureText; - public static LuaTheme CreateDefaultTheme() + public static LuaTheme CreateDefaultTheme() + { + return new LuaTheme { - return new LuaTheme + Name = DefaultThemeName, + Aliases = [DefaultThemeAlias], + EditorBackground = DefaultEditorBackground, + EditorForeground = DefaultEditorForeground, + + SemanticColors = new LuaThemeSemanticColors { - Name = DefaultThemeName, - Aliases = new List { DefaultThemeAlias }, - EditorBackground = DefaultEditorBackground, - EditorForeground = DefaultEditorForeground, - SemanticColors = new LuaThemeSemanticColors - { - MutedText = DefaultMutedText, - Misc = DefaultMisc, - Method = DefaultMethod, - Variable = DefaultVariable, - Property = DefaultProperty, - Type = DefaultType, - Keyword = DefaultKeyword, - LanguageConstant = DefaultLanguageConstant, - Constant = DefaultConstant, - File = DefaultFile, - SignatureParameterDocumentation = DefaultSignatureParameterDocumentation, - SignatureActiveParameter = DefaultSignatureActiveParameter, - SignatureText = DefaultSignatureText - }, - TextMateTheme = LuaBuiltInTextMateThemeDefaults.CreateDefaultTextMateTheme() - }; - } + MutedText = DefaultMutedText, + Misc = DefaultMisc, + Method = DefaultMethod, + Variable = DefaultVariable, + Property = DefaultProperty, + Type = DefaultType, + Keyword = DefaultKeyword, + LanguageConstant = DefaultLanguageConstant, + Constant = DefaultConstant, + File = DefaultFile, + SignatureParameterDocumentation = DefaultSignatureParameterDocumentation, + SignatureActiveParameter = DefaultSignatureActiveParameter, + SignatureText = DefaultSignatureText + }, + + TextMateTheme = LuaBuiltInTextMateThemeDefaults.CreateDefaultTextMateTheme() + }; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs index 24bb595039..bca391358d 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs @@ -3,126 +3,125 @@ using TombLib.Scripting.Resources; using static TombLib.WPF.BrushHelpers; -namespace TombLib.Scripting.Lua.Resources +namespace TombLib.Scripting.Lua.Resources; + +internal static class LuaEditorColorPalette { - internal static class LuaEditorColorPalette + public static LuaThemeBrushSet Create(LuaTheme theme) { - public static LuaThemeBrushSet Create(LuaTheme theme) - { - LuaTheme effectiveTheme = (theme ?? new LuaTheme()).Normalize(ConfigurationDefaults.SelectedThemeName); - LuaThemeSemanticColors semanticColors = effectiveTheme.SemanticColors; + LuaTheme effectiveTheme = (theme ?? new LuaTheme()).Normalize(ConfigurationDefaults.SelectedThemeName); + LuaThemeSemanticColors semanticColors = effectiveTheme.SemanticColors; - return new LuaThemeBrushSet( - effectiveTheme.Name, - CreateBrush(effectiveTheme.EditorBackground, LuaBuiltInThemes.DefaultEditorBackground), - CreateBrush(effectiveTheme.EditorForeground, LuaBuiltInThemes.DefaultEditorForeground), - CreateBrush(semanticColors.MutedText, LuaBuiltInThemes.DefaultMutedText), - CreateBrush(semanticColors.Misc, LuaBuiltInThemes.DefaultMisc), - CreateBrush(semanticColors.Method, LuaBuiltInThemes.DefaultMethod), - CreateBrush(semanticColors.Variable, LuaBuiltInThemes.DefaultVariable), - CreateBrush(semanticColors.Property, LuaBuiltInThemes.DefaultProperty), - CreateBrush(semanticColors.Type, LuaBuiltInThemes.DefaultType), - CreateBrush(semanticColors.Keyword, LuaBuiltInThemes.DefaultKeyword), - CreateBrush(semanticColors.LanguageConstant, LuaBuiltInThemes.DefaultLanguageConstant), - CreateBrush(semanticColors.Constant, LuaBuiltInThemes.DefaultConstant), - CreateBrush(semanticColors.File, LuaBuiltInThemes.DefaultFile), - CreateBrush(semanticColors.SignatureParameterDocumentation, LuaBuiltInThemes.DefaultSignatureParameterDocumentation), - CreateBrush(semanticColors.SignatureActiveParameter, LuaBuiltInThemes.DefaultSignatureActiveParameter), - CreateBrush(semanticColors.SignatureText, ColorToString(TextEditorColorPalette.ToolTipForeground.Color))); - } + return new LuaThemeBrushSet( + effectiveTheme.Name, + CreateBrush(effectiveTheme.EditorBackground, LuaBuiltInThemes.DefaultEditorBackground), + CreateBrush(effectiveTheme.EditorForeground, LuaBuiltInThemes.DefaultEditorForeground), + CreateBrush(semanticColors.MutedText, LuaBuiltInThemes.DefaultMutedText), + CreateBrush(semanticColors.Misc, LuaBuiltInThemes.DefaultMisc), + CreateBrush(semanticColors.Method, LuaBuiltInThemes.DefaultMethod), + CreateBrush(semanticColors.Variable, LuaBuiltInThemes.DefaultVariable), + CreateBrush(semanticColors.Property, LuaBuiltInThemes.DefaultProperty), + CreateBrush(semanticColors.Type, LuaBuiltInThemes.DefaultType), + CreateBrush(semanticColors.Keyword, LuaBuiltInThemes.DefaultKeyword), + CreateBrush(semanticColors.LanguageConstant, LuaBuiltInThemes.DefaultLanguageConstant), + CreateBrush(semanticColors.Constant, LuaBuiltInThemes.DefaultConstant), + CreateBrush(semanticColors.File, LuaBuiltInThemes.DefaultFile), + CreateBrush(semanticColors.SignatureParameterDocumentation, LuaBuiltInThemes.DefaultSignatureParameterDocumentation), + CreateBrush(semanticColors.SignatureActiveParameter, LuaBuiltInThemes.DefaultSignatureActiveParameter), + CreateBrush(semanticColors.SignatureText, ColorToString(TextEditorColorPalette.ToolTipForeground.Color))); + } - private static SolidColorBrush CreateBrush(string colorValue, string fallbackColorValue) + private static SolidColorBrush CreateBrush(string colorValue, string fallbackColorValue) + { + try { - try - { - string effectiveColorValue = string.IsNullOrWhiteSpace(colorValue) - ? fallbackColorValue - : colorValue; + string effectiveColorValue = string.IsNullOrWhiteSpace(colorValue) + ? fallbackColorValue + : colorValue; - return CreateFrozenBrush(effectiveColorValue); - } - catch - { - return CreateFrozenBrush(fallbackColorValue); - } + return CreateFrozenBrush(effectiveColorValue); + } + catch + { + return CreateFrozenBrush(fallbackColorValue); } - - private static string ColorToString(Color color) - => $"#{color.R:X2}{color.G:X2}{color.B:X2}"; } - internal sealed class LuaThemeBrushSet + private static string ColorToString(Color color) + => $"#{color.R:X2}{color.G:X2}{color.B:X2}"; +} + +internal sealed class LuaThemeBrushSet +{ + public LuaThemeBrushSet( + string themeName, + SolidColorBrush editorBackground, + SolidColorBrush editorForeground, + SolidColorBrush mutedText, + SolidColorBrush misc, + SolidColorBrush method, + SolidColorBrush variable, + SolidColorBrush property, + SolidColorBrush type, + SolidColorBrush keyword, + SolidColorBrush languageConstant, + SolidColorBrush constant, + SolidColorBrush file, + SolidColorBrush signatureParamDoc, + SolidColorBrush signatureActiveParam, + SolidColorBrush signatureForeground) { - public LuaThemeBrushSet( - string themeName, - SolidColorBrush editorBackground, - SolidColorBrush editorForeground, - SolidColorBrush mutedText, - SolidColorBrush misc, - SolidColorBrush method, - SolidColorBrush variable, - SolidColorBrush property, - SolidColorBrush type, - SolidColorBrush keyword, - SolidColorBrush languageConstant, - SolidColorBrush constant, - SolidColorBrush file, - SolidColorBrush signatureParamDoc, - SolidColorBrush signatureActiveParam, - SolidColorBrush signatureForeground) - { - ThemeName = themeName; - EditorBackground = editorBackground; - EditorForeground = editorForeground; - MutedTextBrush = mutedText; - MiscBrush = misc; - MethodBrush = method; - VariableBrush = variable; - PropertyBrush = property; - TypeBrush = type; - KeywordBrush = keyword; - LanguageConstantBrush = languageConstant; - ConstantBrush = constant; - FileBrush = file; - SignatureParamDocForeground = signatureParamDoc; - SignatureActiveParamForeground = signatureActiveParam; - SignatureForeground = signatureForeground; - } + ThemeName = themeName; + EditorBackground = editorBackground; + EditorForeground = editorForeground; + MutedTextBrush = mutedText; + MiscBrush = misc; + MethodBrush = method; + VariableBrush = variable; + PropertyBrush = property; + TypeBrush = type; + KeywordBrush = keyword; + LanguageConstantBrush = languageConstant; + ConstantBrush = constant; + FileBrush = file; + SignatureParamDocForeground = signatureParamDoc; + SignatureActiveParamForeground = signatureActiveParam; + SignatureForeground = signatureForeground; + } - public string ThemeName { get; } - public SolidColorBrush EditorBackground { get; } - public SolidColorBrush EditorForeground { get; } - public SolidColorBrush MutedTextBrush { get; } - public SolidColorBrush MiscBrush { get; } - public SolidColorBrush MethodBrush { get; } - public SolidColorBrush VariableBrush { get; } - public SolidColorBrush PropertyBrush { get; } - public SolidColorBrush TypeBrush { get; } - public SolidColorBrush KeywordBrush { get; } - public SolidColorBrush LanguageConstantBrush { get; } - public SolidColorBrush ConstantBrush { get; } - public SolidColorBrush FileBrush { get; } - public SolidColorBrush SignatureParamDocForeground { get; } - public SolidColorBrush SignatureActiveParamForeground { get; } - public SolidColorBrush SignatureForeground { get; } + public string ThemeName { get; } + public SolidColorBrush EditorBackground { get; } + public SolidColorBrush EditorForeground { get; } + public SolidColorBrush MutedTextBrush { get; } + public SolidColorBrush MiscBrush { get; } + public SolidColorBrush MethodBrush { get; } + public SolidColorBrush VariableBrush { get; } + public SolidColorBrush PropertyBrush { get; } + public SolidColorBrush TypeBrush { get; } + public SolidColorBrush KeywordBrush { get; } + public SolidColorBrush LanguageConstantBrush { get; } + public SolidColorBrush ConstantBrush { get; } + public SolidColorBrush FileBrush { get; } + public SolidColorBrush SignatureParamDocForeground { get; } + public SolidColorBrush SignatureActiveParamForeground { get; } + public SolidColorBrush SignatureForeground { get; } - public Brush GetCompletionItemBrush(Objects.LuaCompletionIconKind kind) + public Brush GetCompletionItemBrush(LuaCompletionIconKind kind) + { + return kind switch { - return kind switch - { - Objects.LuaCompletionIconKind.Variable => VariableBrush, - Objects.LuaCompletionIconKind.Field => PropertyBrush, - Objects.LuaCompletionIconKind.Method => MethodBrush, - Objects.LuaCompletionIconKind.Property => PropertyBrush, - Objects.LuaCompletionIconKind.Class => TypeBrush, - Objects.LuaCompletionIconKind.Keyword => KeywordBrush, - Objects.LuaCompletionIconKind.Constant => ConstantBrush, - Objects.LuaCompletionIconKind.Parameter => VariableBrush, - Objects.LuaCompletionIconKind.Namespace => TypeBrush, - Objects.LuaCompletionIconKind.File => FileBrush, - Objects.LuaCompletionIconKind.Folder => FileBrush, - _ => MiscBrush - }; - } + LuaCompletionIconKind.Variable => VariableBrush, + LuaCompletionIconKind.Field => PropertyBrush, + LuaCompletionIconKind.Method => MethodBrush, + LuaCompletionIconKind.Property => PropertyBrush, + LuaCompletionIconKind.Class => TypeBrush, + LuaCompletionIconKind.Keyword => KeywordBrush, + LuaCompletionIconKind.Constant => ConstantBrush, + LuaCompletionIconKind.Parameter => VariableBrush, + LuaCompletionIconKind.Namespace => TypeBrush, + LuaCompletionIconKind.File => FileBrush, + LuaCompletionIconKind.Folder => FileBrush, + _ => MiscBrush + }; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs index 0421e5e4b7..5c00372337 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs @@ -3,114 +3,112 @@ using System.IO; using System.Linq; using System.Text.Json; -using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua.Objects; -namespace TombLib.Scripting.Lua.Resources +namespace TombLib.Scripting.Lua.Resources; + +public static class LuaThemeRepository { - public static class LuaThemeRepository + private static readonly Lazy Catalog = new(LoadCatalog); + + public static IReadOnlyList GetAvailableThemes() + => Catalog.Value.Themes; + + public static string ResolveThemeName(string themeName) { - private static readonly Lazy Catalog = new Lazy(LoadCatalog); + LuaTheme theme = GetTheme(themeName); + return theme.Name; + } - public static IReadOnlyList GetAvailableThemes() - => Catalog.Value.Themes; + public static LuaTheme GetTheme(string themeName) + { + LuaThemeCatalog catalog = Catalog.Value; - public static string ResolveThemeName(string themeName) + if (!string.IsNullOrWhiteSpace(themeName) + && catalog.ThemesByLookupName.TryGetValue(themeName, out LuaTheme? theme) + && theme is not null) { - LuaTheme theme = GetTheme(themeName); - return theme.Name; + return theme; } - public static LuaTheme GetTheme(string themeName) - { - LuaThemeCatalog catalog = Catalog.Value; - - if (!string.IsNullOrWhiteSpace(themeName) - && catalog.ThemesByLookupName.TryGetValue(themeName, out LuaTheme? theme) - && theme is not null) - { - return theme; - } + return catalog.DefaultTheme; + } - return catalog.DefaultTheme; - } + private static LuaThemeCatalog LoadCatalog() + { + var themes = new List(); + string themesDirectory = DefaultPaths.LuaThemeConfigsDirectory; - private static LuaThemeCatalog LoadCatalog() + var serializerOptions = new JsonSerializerOptions { - var themes = new List(); - string themesDirectory = DefaultPaths.LuaThemeConfigsDirectory; - var serializerOptions = new JsonSerializerOptions - { - AllowTrailingCommas = true, - PropertyNameCaseInsensitive = true, - ReadCommentHandling = JsonCommentHandling.Skip - }; + AllowTrailingCommas = true, + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip + }; - if (Directory.Exists(themesDirectory)) + if (Directory.Exists(themesDirectory)) + { + foreach (string filePath in Directory.GetFiles(themesDirectory, "*.json", SearchOption.TopDirectoryOnly)) { - foreach (string filePath in Directory.GetFiles(themesDirectory, "*.json", SearchOption.TopDirectoryOnly)) + try { - try - { - string fileContent = File.ReadAllText(filePath); - LuaTheme? theme = JsonSerializer.Deserialize(fileContent, serializerOptions); - - if (theme is not null) - themes.Add(theme.Normalize(Path.GetFileNameWithoutExtension(filePath))); - } - catch - { - } + string fileContent = File.ReadAllText(filePath); + LuaTheme? theme = JsonSerializer.Deserialize(fileContent, serializerOptions); + + if (theme is not null) + themes.Add(theme.Normalize(Path.GetFileNameWithoutExtension(filePath))); } + catch + { } } + } - if (themes.Count == 0) - themes.Add(LuaBuiltInThemes.CreateDefaultTheme().Normalize(ConfigurationDefaults.SelectedThemeName)); + if (themes.Count == 0) + themes.Add(LuaBuiltInThemes.CreateDefaultTheme().Normalize(ConfigurationDefaults.SelectedThemeName)); - var orderedThemes = themes - .OrderByDescending(theme => string.Equals(theme.Name, ConfigurationDefaults.SelectedThemeName, StringComparison.OrdinalIgnoreCase)) - .ThenBy(theme => theme.Name, StringComparer.OrdinalIgnoreCase) - .ToList(); + var orderedThemes = themes + .OrderByDescending(theme => string.Equals(theme.Name, ConfigurationDefaults.SelectedThemeName, StringComparison.OrdinalIgnoreCase)) + .ThenBy(theme => theme.Name, StringComparer.OrdinalIgnoreCase) + .ToList(); - var themesByLookupName = new Dictionary(StringComparer.OrdinalIgnoreCase); + var themesByLookupName = new Dictionary(StringComparer.OrdinalIgnoreCase); - for (int i = 0; i < orderedThemes.Count; i++) - { - LuaTheme theme = orderedThemes[i]; - AddLookupName(themesByLookupName, theme.Name, theme); + for (int i = 0; i < orderedThemes.Count; i++) + { + LuaTheme theme = orderedThemes[i]; + AddLookupName(themesByLookupName, theme.Name, theme); - for (int aliasIndex = 0; aliasIndex < theme.Aliases.Count; aliasIndex++) - AddLookupName(themesByLookupName, theme.Aliases[aliasIndex], theme); - } + for (int aliasIndex = 0; aliasIndex < theme.Aliases.Count; aliasIndex++) + AddLookupName(themesByLookupName, theme.Aliases[aliasIndex], theme); + } - LuaTheme defaultTheme = themesByLookupName.TryGetValue(ConfigurationDefaults.SelectedThemeName, out LuaTheme? configuredTheme) - && configuredTheme is not null - ? configuredTheme - : orderedThemes[0]; + LuaTheme defaultTheme = themesByLookupName.TryGetValue(ConfigurationDefaults.SelectedThemeName, out LuaTheme? configuredTheme) + && configuredTheme is not null + ? configuredTheme + : orderedThemes[0]; - return new LuaThemeCatalog(orderedThemes, themesByLookupName, defaultTheme); - } + return new LuaThemeCatalog(orderedThemes, themesByLookupName, defaultTheme); + } - private static void AddLookupName(IDictionary themesByLookupName, string lookupName, LuaTheme theme) - { - if (string.IsNullOrWhiteSpace(lookupName) || themesByLookupName.ContainsKey(lookupName)) - return; + private static void AddLookupName(IDictionary themesByLookupName, string lookupName, LuaTheme theme) + { + if (string.IsNullOrWhiteSpace(lookupName) || themesByLookupName.ContainsKey(lookupName)) + return; - themesByLookupName[lookupName] = theme; - } + themesByLookupName[lookupName] = theme; + } - private sealed class LuaThemeCatalog + private sealed class LuaThemeCatalog + { + public LuaThemeCatalog(IReadOnlyList themes, IReadOnlyDictionary themesByLookupName, LuaTheme defaultTheme) { - public LuaThemeCatalog(IReadOnlyList themes, IReadOnlyDictionary themesByLookupName, LuaTheme defaultTheme) - { - Themes = themes; - ThemesByLookupName = themesByLookupName; - DefaultTheme = defaultTheme; - } - - public IReadOnlyList Themes { get; } - public IReadOnlyDictionary ThemesByLookupName { get; } - public LuaTheme DefaultTheme { get; } + Themes = themes; + ThemesByLookupName = themesByLookupName; + DefaultTheme = defaultTheme; } + + public IReadOnlyList Themes { get; } + public IReadOnlyDictionary ThemesByLookupName { get; } + public LuaTheme DefaultTheme { get; } } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs index e7ec28523a..2329eb454b 100644 --- a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs +++ b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs @@ -5,31 +5,35 @@ using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Objects; -namespace TombLib.Scripting.Lua.Services +namespace TombLib.Scripting.Lua.Services; + +public interface ILuaIntellisenseProvider : IDisposable { - public interface ILuaIntellisenseProvider : IDisposable - { - bool IsAvailable { get; } - event Action>? DiagnosticsUpdated; - event Action>? SemanticTokensUpdated; + bool IsAvailable { get; } + + event Action>? DiagnosticsUpdated; + + event Action>? SemanticTokensUpdated; + + IReadOnlyList GetDiagnostics(string filePath); + + IReadOnlyList GetSemanticTokens(string filePath); + + void OpenDocument(string filePath, string content); - IReadOnlyList GetDiagnostics(string filePath); - IReadOnlyList GetSemanticTokens(string filePath); + void UpdateDocument(string filePath, string content); - void OpenDocument(string filePath, string content); - void UpdateDocument(string filePath, string content); - void CloseDocument(string filePath); + void CloseDocument(string filePath); - Task> GetCompletionItemsAsync(string filePath, string content, - int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default); + Task> GetCompletionItemsAsync(string filePath, string content, + int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default); - Task GetHoverAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default); + Task GetHoverAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); - Task GetDefinitionAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default); + Task GetDefinitionAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); - Task GetSignatureHelpAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default); - } -} \ No newline at end of file + Task GetSignatureHelpAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); +} diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index e059239f18..f747d18305 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -1,6 +1,7 @@  net6.0-windows + 12 Library false enable diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs index ffaa5b5cea..553b6f63ab 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -1,139 +1,137 @@ -using System; using ICSharpCode.AvalonEdit.Document; +using System; + +namespace TombLib.Scripting.Lua.Utils; -namespace TombLib.Scripting.Lua.Utils +internal static class LuaEditorInteractionRules { - internal static class LuaEditorInteractionRules + public static bool CanRequestHover(TextDocument? document, int offset, bool isCompletionWindowOpen, bool isSignatureHelpOpen) { - public static bool CanRequestHover(TextDocument? document, int offset, bool isCompletionWindowOpen, bool isSignatureHelpOpen) - { - if (isCompletionWindowOpen || isSignatureHelpOpen) - return false; + if (isCompletionWindowOpen || isSignatureHelpOpen) + return false; - return !IsInsideCommentOrString(document, offset); - } + return !IsInsideCommentOrString(document, offset); + } - public static bool TryGetHoverOffset(TextDocument? document, int offset, out int hoverOffset) - { - hoverOffset = 0; + public static bool TryGetHoverOffset(TextDocument? document, int offset, out int hoverOffset) + { + hoverOffset = 0; - if (document is null || document.TextLength == 0) - return false; + if (document is null || document.TextLength == 0) + return false; - int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); - if (safeOffset >= document.TextLength) - return false; + if (safeOffset >= document.TextLength) + return false; - if (IsInsideCommentOrString(document, safeOffset)) - return false; + if (IsInsideCommentOrString(document, safeOffset)) + return false; - if (!LuaLineParser.IsIdentifierCharacter(document.GetCharAt(safeOffset))) - return false; + if (!LuaLineParser.IsIdentifierCharacter(document.GetCharAt(safeOffset))) + return false; - hoverOffset = safeOffset; - return true; - } + hoverOffset = safeOffset; + return true; + } - public static bool IsValidAutocompleteContext(TextDocument? document, int offset, char? triggerCharacter) - { - if (offset <= 0 || document is null || document.TextLength == 0) - return false; + public static bool IsValidAutocompleteContext(TextDocument? document, int offset, char? triggerCharacter) + { + if (offset <= 0 || document is null || document.TextLength == 0) + return false; - if (IsInsideCommentOrString(document, offset)) - return false; + if (IsInsideCommentOrString(document, offset)) + return false; - if (triggerCharacter is '.' || triggerCharacter is ':') - return true; + if (triggerCharacter is '.' || triggerCharacter is ':') + return true; - char typedCharacter = document.GetCharAt(offset - 1); + char typedCharacter = document.GetCharAt(offset - 1); - if (!LuaLineParser.IsIdentifierCharacter(typedCharacter)) - return false; + if (!LuaLineParser.IsIdentifierCharacter(typedCharacter)) + return false; - if (offset >= 2 && document.GetCharAt(offset - 2) == '.') - return false; + if (offset >= 2 && document.GetCharAt(offset - 2) == '.') + return false; - return true; - } + return true; + } - public static bool IsValidManualCompletionContext(TextDocument? document, int offset) - { - if (document is null) - return false; + public static bool IsValidManualCompletionContext(TextDocument? document, int offset) + { + if (document is null) + return false; - if (document.TextLength == 0) - return true; + if (document.TextLength == 0) + return true; - return !IsInsideCommentOrString(document, offset); - } + return !IsInsideCommentOrString(document, offset); + } - public static bool TryGetDefinitionStartOffset(TextDocument? document, int offset, out int definitionOffset) - { - definitionOffset = 0; + public static bool TryGetDefinitionStartOffset(TextDocument? document, int offset, out int definitionOffset) + { + definitionOffset = 0; - if (document is null || document.TextLength == 0) - return false; + if (document is null || document.TextLength == 0) + return false; - int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); - if (IsInsideCommentOrString(document, safeOffset)) - return false; + if (IsInsideCommentOrString(document, safeOffset)) + return false; - if (!TryGetDefinitionWordBounds(document, safeOffset, out definitionOffset, out _)) - return false; + if (!TryGetDefinitionWordBounds(document, safeOffset, out definitionOffset, out _)) + return false; - return true; - } + return true; + } - public static bool IsInsideCommentOrString(TextDocument? document, int offset) - { - if (document is null || document.TextLength == 0) - return false; + public static bool IsInsideCommentOrString(TextDocument? document, int offset) + { + if (document is null || document.TextLength == 0) + return false; - int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); - DocumentLine currentLine = document.GetLineByOffset(safeOffset); - int lineStart = currentLine.Offset; - int inspectedLength = Math.Max(0, Math.Min(safeOffset, currentLine.EndOffset) - lineStart); - string lineText = document.GetText(lineStart, inspectedLength); + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + DocumentLine currentLine = document.GetLineByOffset(safeOffset); + int lineStart = currentLine.Offset; + int inspectedLength = Math.Max(0, Math.Min(safeOffset, currentLine.EndOffset) - lineStart); + string lineText = document.GetText(lineStart, inspectedLength); - return LuaLineParser.IsInsideCommentOrString(lineText); - } + return LuaLineParser.IsInsideCommentOrString(lineText); + } - private static bool TryGetDefinitionWordBounds(TextDocument document, int offset, out int wordStart, out int wordEnd) - { - wordStart = 0; - wordEnd = 0; + private static bool TryGetDefinitionWordBounds(TextDocument document, int offset, out int wordStart, out int wordEnd) + { + wordStart = 0; + wordEnd = 0; - if (document.TextLength == 0) - return false; + if (document.TextLength == 0) + return false; - int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); - int probeOffset = safeOffset; + int probeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); - if (probeOffset >= document.TextLength) - probeOffset = document.TextLength - 1; + if (probeOffset >= document.TextLength) + probeOffset = document.TextLength - 1; - if (probeOffset > 0 - && !LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset)) - && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset - 1))) - { - probeOffset--; - } + if (probeOffset > 0 + && !LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset)) + && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset - 1))) + { + probeOffset--; + } - if (!LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset))) - return false; + if (!LuaLineParser.IsIdentifierCharacter(document.GetCharAt(probeOffset))) + return false; - wordStart = probeOffset; - wordEnd = probeOffset + 1; + wordStart = probeOffset; + wordEnd = probeOffset + 1; - while (wordStart > 0 && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(wordStart - 1))) - wordStart--; + while (wordStart > 0 && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(wordStart - 1))) + wordStart--; - while (wordEnd < document.TextLength && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(wordEnd))) - wordEnd++; + while (wordEnd < document.TextLength && LuaLineParser.IsIdentifierCharacter(document.GetCharAt(wordEnd))) + wordEnd++; - return wordEnd > wordStart; - } + return wordEnd > wordStart; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs index 8e200961ff..88ca0857ef 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -1,321 +1,324 @@ using System.Collections.Generic; using System.Text; -namespace TombLib.Scripting.Lua.Utils +namespace TombLib.Scripting.Lua.Utils; + +internal static class LuaLineParser { - internal static class LuaLineParser + private enum ParserState { - private enum ParserState - { - None, - SingleQuotedString, - DoubleQuotedString, - LongString, - LongComment - } + None, + SingleQuotedString, + DoubleQuotedString, + LongString, + LongComment + } - public static bool IsIdentifierCharacter(char character) - => char.IsLetterOrDigit(character) || character == '_'; + public static bool IsIdentifierCharacter(char character) + => char.IsLetterOrDigit(character) || character == '_'; - public static bool IsIdentifierTriggerCharacter(char character) - => char.IsLetter(character) || character == '_'; + public static bool IsIdentifierTriggerCharacter(char character) + => char.IsLetter(character) || character == '_'; - public static bool IsInsideCommentOrString(string lineText) - { - if (string.IsNullOrEmpty(lineText)) - return false; + public static bool IsInsideCommentOrString(string lineText) + { + if (string.IsNullOrEmpty(lineText)) + return false; - ParserState state = ParserState.None; - int longBracketEqualsCount = 0; + ParserState state = ParserState.None; + int longBracketEqualsCount = 0; - for (int i = 0; i < lineText.Length; i++) - { - char currentChar = lineText[i]; + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; - if (state == ParserState.LongString || state == ParserState.LongComment) + if (state == ParserState.LongString || state == ParserState.LongComment) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) { - if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) - { - i += endTokenLength - 1; - state = ParserState.None; - } - - continue; + i += endTokenLength - 1; + state = ParserState.None; } - if (state == ParserState.SingleQuotedString) - { - if (currentChar == '\\' && i + 1 < lineText.Length) - { - i++; - continue; - } - - if (currentChar == '\'') - state = ParserState.None; + continue; + } + if (state == ParserState.SingleQuotedString) + { + if (currentChar == '\\' && i + 1 < lineText.Length) + { + i++; continue; } - if (state == ParserState.DoubleQuotedString) - { - if (currentChar == '\\' && i + 1 < lineText.Length) - { - i++; - continue; - } - - if (currentChar == '"') - state = ParserState.None; + if (currentChar == '\'') + state = ParserState.None; - continue; - } + continue; + } - if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + if (state == ParserState.DoubleQuotedString) + { + if (currentChar == '\\' && i + 1 < lineText.Length) { - state = ParserState.LongComment; - i += longCommentStartLength - 1; + i++; continue; } - if (IsLineCommentStart(lineText, i)) - return true; + if (currentChar == '"') + state = ParserState.None; - if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) - { - state = ParserState.LongString; - i += longStringStartLength - 1; - continue; - } + continue; + } - if (currentChar == '\'') - state = ParserState.SingleQuotedString; - else if (currentChar == '"') - state = ParserState.DoubleQuotedString; + if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + { + state = ParserState.LongComment; + i += longCommentStartLength - 1; + continue; } - return state != ParserState.None; + if (IsLineCommentStart(lineText, i)) + return true; + + if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) + { + state = ParserState.LongString; + i += longStringStartLength - 1; + continue; + } + + if (currentChar == '\'') + state = ParserState.SingleQuotedString; + else if (currentChar == '"') + state = ParserState.DoubleQuotedString; } - public static string StripLineComment(string lineText) - { - if (string.IsNullOrEmpty(lineText)) - return string.Empty; + return state != ParserState.None; + } - var builder = new StringBuilder(lineText.Length); - ParserState state = ParserState.None; - int longBracketEqualsCount = 0; + public static string StripLineComment(string lineText) + { + if (string.IsNullOrEmpty(lineText)) + return string.Empty; - for (int i = 0; i < lineText.Length; i++) - { - char currentChar = lineText[i]; + var builder = new StringBuilder(lineText.Length); + ParserState state = ParserState.None; + int longBracketEqualsCount = 0; - if (state == ParserState.LongComment) - { - if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) - { - i += endTokenLength - 1; - state = ParserState.None; - } + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; - continue; + if (state == ParserState.LongComment) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) + { + i += endTokenLength - 1; + state = ParserState.None; } - if (state == ParserState.LongString) - { - if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) - { - builder.Append(lineText, i, endTokenLength); - i += endTokenLength - 1; - state = ParserState.None; - } - else - builder.Append(currentChar); + continue; + } - continue; + if (state == ParserState.LongString) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) + { + builder.Append(lineText, i, endTokenLength); + i += endTokenLength - 1; + state = ParserState.None; } - - if (state == ParserState.SingleQuotedString || state == ParserState.DoubleQuotedString) + else { builder.Append(currentChar); + } - if (currentChar == '\\' && i + 1 < lineText.Length) - { - builder.Append(lineText[i + 1]); - i++; - continue; - } - - if ((state == ParserState.SingleQuotedString && currentChar == '\'') - || (state == ParserState.DoubleQuotedString && currentChar == '"')) - { - state = ParserState.None; - } + continue; + } - continue; - } + if (state == ParserState.SingleQuotedString || state == ParserState.DoubleQuotedString) + { + builder.Append(currentChar); - if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + if (currentChar == '\\' && i + 1 < lineText.Length) { - state = ParserState.LongComment; - i += longCommentStartLength - 1; + builder.Append(lineText[i + 1]); + i++; continue; } - if (IsLineCommentStart(lineText, i)) - break; - - if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) + if ((state == ParserState.SingleQuotedString && currentChar == '\'') + || (state == ParserState.DoubleQuotedString && currentChar == '"')) { - builder.Append(lineText, i, longStringStartLength); - state = ParserState.LongString; - i += longStringStartLength - 1; - continue; + state = ParserState.None; } - if (currentChar == '\'') - state = ParserState.SingleQuotedString; - else if (currentChar == '"') - state = ParserState.DoubleQuotedString; + continue; + } - builder.Append(currentChar); + if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + { + state = ParserState.LongComment; + i += longCommentStartLength - 1; + continue; } - return builder.ToString(); - } + if (IsLineCommentStart(lineText, i)) + break; - public static IEnumerable EnumerateStructuralCharacters(string lineText) - { - if (string.IsNullOrEmpty(lineText)) - yield break; + if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) + { + builder.Append(lineText, i, longStringStartLength); + state = ParserState.LongString; + i += longStringStartLength - 1; + continue; + } - ParserState state = ParserState.None; - int longBracketEqualsCount = 0; + if (currentChar == '\'') + state = ParserState.SingleQuotedString; + else if (currentChar == '"') + state = ParserState.DoubleQuotedString; - for (int i = 0; i < lineText.Length; i++) - { - char currentChar = lineText[i]; + builder.Append(currentChar); + } - if (state == ParserState.LongComment || state == ParserState.LongString) - { - if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) - { - i += endTokenLength - 1; - state = ParserState.None; - } + return builder.ToString(); + } - continue; - } + public static IEnumerable EnumerateStructuralCharacters(string lineText) + { + if (string.IsNullOrEmpty(lineText)) + yield break; - if (state == ParserState.SingleQuotedString || state == ParserState.DoubleQuotedString) - { - if (currentChar == '\\' && i + 1 < lineText.Length) - i++; - else if ((state == ParserState.SingleQuotedString && currentChar == '\'') - || (state == ParserState.DoubleQuotedString && currentChar == '"')) - { - state = ParserState.None; - } + ParserState state = ParserState.None; + int longBracketEqualsCount = 0; - continue; - } + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; - if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + if (state == ParserState.LongComment || state == ParserState.LongString) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) { - state = ParserState.LongComment; - i += longCommentStartLength - 1; - continue; + i += endTokenLength - 1; + state = ParserState.None; } - if (IsLineCommentStart(lineText, i)) - yield break; + continue; + } - if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) + if (state == ParserState.SingleQuotedString || state == ParserState.DoubleQuotedString) + { + if (currentChar == '\\' && i + 1 < lineText.Length) { - state = ParserState.LongString; - i += longStringStartLength - 1; - continue; + i++; } - - if (currentChar == '\'') + else if ((state == ParserState.SingleQuotedString && currentChar == '\'') + || (state == ParserState.DoubleQuotedString && currentChar == '"')) { - state = ParserState.SingleQuotedString; - continue; + state = ParserState.None; } - if (currentChar == '"') - { - state = ParserState.DoubleQuotedString; - continue; - } + continue; + } - yield return currentChar; + if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + { + state = ParserState.LongComment; + i += longCommentStartLength - 1; + continue; } - } - private static bool TryMatchLongCommentStart(string lineText, int index, out int equalsCount, out int tokenLength) - { - equalsCount = 0; - tokenLength = 0; + if (IsLineCommentStart(lineText, i)) + yield break; - if (!IsLineCommentStart(lineText, index) || !TryMatchLongBracketStart(lineText, index + 2, out equalsCount, out int bracketTokenLength)) - return false; + if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) + { + state = ParserState.LongString; + i += longStringStartLength - 1; + continue; + } + + if (currentChar == '\'') + { + state = ParserState.SingleQuotedString; + continue; + } + + if (currentChar == '"') + { + state = ParserState.DoubleQuotedString; + continue; + } - tokenLength = 2 + bracketTokenLength; - return true; + yield return currentChar; } + } - private static bool TryMatchLongBracketStart(string lineText, int index, out int equalsCount, out int tokenLength) - { - equalsCount = 0; - tokenLength = 0; + private static bool TryMatchLongCommentStart(string lineText, int index, out int equalsCount, out int tokenLength) + { + equalsCount = 0; + tokenLength = 0; - if (index >= lineText.Length || lineText[index] != '[') - return false; + if (!IsLineCommentStart(lineText, index) || !TryMatchLongBracketStart(lineText, index + 2, out equalsCount, out int bracketTokenLength)) + return false; - int probeIndex = index + 1; + tokenLength = 2 + bracketTokenLength; + return true; + } - while (probeIndex < lineText.Length && lineText[probeIndex] == '=') - { - equalsCount++; - probeIndex++; - } + private static bool TryMatchLongBracketStart(string lineText, int index, out int equalsCount, out int tokenLength) + { + equalsCount = 0; + tokenLength = 0; - if (probeIndex >= lineText.Length || lineText[probeIndex] != '[') - { - equalsCount = 0; - return false; - } + if (index >= lineText.Length || lineText[index] != '[') + return false; - tokenLength = probeIndex - index + 1; - return true; + int probeIndex = index + 1; + + while (probeIndex < lineText.Length && lineText[probeIndex] == '=') + { + equalsCount++; + probeIndex++; } - private static bool TryMatchLongBracketEnd(string lineText, int index, int equalsCount, out int tokenLength) + if (probeIndex >= lineText.Length || lineText[probeIndex] != '[') { - tokenLength = 0; + equalsCount = 0; + return false; + } - if (index >= lineText.Length || lineText[index] != ']') - return false; + tokenLength = probeIndex - index + 1; + return true; + } - int probeIndex = index + 1; + private static bool TryMatchLongBracketEnd(string lineText, int index, int equalsCount, out int tokenLength) + { + tokenLength = 0; - for (int i = 0; i < equalsCount; i++) - { - if (probeIndex >= lineText.Length || lineText[probeIndex] != '=') - return false; + if (index >= lineText.Length || lineText[index] != ']') + return false; - probeIndex++; - } + int probeIndex = index + 1; - if (probeIndex >= lineText.Length || lineText[probeIndex] != ']') + for (int i = 0; i < equalsCount; i++) + { + if (probeIndex >= lineText.Length || lineText[probeIndex] != '=') return false; - tokenLength = probeIndex - index + 1; - return true; + probeIndex++; } - private static bool IsLineCommentStart(string lineText, int index) - => lineText[index] == '-' && index + 1 < lineText.Length && lineText[index + 1] == '-'; + if (probeIndex >= lineText.Length || lineText[probeIndex] != ']') + return false; + + tokenLength = probeIndex - index + 1; + return true; } -} \ No newline at end of file + + private static bool IsLineCommentStart(string lineText, int index) + => lineText[index] == '-' && index + 1 < lineText.Length && lineText[index + 1] == '-'; +} diff --git a/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs index 2f5e1a2d3a..bbd57e6ce3 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs @@ -1,135 +1,134 @@ +using ICSharpCode.AvalonEdit.Document; using System; using System.Text.RegularExpressions; -using ICSharpCode.AvalonEdit.Document; -namespace TombLib.Scripting.Lua.Utils +namespace TombLib.Scripting.Lua.Utils; + +public sealed class TombEngineLanguageScriptService { - public sealed class TombEngineLanguageScriptService - { - private static readonly Regex SetStringsRegex = new( - @"TEN\.Flow\.SetStrings\s*\(\s*(?[^)\s]+)\s*\)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + private static readonly Regex SetStringsRegex = new( + @"TEN\.Flow\.SetStrings\s*\(\s*(?[^)\s]+)\s*\)", + RegexOptions.Compiled | RegexOptions.IgnoreCase); - public int? TryInsertLanguageScript(TextDocument document, string languageScript) - { - string? stringsVariableName = TryGetStringsVariableName(document); + public int? TryInsertLanguageScript(TextDocument document, string languageScript) + { + string? stringsVariableName = TryGetStringsVariableName(document); - if (stringsVariableName is null) - return null; + if (stringsVariableName is null) + return null; - DocumentLine? stringsStartLine = FindStringsStartLine(document, stringsVariableName); + DocumentLine? stringsStartLine = FindStringsStartLine(document, stringsVariableName); - if (stringsStartLine is null) - return null; + if (stringsStartLine is null) + return null; - DocumentLine? stopLine = FindStringsStopLine(document, stringsStartLine); + DocumentLine? stopLine = FindStringsStopLine(document, stringsStartLine); - if (stopLine is null) - return null; + if (stopLine is null) + return null; - DocumentLine? insertionLine = FindLanguageInsertionLine(document, stringsStartLine, stopLine); + DocumentLine? insertionLine = FindLanguageInsertionLine(document, stringsStartLine, stopLine); - if (insertionLine is not null) - return InsertLanguageScript(document, languageScript, insertionLine); + if (insertionLine is not null) + return InsertLanguageScript(document, languageScript, insertionLine); - return InsertLanguageScriptIntoEmptyTable(document, languageScript, stopLine); - } + return InsertLanguageScriptIntoEmptyTable(document, languageScript, stopLine); + } - private static string? TryGetStringsVariableName(TextDocument document) + private static string? TryGetStringsVariableName(TextDocument document) + { + foreach (DocumentLine line in document.Lines) { - foreach (DocumentLine line in document.Lines) - { - string lineText = LuaLineParser.StripLineComment(document.GetText(line)); - Match match = SetStringsRegex.Match(lineText); + string lineText = LuaLineParser.StripLineComment(document.GetText(line)); + Match match = SetStringsRegex.Match(lineText); - if (match.Success) - return match.Groups["name"].Value; - } - - return null; + if (match.Success) + return match.Groups["name"].Value; } - private static DocumentLine? FindStringsStartLine(TextDocument document, string stringsVariableName) - { - Regex regex = CreateStringsStartRegex(stringsVariableName); + return null; + } - foreach (DocumentLine line in document.Lines) - { - if (regex.IsMatch(LuaLineParser.StripLineComment(document.GetText(line)))) - return line; - } + private static DocumentLine? FindStringsStartLine(TextDocument document, string stringsVariableName) + { + Regex regex = CreateStringsStartRegex(stringsVariableName); - return null; + foreach (DocumentLine line in document.Lines) + { + if (regex.IsMatch(LuaLineParser.StripLineComment(document.GetText(line)))) + return line; } - private static Regex CreateStringsStartRegex(string stringsVariableName) - => new(@"^\s*local\s+" + Regex.Escape(stringsVariableName) + @"\s*=", RegexOptions.Compiled); + return null; + } + + private static Regex CreateStringsStartRegex(string stringsVariableName) + => new(@"^\s*local\s+" + Regex.Escape(stringsVariableName) + @"\s*=", RegexOptions.Compiled); + + private static DocumentLine? FindStringsStopLine(TextDocument document, DocumentLine stringsStartLine) + { + int bracketDepth = 0; + bool foundOpeningBracket = false; - private static DocumentLine? FindStringsStopLine(TextDocument document, DocumentLine stringsStartLine) + for (DocumentLine? line = stringsStartLine; line is not null; line = line.NextLine) { - int bracketDepth = 0; - bool foundOpeningBracket = false; + string lineText = LuaLineParser.StripLineComment(document.GetText(line)); - for (DocumentLine? line = stringsStartLine; line is not null; line = line.NextLine) + foreach (char character in LuaLineParser.EnumerateStructuralCharacters(lineText)) { - string lineText = LuaLineParser.StripLineComment(document.GetText(line)); - - foreach (char character in LuaLineParser.EnumerateStructuralCharacters(lineText)) + if (character == '{') { - if (character == '{') - { - bracketDepth++; - foundOpeningBracket = true; - } - else if (character == '}') - { - if (!foundOpeningBracket || bracketDepth == 0) - return null; - - bracketDepth--; - - if (bracketDepth == 0) - return line; - } + bracketDepth++; + foundOpeningBracket = true; } - } + else if (character == '}') + { + if (!foundOpeningBracket || bracketDepth == 0) + return null; - return null; - } + bracketDepth--; - private static DocumentLine? FindLanguageInsertionLine(TextDocument document, DocumentLine stringsStartLine, DocumentLine stopLine) - { - for (int i = stopLine.LineNumber - 1; i > stringsStartLine.LineNumber; i--) - { - DocumentLine line = document.GetLineByNumber(i); - string cleanLine = LuaLineParser.StripLineComment(document.GetText(line)).TrimEnd(); - - if (cleanLine.EndsWith("}") || cleanLine.EndsWith("},")) - return line; + if (bracketDepth == 0) + return line; + } } - - return null; } - private static int InsertLanguageScript(TextDocument document, string languageScript, DocumentLine insertionLine) - { - string rawLine = document.GetText(insertionLine); - string cleanLine = LuaLineParser.StripLineComment(rawLine).TrimEnd(); + return null; + } - if (cleanLine.EndsWith("}")) - { - int commaOffset = insertionLine.Offset + cleanLine.Length; - document.Insert(commaOffset, ","); - } + private static DocumentLine? FindLanguageInsertionLine(TextDocument document, DocumentLine stringsStartLine, DocumentLine stopLine) + { + for (int i = stopLine.LineNumber - 1; i > stringsStartLine.LineNumber; i--) + { + DocumentLine line = document.GetLineByNumber(i); + string cleanLine = LuaLineParser.StripLineComment(document.GetText(line)).TrimEnd(); - document.Insert(insertionLine.EndOffset, Environment.NewLine + languageScript); - return insertionLine.LineNumber + 1; + if (cleanLine.EndsWith("}") || cleanLine.EndsWith("},")) + return line; } - private static int InsertLanguageScriptIntoEmptyTable(TextDocument document, string languageScript, DocumentLine stopLine) + return null; + } + + private static int InsertLanguageScript(TextDocument document, string languageScript, DocumentLine insertionLine) + { + string rawLine = document.GetText(insertionLine); + string cleanLine = LuaLineParser.StripLineComment(rawLine).TrimEnd(); + + if (cleanLine.EndsWith("}")) { - document.Insert(stopLine.Offset, languageScript + Environment.NewLine); - return stopLine.LineNumber; + int commaOffset = insertionLine.Offset + cleanLine.Length; + document.Insert(commaOffset, ","); } + + document.Insert(insertionLine.EndOffset, Environment.NewLine + languageScript); + return insertionLine.LineNumber + 1; + } + + private static int InsertLanguageScriptIntoEmptyTable(TextDocument document, string languageScript, DocumentLine stopLine) + { + document.Insert(stopLine.Offset, languageScript + Environment.NewLine); + return stopLine.LineNumber; } -} \ No newline at end of file +} From 97096cd5da270cdceb1ab319b11bcc6bebeb28ac Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 20:29:06 +0100 Subject: [PATCH 12/34] Docs --- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 4 - .../LuaEditor.Navigation.cs | 3 + .../LuaEditor.SemanticHighlighting.cs | 7 ++ TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 20 +++++ .../LuaEditorConfiguration.cs | 18 ++++ .../Objects/LuaCompletionIconKind.cs | 50 +++++++++++ .../Objects/LuaCompletionItem.cs | 55 ++++++++++++ .../Objects/LuaDefinitionLocation.cs | 20 +++++ .../Objects/LuaHoverInfo.cs | 15 ++++ .../Objects/LuaSemanticToken.cs | 35 ++++++++ .../Objects/LuaSignatureInfo.cs | 40 +++++++++ .../TombLib.Scripting.Lua/Objects/LuaTheme.cs | 88 +++++++++++++++++++ .../Resources/ConfigurationDefaults.cs | 9 ++ .../Resources/LuaBuiltInThemes.cs | 7 ++ .../Resources/LuaThemeRepository.cs | 17 ++++ .../Services/ILuaIntellisenseProvider.cs | 73 +++++++++++++++ .../Utils/LuaEditorInteractionRules.cs | 44 ++++++++++ .../Utils/LuaLineParser.cs | 28 ++++++ .../Utils/TombEngineLanguageScriptService.cs | 9 ++ 19 files changed, 538 insertions(+), 4 deletions(-) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index bc3b893dee..2e1e377b72 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -25,7 +25,6 @@ protected override async void HandleMouseHover(MouseEventArgs e) return; bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); - bool isCompletionWindowOpen = _completionWindow is not null; if (!LuaEditorInteractionRules.CanRequestHover(Document, hoveredOffset, isCompletionWindowOpen, _signaturePopup.IsOpen)) @@ -45,7 +44,6 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (!IsIntellisenseAvailable()) { ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - return; } @@ -54,7 +52,6 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (string.IsNullOrWhiteSpace(hoveredWord)) { ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - return; } @@ -83,7 +80,6 @@ protected override async void HandleMouseHover(MouseEventArgs e) catch (Exception exception) { WriteDebugFailure("Hover request", exception); - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index ca25aea422..bf29db6494 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -86,6 +86,9 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo } } + /// + /// Attempts to resolve and navigate to the symbol definition at the current caret position. + /// public async void NavigateToDefinitionAtCaretAsync() => await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true); } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs index 8995157f51..bbbc711526 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs @@ -8,12 +8,19 @@ public sealed partial class LuaEditor { private LuaSemanticTokensColorizer? _semanticTokensColorizer; + /// + /// Replaces the current semantic token set used to colorize the document. + /// + /// The semantic tokens to apply to the editor. public void SetSemanticTokens(IReadOnlyList tokens) { EnsureSemanticTokensColorizerAttached(); _semanticTokensColorizer!.SetTokens(tokens); } + /// + /// Removes all semantic token formatting from the current document. + /// public void ClearSemanticTokens() => _semanticTokensColorizer?.ClearTokens(); diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index 34799c0333..4e7e01ffa8 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -7,17 +7,33 @@ namespace TombLib.Scripting.Lua; +/// +/// Provides a Lua-specific text editor with syntax highlighting, semantic coloring, and language-service integration. +/// public sealed partial class LuaEditor : TextEditorBase { + /// + /// Gets the default file extension associated with Lua documents. + /// public override string DefaultFileExtension => ".lua"; private LuaTextMateInstallation? _textMateHighlighting; private LuaThemeBrushSet? _themeBrushSet; + /// + /// Gets or sets the IntelliSense provider used to supply completions, hover text, diagnostics, and navigation results. + /// public ILuaIntellisenseProvider? IntellisenseProvider { get; set; } + /// + /// Occurs when the editor resolves a definition location that should be opened by the host application. + /// public event Action? DefinitionNavigationRequested; + /// + /// Initializes a new instance of the class for the specified engine version. + /// + /// The engine version used to configure editor behavior. public LuaEditor(Version engineVersion) : base(engineVersion) { CommentPrefix = "--"; @@ -25,6 +41,10 @@ public LuaEditor(Version engineVersion) : base(engineVersion) BindLuaIntellisenseEvents(); } + /// + /// Applies the active Lua theme, refreshes syntax highlighting, and updates shared editor settings. + /// + /// The editor configuration to apply. public override void UpdateSettings(Bases.ConfigurationBase configuration) { var config = configuration as LuaEditorConfiguration; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs index c3a3b633f0..328a6046e9 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditorConfiguration.cs @@ -5,12 +5,21 @@ namespace TombLib.Scripting.Lua; +/// +/// Stores user-configurable settings for the Lua editor. +/// public sealed class LuaEditorConfiguration : TextEditorConfigBase { + /// + /// Gets the default file path used to persist this configuration. + /// public override string DefaultPath { get; } private string _selectedThemeName = ConfigurationDefaults.SelectedThemeName; + /// + /// Gets or sets the selected Lua theme name. + /// public string SelectedThemeName { get => _selectedThemeName; @@ -22,15 +31,24 @@ public string SelectedThemeName } } + /// + /// Gets the resolved theme object for the current selection. + /// [XmlIgnore] public Objects.LuaTheme Theme { get; private set; } = LuaThemeRepository.GetTheme(ConfigurationDefaults.SelectedThemeName); + /// + /// Gets or sets the legacy color-scheme alias used by existing serialized configuration data. + /// public string SelectedColorSchemeName { get => SelectedThemeName; set => SelectedThemeName = value; } + /// + /// Initializes a new instance of the class. + /// public LuaEditorConfiguration() { DefaultPath = Path.Combine(DefaultPaths.TextEditorConfigsDirectory, ConfigurationDefaults.ConfigurationFileName); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs index ebd5deafe5..3074d804f8 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconKind.cs @@ -1,17 +1,67 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Defines the icon categories used by Lua completion items. +/// public enum LuaCompletionIconKind { + /// + /// A generic icon for uncategorized completion items. + /// Misc, + + /// + /// An icon for variables. + /// Variable, + + /// + /// An icon for fields. + /// Field, + + /// + /// An icon for methods or functions. + /// Method, + + /// + /// An icon for properties. + /// Property, + + /// + /// An icon for classes or types. + /// Class, + + /// + /// An icon for keywords. + /// Keyword, + + /// + /// An icon for constants. + /// Constant, + + /// + /// An icon for parameters. + /// Parameter, + + /// + /// An icon for namespaces. + /// Namespace, + + /// + /// An icon for files. + /// File, + + /// + /// An icon for folders. + /// Folder } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index ae3c2fc39b..8188897289 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -4,10 +4,25 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Represents a single completion entry returned by a Lua IntelliSense provider. +/// public sealed class LuaCompletionItem { private readonly Func>? _resolveAsync; + /// + /// Initializes a new instance of the class. + /// + /// The label shown in the completion list. + /// The text inserted when the item is committed. + /// Optional secondary detail shown in the completion list. + /// Optional description shown in the completion tooltip. + /// Optional filter text used when matching the item. + /// The sort priority for the item. + /// The icon category shown for the item. + /// Whether should be rendered as Markdown. + /// Optional callback that lazily resolves additional item data. public LuaCompletionItem( string label, string? insertText = null, @@ -30,16 +45,56 @@ public LuaCompletionItem( _resolveAsync = resolveAsync; } + /// + /// Gets the label shown in the completion list. + /// public string Label { get; } + + /// + /// Gets the text inserted when the item is committed. + /// public string InsertText { get; } + + /// + /// Gets the optional secondary detail shown alongside the label. + /// public string? Detail { get; } + + /// + /// Gets the optional completion description. + /// public string? Description { get; } + + /// + /// Gets the text used to filter or match the item. + /// public string FilterText { get; } + + /// + /// Gets the sort priority for the item. + /// public double Priority { get; } + + /// + /// Gets the icon category shown for the item. + /// public LuaCompletionIconKind IconKind { get; } + + /// + /// Gets a value indicating whether should be rendered as Markdown. + /// public bool IsDescriptionMarkdown { get; } + + /// + /// Gets a value indicating whether additional item details can be resolved lazily. + /// public bool CanResolve => _resolveAsync is not null; + /// + /// Resolves the completion item, returning either the current instance or a lazily populated copy. + /// + /// A token that can cancel the resolve request. + /// The resolved completion item. public Task ResolveAsync(CancellationToken cancellationToken = default) { return _resolveAsync is null diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs index a75175b8ad..31f8ce0277 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs @@ -2,8 +2,17 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Identifies a source location for a resolved Lua symbol definition. +/// public sealed class LuaDefinitionLocation { + /// + /// Initializes a new instance of the class. + /// + /// The file containing the definition. + /// The one-based line number. + /// The one-based column number. public LuaDefinitionLocation(string filePath, int lineNumber, int columnNumber) { FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); @@ -11,7 +20,18 @@ public LuaDefinitionLocation(string filePath, int lineNumber, int columnNumber) ColumnNumber = Math.Max(1, columnNumber); } + /// + /// Gets the file containing the definition. + /// public string FilePath { get; } + + /// + /// Gets the one-based line number of the definition. + /// public int LineNumber { get; } + + /// + /// Gets the one-based column number of the definition. + /// public int ColumnNumber { get; } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs index 81424fbb03..8f5f8057b3 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs @@ -2,14 +2,29 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Describes the content shown in a Lua hover tooltip. +/// public sealed class LuaHoverInfo { + /// + /// Initializes a new instance of the class. + /// + /// The hover content. + /// Whether the content should be rendered as Markdown. public LuaHoverInfo(string content, bool isMarkdown) { Content = content ?? throw new ArgumentNullException(nameof(content)); IsMarkdown = isMarkdown; } + /// + /// Gets the hover content. + /// public string Content { get; } + + /// + /// Gets a value indicating whether is Markdown. + /// public bool IsMarkdown { get; } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs index 727863ed70..59745c5b21 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSemanticToken.cs @@ -3,8 +3,19 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Represents a single semantic token produced by the Lua language service. +/// public sealed class LuaSemanticToken { + /// + /// Initializes a new instance of the class. + /// + /// The zero-based line index. + /// The zero-based character index within the line. + /// The token length in characters. + /// The semantic token type. + /// The semantic token modifiers. public LuaSemanticToken(int line, int character, int length, string type, IReadOnlyList modifiers) { Line = Math.Max(0, line); @@ -14,12 +25,36 @@ public LuaSemanticToken(int line, int character, int length, string type, IReadO Modifiers = modifiers ?? []; } + /// + /// Gets the zero-based line index containing the token. + /// public int Line { get; } + + /// + /// Gets the zero-based character index of the token within its line. + /// public int Character { get; } + + /// + /// Gets the token length in characters. + /// public int Length { get; } + + /// + /// Gets the semantic token type. + /// public string Type { get; } + + /// + /// Gets the semantic token modifiers. + /// public IReadOnlyList Modifiers { get; } + /// + /// Determines whether the token has the specified modifier. + /// + /// The modifier name to check. + /// if the modifier is present; otherwise, . public bool HasModifier(string modifier) { if (string.IsNullOrWhiteSpace(modifier) || Modifiers.Count == 0) diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs index 48239a7432..a2605fed7f 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs @@ -3,8 +3,18 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Describes signature-help data for a function call. +/// public sealed class LuaSignatureInfo { + /// + /// Initializes a new instance of the class. + /// + /// The full signature label to display. + /// Optional documentation for the signature. + /// The parameters available in the signature. + /// The zero-based index of the active parameter. public LuaSignatureInfo(string label, string? documentation, IReadOnlyList parameters, int activeParameter) { @@ -14,20 +24,50 @@ public LuaSignatureInfo(string label, string? documentation, IReadOnlyList + /// Gets the full label shown in signature help. + /// public string Label { get; } + + /// + /// Gets the optional documentation associated with the signature. + /// public string? Documentation { get; } + + /// + /// Gets the parameter metadata associated with the signature. + /// public IReadOnlyList Parameters { get; } + + /// + /// Gets the zero-based index of the active parameter. + /// public int ActiveParameter { get; } } +/// +/// Describes a single signature parameter. +/// public sealed class LuaParameterInfo { + /// + /// Initializes a new instance of the class. + /// + /// The parameter label. + /// Optional documentation for the parameter. public LuaParameterInfo(string label, string? documentation) { Label = label ?? string.Empty; Documentation = documentation; } + /// + /// Gets the display label for the parameter. + /// public string Label { get; } + + /// + /// Gets the optional documentation associated with the parameter. + /// public string? Documentation { get; } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs index 1cd399426a..509729250c 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaTheme.cs @@ -4,15 +4,46 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Describes a Lua editor theme, including editor colors, semantic colors, and TextMate token colors. +/// public sealed class LuaTheme { + /// + /// Gets or sets the display name of the theme. + /// public string Name { get; set; } = string.Empty; + + /// + /// Gets or sets additional names that can be used to resolve this theme. + /// public List Aliases { get; set; } = []; + + /// + /// Gets or sets the editor background color. + /// public string EditorBackground { get; set; } = LuaBuiltInThemes.DefaultEditorBackground; + + /// + /// Gets or sets the editor foreground color. + /// public string EditorForeground { get; set; } = LuaBuiltInThemes.DefaultEditorForeground; + + /// + /// Gets or sets the TextMate token theme used for syntax highlighting. + /// public TextMateTokenTheme TextMateTheme { get; set; } = new TextMateTokenTheme(); + + /// + /// Gets or sets the semantic color palette used for Lua editor features. + /// public LuaThemeSemanticColors SemanticColors { get; set; } = new LuaThemeSemanticColors(); + /// + /// Normalizes missing values so the theme can be used safely at runtime. + /// + /// The theme name to use when no explicit name was provided. + /// The current theme instance. public LuaTheme Normalize(string fallbackName) { if (string.IsNullOrWhiteSpace(Name)) @@ -33,22 +64,79 @@ public LuaTheme Normalize(string fallbackName) } } +/// +/// Defines the semantic color slots used by the Lua editor UI. +/// public sealed class LuaThemeSemanticColors { + /// + /// Gets or sets the muted text color used for secondary completion details. + /// public string MutedText { get; set; } = LuaBuiltInThemes.DefaultMutedText; + + /// + /// Gets or sets the fallback color used for uncategorized symbols. + /// public string Misc { get; set; } = LuaBuiltInThemes.DefaultMisc; + + /// + /// Gets or sets the color used for methods and functions. + /// public string Method { get; set; } = LuaBuiltInThemes.DefaultMethod; + + /// + /// Gets or sets the color used for variables and parameters. + /// public string Variable { get; set; } = LuaBuiltInThemes.DefaultVariable; + + /// + /// Gets or sets the color used for properties and fields. + /// public string Property { get; set; } = LuaBuiltInThemes.DefaultProperty; + + /// + /// Gets or sets the color used for types and namespaces. + /// public string Type { get; set; } = LuaBuiltInThemes.DefaultType; + + /// + /// Gets or sets the color used for keywords. + /// public string Keyword { get; set; } = LuaBuiltInThemes.DefaultKeyword; + + /// + /// Gets or sets the color used for language-defined constants. + /// public string LanguageConstant { get; set; } = LuaBuiltInThemes.DefaultLanguageConstant; + + /// + /// Gets or sets the color used for user-defined constants and enum members. + /// public string Constant { get; set; } = LuaBuiltInThemes.DefaultConstant; + + /// + /// Gets or sets the color used for file and folder completion items. + /// public string File { get; set; } = LuaBuiltInThemes.DefaultFile; + + /// + /// Gets or sets the color used for signature-help documentation text. + /// public string SignatureParameterDocumentation { get; set; } = LuaBuiltInThemes.DefaultSignatureParameterDocumentation; + + /// + /// Gets or sets the color used to emphasize the active signature parameter. + /// public string SignatureActiveParameter { get; set; } = LuaBuiltInThemes.DefaultSignatureActiveParameter; + + /// + /// Gets or sets the base color used for signature labels. + /// public string SignatureText { get; set; } = LuaBuiltInThemes.DefaultSignatureText; + /// + /// Replaces missing or whitespace-only color values with built-in defaults. + /// public void Normalize() { MutedText = NormalizeValue(MutedText, LuaBuiltInThemes.DefaultMutedText); diff --git a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs index 63dc6c5006..fee7f45f97 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/ConfigurationDefaults.cs @@ -1,8 +1,17 @@ namespace TombLib.Scripting.Lua.Resources; +/// +/// Defines default values used by Lua editor configuration objects. +/// public static class ConfigurationDefaults { + /// + /// Gets the default file name used to persist Lua editor configuration. + /// public const string ConfigurationFileName = "LuaConfiguration.xml"; + /// + /// Gets the default selected Lua theme name. + /// public const string SelectedThemeName = LuaBuiltInThemes.DefaultThemeName; } diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs index a52b1bf921..67ac225779 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaBuiltInThemes.cs @@ -3,6 +3,9 @@ namespace TombLib.Scripting.Lua.Resources; +/// +/// Defines the built-in Lua theme defaults used when no external theme data is available. +/// internal static class LuaBuiltInThemes { public const string DefaultThemeName = "SharpLua Classic"; @@ -25,6 +28,10 @@ internal static class LuaBuiltInThemes public const string DefaultSignatureActiveParameter = LuaBuiltInTextMateThemeDefaults.DefaultSignatureActiveParameter; public const string DefaultSignatureText = LuaBuiltInTextMateThemeDefaults.DefaultSignatureText; + /// + /// Creates the built-in fallback Lua theme. + /// + /// A fully populated default Lua theme instance. public static LuaTheme CreateDefaultTheme() { return new LuaTheme diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs index 5c00372337..1f942e2f6b 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs @@ -7,19 +7,36 @@ namespace TombLib.Scripting.Lua.Resources; +/// +/// Loads and resolves Lua editor themes from disk, falling back to the built-in default theme when needed. +/// public static class LuaThemeRepository { private static readonly Lazy Catalog = new(LoadCatalog); + /// + /// Gets all available Lua themes known to the repository. + /// + /// The ordered list of available themes. public static IReadOnlyList GetAvailableThemes() => Catalog.Value.Themes; + /// + /// Resolves a theme name or alias to the repository's canonical theme name. + /// + /// The theme name or alias to resolve. + /// The canonical theme name. public static string ResolveThemeName(string themeName) { LuaTheme theme = GetTheme(themeName); return theme.Name; } + /// + /// Gets the theme matching the supplied name or alias, or the default theme when no match exists. + /// + /// The theme name or alias to resolve. + /// The resolved theme. public static LuaTheme GetTheme(string themeName) { LuaThemeCatalog catalog = Catalog.Value; diff --git a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs index 2329eb454b..89fccc1768 100644 --- a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs +++ b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs @@ -7,33 +7,106 @@ namespace TombLib.Scripting.Lua.Services; +/// +/// Defines the language-service contract used by to provide Lua IntelliSense features. +/// public interface ILuaIntellisenseProvider : IDisposable { + /// + /// Gets a value indicating whether the provider is ready to serve IntelliSense requests. + /// bool IsAvailable { get; } + /// + /// Occurs when diagnostics for a document have changed. + /// event Action>? DiagnosticsUpdated; + /// + /// Occurs when semantic tokens for a document have changed. + /// event Action>? SemanticTokensUpdated; + /// + /// Gets the latest diagnostics known for a document. + /// + /// The path of the document. + /// The diagnostics currently cached for the document. IReadOnlyList GetDiagnostics(string filePath); + /// + /// Gets the latest semantic tokens known for a document. + /// + /// The path of the document. + /// The semantic tokens currently cached for the document. IReadOnlyList GetSemanticTokens(string filePath); + /// + /// Opens a document in the provider and starts tracking its contents. + /// + /// The document path. + /// The initial document content. void OpenDocument(string filePath, string content); + /// + /// Pushes updated content for a document that is already open in the provider. + /// + /// The document path. + /// The updated document content. void UpdateDocument(string filePath, string content); + /// + /// Closes a tracked document and releases any provider-side state associated with it. + /// + /// The document path. void CloseDocument(string filePath); + /// + /// Requests completion items for a position within a Lua document. + /// + /// The document path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// The optional character that triggered completion. + /// A token that can cancel the request. + /// The available completion items for the requested position. Task> GetCompletionItemsAsync(string filePath, string content, int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default); + /// + /// Requests hover information for a position within a Lua document. + /// + /// The document path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The hover information for the requested position, or when unavailable. Task GetHoverAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); + /// + /// Requests the definition location for a symbol at a position within a Lua document. + /// + /// The document path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The resolved definition location, or when no definition is available. Task GetDefinitionAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); + /// + /// Requests signature help for a function call at a position within a Lua document. + /// + /// The document path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The signature help information, or when unavailable. Task GetSignatureHelpAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); } diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs index 553b6f63ab..b23bd4eb7f 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -3,8 +3,19 @@ namespace TombLib.Scripting.Lua.Utils; +/// +/// Encapsulates Lua-editor interaction rules for hover, completion, and definition navigation. +/// internal static class LuaEditorInteractionRules { + /// + /// Determines whether a hover request should be attempted at the specified offset. + /// + /// The document being inspected. + /// The zero-based character offset. + /// Whether the completion window is currently open. + /// Whether signature help is currently open. + /// if hover may be requested; otherwise, . public static bool CanRequestHover(TextDocument? document, int offset, bool isCompletionWindowOpen, bool isSignatureHelpOpen) { if (isCompletionWindowOpen || isSignatureHelpOpen) @@ -13,6 +24,13 @@ public static bool CanRequestHover(TextDocument? document, int offset, bool isCo return !IsInsideCommentOrString(document, offset); } + /// + /// Attempts to resolve the exact offset that should be used for a hover request. + /// + /// The document being inspected. + /// The zero-based character offset under the mouse. + /// When this method returns, contains the resolved hover offset. + /// if a hoverable identifier exists at the requested offset; otherwise, . public static bool TryGetHoverOffset(TextDocument? document, int offset, out int hoverOffset) { hoverOffset = 0; @@ -35,6 +53,13 @@ public static bool TryGetHoverOffset(TextDocument? document, int offset, out int return true; } + /// + /// Determines whether the current caret context allows an automatic completion request. + /// + /// The document being inspected. + /// The zero-based caret offset after text entry. + /// The character that triggered completion, if any. + /// if autocomplete should be requested; otherwise, . public static bool IsValidAutocompleteContext(TextDocument? document, int offset, char? triggerCharacter) { if (offset <= 0 || document is null || document.TextLength == 0) @@ -57,6 +82,12 @@ public static bool IsValidAutocompleteContext(TextDocument? document, int offset return true; } + /// + /// Determines whether the current caret context allows a manual completion request. + /// + /// The document being inspected. + /// The zero-based caret offset. + /// if manual completion may be requested; otherwise, . public static bool IsValidManualCompletionContext(TextDocument? document, int offset) { if (document is null) @@ -68,6 +99,13 @@ public static bool IsValidManualCompletionContext(TextDocument? document, int of return !IsInsideCommentOrString(document, offset); } + /// + /// Attempts to resolve the identifier start offset that should be used for a go-to-definition request. + /// + /// The document being inspected. + /// The zero-based offset near the identifier. + /// When this method returns, contains the identifier start offset. + /// if a definition target offset was found; otherwise, . public static bool TryGetDefinitionStartOffset(TextDocument? document, int offset, out int definitionOffset) { definitionOffset = 0; @@ -86,6 +124,12 @@ public static bool TryGetDefinitionStartOffset(TextDocument? document, int offse return true; } + /// + /// Determines whether the specified offset is inside a comment or string using the current line context. + /// + /// The document being inspected. + /// The zero-based character offset. + /// if the offset is inside a comment or string on the current line; otherwise, . public static bool IsInsideCommentOrString(TextDocument? document, int offset) { if (document is null || document.TextLength == 0) diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs index 88ca0857ef..19490c8c07 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -3,6 +3,9 @@ namespace TombLib.Scripting.Lua.Utils; +/// +/// Provides lightweight line-based parsing helpers for Lua identifiers, comments, and long-bracket strings. +/// internal static class LuaLineParser { private enum ParserState @@ -14,12 +17,27 @@ private enum ParserState LongComment } + /// + /// Determines whether a character can appear within a Lua identifier. + /// + /// The character to test. + /// if the character is valid inside an identifier; otherwise, . public static bool IsIdentifierCharacter(char character) => char.IsLetterOrDigit(character) || character == '_'; + /// + /// Determines whether a character can start an identifier-triggered autocomplete request. + /// + /// The character to test. + /// if the character is a valid identifier trigger; otherwise, . public static bool IsIdentifierTriggerCharacter(char character) => char.IsLetter(character) || character == '_'; + /// + /// Determines whether the inspected line fragment currently ends inside a comment or string. + /// + /// The line text to inspect, typically truncated at the current offset. + /// if the fragment is inside a comment or string; otherwise, . public static bool IsInsideCommentOrString(string lineText) { if (string.IsNullOrEmpty(lineText)) @@ -97,6 +115,11 @@ public static bool IsInsideCommentOrString(string lineText) return state != ParserState.None; } + /// + /// Removes a trailing Lua line comment while preserving quoted strings and long-bracket strings. + /// + /// The line text to process. + /// The line text without a trailing line comment. public static string StripLineComment(string lineText) { if (string.IsNullOrEmpty(lineText)) @@ -186,6 +209,11 @@ public static string StripLineComment(string lineText) return builder.ToString(); } + /// + /// Enumerates structural characters that remain after stripping comments and string content from a line. + /// + /// The line text to inspect. + /// The structural characters that participate in brace and delimiter analysis. public static IEnumerable EnumerateStructuralCharacters(string lineText) { if (string.IsNullOrEmpty(lineText)) diff --git a/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs index bbd57e6ce3..7175f63ba6 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs @@ -4,12 +4,21 @@ namespace TombLib.Scripting.Lua.Utils; +/// +/// Inserts generated Tomb Engine language strings into an existing Lua strings table. +/// public sealed class TombEngineLanguageScriptService { private static readonly Regex SetStringsRegex = new( @"TEN\.Flow\.SetStrings\s*\(\s*(?[^)\s]+)\s*\)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + /// + /// Attempts to insert a generated language entry into the strings table referenced by TEN.Flow.SetStrings(...). + /// + /// The document to modify. + /// The generated language-table entry to insert. + /// The one-based line number of the inserted entry, or when no suitable strings table could be found. public int? TryInsertLanguageScript(TextDocument document, string languageScript) { string? stringsVariableName = TryGetStringsVariableName(document); From afb8e4364fe8fa3fd51b0470376cbbb7ede9c3b0 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 20:45:06 +0100 Subject: [PATCH 13/34] Cleanups --- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 53 +++++------- .../Resources/LuaEditorColorPalette.cs | 75 ----------------- .../Resources/LuaThemeBrushSet.cs | 84 +++++++++++++++++++ .../Utils/LuaEditorInteractionRules.cs | 28 ++++--- .../Utils/LuaLineParser.cs | 57 ++++++++++++- .../LuaEditorInteractionRulesTests.cs | 58 +++++++++++-- 6 files changed, 228 insertions(+), 127 deletions(-) create mode 100644 TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index 2e1e377b72..3f6f5470b6 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -25,36 +25,16 @@ protected override async void HandleMouseHover(MouseEventArgs e) return; bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); - bool isCompletionWindowOpen = _completionWindow is not null; + bool canShowDiagnosticFallback = _completionWindow is null && !_signaturePopup.IsOpen; - if (!LuaEditorInteractionRules.CanRequestHover(Document, hoveredOffset, isCompletionWindowOpen, _signaturePopup.IsOpen)) + if (!TryGetHoverRequestOffset(hoveredOffset, out int hoverOffset) || !IsIntellisenseAvailable()) { - if (!isCompletionWindowOpen && !_signaturePopup.IsOpen) + if (canShowDiagnosticFallback) ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); return; } - if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, hoveredOffset, out int hoverOffset)) - { - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - return; - } - - if (!IsIntellisenseAvailable()) - { - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - return; - } - - string hoveredWord = GetWordFromOffset(hoverOffset); - - if (string.IsNullOrWhiteSpace(hoveredWord)) - { - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - return; - } - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _hoverCancellationTokenSource); int hoverRequestToken = ++_hoverRequestToken; @@ -80,10 +60,25 @@ protected override async void HandleMouseHover(MouseEventArgs e) catch (Exception exception) { WriteDebugFailure("Hover request", exception); - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + + if (canShowDiagnosticFallback) + ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); } } + private bool TryGetHoverRequestOffset(int hoveredOffset, out int hoverOffset) + { + hoverOffset = 0; + + if (!LuaEditorInteractionRules.CanRequestHover(_completionWindow is not null, _signaturePopup.IsOpen)) + return false; + + if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, hoveredOffset, out hoverOffset)) + return false; + + return !string.IsNullOrWhiteSpace(GetWordFromOffset(hoverOffset)); + } + private void ShowDiagnosticToolTipIfAvailable(bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) { if (hasDiagnostic) @@ -133,13 +128,9 @@ private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, strin private void ShowHoverToolTip(LuaHoverInfo hoverInfo) => ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); - private static FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) - { - if (hoverInfo.IsMarkdown) - return MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground); - - return MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); - } + private static FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) => hoverInfo.IsMarkdown + ? MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground) + : MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) { diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs index bca391358d..d63269c3db 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs @@ -50,78 +50,3 @@ private static SolidColorBrush CreateBrush(string colorValue, string fallbackCol private static string ColorToString(Color color) => $"#{color.R:X2}{color.G:X2}{color.B:X2}"; } - -internal sealed class LuaThemeBrushSet -{ - public LuaThemeBrushSet( - string themeName, - SolidColorBrush editorBackground, - SolidColorBrush editorForeground, - SolidColorBrush mutedText, - SolidColorBrush misc, - SolidColorBrush method, - SolidColorBrush variable, - SolidColorBrush property, - SolidColorBrush type, - SolidColorBrush keyword, - SolidColorBrush languageConstant, - SolidColorBrush constant, - SolidColorBrush file, - SolidColorBrush signatureParamDoc, - SolidColorBrush signatureActiveParam, - SolidColorBrush signatureForeground) - { - ThemeName = themeName; - EditorBackground = editorBackground; - EditorForeground = editorForeground; - MutedTextBrush = mutedText; - MiscBrush = misc; - MethodBrush = method; - VariableBrush = variable; - PropertyBrush = property; - TypeBrush = type; - KeywordBrush = keyword; - LanguageConstantBrush = languageConstant; - ConstantBrush = constant; - FileBrush = file; - SignatureParamDocForeground = signatureParamDoc; - SignatureActiveParamForeground = signatureActiveParam; - SignatureForeground = signatureForeground; - } - - public string ThemeName { get; } - public SolidColorBrush EditorBackground { get; } - public SolidColorBrush EditorForeground { get; } - public SolidColorBrush MutedTextBrush { get; } - public SolidColorBrush MiscBrush { get; } - public SolidColorBrush MethodBrush { get; } - public SolidColorBrush VariableBrush { get; } - public SolidColorBrush PropertyBrush { get; } - public SolidColorBrush TypeBrush { get; } - public SolidColorBrush KeywordBrush { get; } - public SolidColorBrush LanguageConstantBrush { get; } - public SolidColorBrush ConstantBrush { get; } - public SolidColorBrush FileBrush { get; } - public SolidColorBrush SignatureParamDocForeground { get; } - public SolidColorBrush SignatureActiveParamForeground { get; } - public SolidColorBrush SignatureForeground { get; } - - public Brush GetCompletionItemBrush(LuaCompletionIconKind kind) - { - return kind switch - { - LuaCompletionIconKind.Variable => VariableBrush, - LuaCompletionIconKind.Field => PropertyBrush, - LuaCompletionIconKind.Method => MethodBrush, - LuaCompletionIconKind.Property => PropertyBrush, - LuaCompletionIconKind.Class => TypeBrush, - LuaCompletionIconKind.Keyword => KeywordBrush, - LuaCompletionIconKind.Constant => ConstantBrush, - LuaCompletionIconKind.Parameter => VariableBrush, - LuaCompletionIconKind.Namespace => TypeBrush, - LuaCompletionIconKind.File => FileBrush, - LuaCompletionIconKind.Folder => FileBrush, - _ => MiscBrush - }; - } -} diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs new file mode 100644 index 0000000000..014a6f75c9 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs @@ -0,0 +1,84 @@ +using System.Windows.Media; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.Resources; + +/// +/// Bundles the frozen WPF brushes derived from a resolved Lua theme. +/// +internal sealed class LuaThemeBrushSet +{ + public LuaThemeBrushSet( + string themeName, + SolidColorBrush editorBackground, + SolidColorBrush editorForeground, + SolidColorBrush mutedText, + SolidColorBrush misc, + SolidColorBrush method, + SolidColorBrush variable, + SolidColorBrush property, + SolidColorBrush type, + SolidColorBrush keyword, + SolidColorBrush languageConstant, + SolidColorBrush constant, + SolidColorBrush file, + SolidColorBrush signatureParamDoc, + SolidColorBrush signatureActiveParam, + SolidColorBrush signatureForeground) + { + ThemeName = themeName; + EditorBackground = editorBackground; + EditorForeground = editorForeground; + MutedTextBrush = mutedText; + MiscBrush = misc; + MethodBrush = method; + VariableBrush = variable; + PropertyBrush = property; + TypeBrush = type; + KeywordBrush = keyword; + LanguageConstantBrush = languageConstant; + ConstantBrush = constant; + FileBrush = file; + SignatureParamDocForeground = signatureParamDoc; + SignatureActiveParamForeground = signatureActiveParam; + SignatureForeground = signatureForeground; + } + + public string ThemeName { get; } + public SolidColorBrush EditorBackground { get; } + public SolidColorBrush EditorForeground { get; } + public SolidColorBrush MutedTextBrush { get; } + public SolidColorBrush MiscBrush { get; } + public SolidColorBrush MethodBrush { get; } + public SolidColorBrush VariableBrush { get; } + public SolidColorBrush PropertyBrush { get; } + public SolidColorBrush TypeBrush { get; } + public SolidColorBrush KeywordBrush { get; } + public SolidColorBrush LanguageConstantBrush { get; } + public SolidColorBrush ConstantBrush { get; } + public SolidColorBrush FileBrush { get; } + public SolidColorBrush SignatureParamDocForeground { get; } + public SolidColorBrush SignatureActiveParamForeground { get; } + public SolidColorBrush SignatureForeground { get; } + + /// + /// Gets the brush used to render the specified completion item kind. + /// + /// The completion item icon kind. + /// The brush associated with that kind. + public Brush GetCompletionItemBrush(LuaCompletionIconKind kind) => kind switch + { + LuaCompletionIconKind.Variable => VariableBrush, + LuaCompletionIconKind.Field => PropertyBrush, + LuaCompletionIconKind.Method => MethodBrush, + LuaCompletionIconKind.Property => PropertyBrush, + LuaCompletionIconKind.Class => TypeBrush, + LuaCompletionIconKind.Keyword => KeywordBrush, + LuaCompletionIconKind.Constant => ConstantBrush, + LuaCompletionIconKind.Parameter => VariableBrush, + LuaCompletionIconKind.Namespace => TypeBrush, + LuaCompletionIconKind.File => FileBrush, + LuaCompletionIconKind.Folder => FileBrush, + _ => MiscBrush + }; +} diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs index b23bd4eb7f..307127e580 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -9,20 +9,13 @@ namespace TombLib.Scripting.Lua.Utils; internal static class LuaEditorInteractionRules { /// - /// Determines whether a hover request should be attempted at the specified offset. + /// Determines whether a hover request should be attempted. /// - /// The document being inspected. - /// The zero-based character offset. /// Whether the completion window is currently open. /// Whether signature help is currently open. /// if hover may be requested; otherwise, . - public static bool CanRequestHover(TextDocument? document, int offset, bool isCompletionWindowOpen, bool isSignatureHelpOpen) - { - if (isCompletionWindowOpen || isSignatureHelpOpen) - return false; - - return !IsInsideCommentOrString(document, offset); - } + public static bool CanRequestHover(bool isCompletionWindowOpen, bool isSignatureHelpOpen) + => !isCompletionWindowOpen && !isSignatureHelpOpen; /// /// Attempts to resolve the exact offset that should be used for a hover request. @@ -125,7 +118,7 @@ public static bool TryGetDefinitionStartOffset(TextDocument? document, int offse } /// - /// Determines whether the specified offset is inside a comment or string using the current line context. + /// Determines whether the specified offset is inside a comment or string using document-aware long-block state. /// /// The document being inspected. /// The zero-based character offset. @@ -137,11 +130,22 @@ public static bool IsInsideCommentOrString(TextDocument? document, int offset) int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); DocumentLine currentLine = document.GetLineByOffset(safeOffset); + LuaLineParserState lineStartState = GetLineStartParserState(document, currentLine); int lineStart = currentLine.Offset; int inspectedLength = Math.Max(0, Math.Min(safeOffset, currentLine.EndOffset) - lineStart); string lineText = document.GetText(lineStart, inspectedLength); - return LuaLineParser.IsInsideCommentOrString(lineText); + return LuaLineParser.IsInsideCommentOrString(lineText, lineStartState, out _); + } + + private static LuaLineParserState GetLineStartParserState(TextDocument document, DocumentLine currentLine) + { + LuaLineParserState parserState = default; + + for (DocumentLine? line = document.GetLineByNumber(1); line is not null && line != currentLine; line = line.NextLine) + LuaLineParser.IsInsideCommentOrString(document.GetText(line), parserState, out parserState); + + return parserState; } private static bool TryGetDefinitionWordBounds(TextDocument document, int offset, out int wordStart, out int wordEnd) diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs index 19490c8c07..0d242026a5 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -3,6 +3,31 @@ namespace TombLib.Scripting.Lua.Utils; +/// +/// Identifies the long-block parser mode that must continue across Lua document lines. +/// +internal enum LuaLineParserStateKind +{ + None, + LongString, + LongComment +} + +/// +/// Stores the parser continuation state needed to evaluate long strings and long comments across line boundaries. +/// +internal readonly struct LuaLineParserState +{ + public LuaLineParserState(LuaLineParserStateKind kind, int longBracketEqualsCount) + { + Kind = kind; + LongBracketEqualsCount = longBracketEqualsCount; + } + + public LuaLineParserStateKind Kind { get; } + public int LongBracketEqualsCount { get; } +} + /// /// Provides lightweight line-based parsing helpers for Lua identifiers, comments, and long-bracket strings. /// @@ -39,12 +64,18 @@ public static bool IsIdentifierTriggerCharacter(char character) /// The line text to inspect, typically truncated at the current offset. /// if the fragment is inside a comment or string; otherwise, . public static bool IsInsideCommentOrString(string lineText) + => IsInsideCommentOrString(lineText, default, out _); + + internal static bool IsInsideCommentOrString(string lineText, LuaLineParserState initialState, out LuaLineParserState finalState) { - if (string.IsNullOrEmpty(lineText)) - return false; + ParserState state = GetInitialParserState(initialState); + int longBracketEqualsCount = initialState.LongBracketEqualsCount; - ParserState state = ParserState.None; - int longBracketEqualsCount = 0; + if (string.IsNullOrEmpty(lineText)) + { + finalState = CreateContinuationState(state, longBracketEqualsCount); + return state != ParserState.None; + } for (int i = 0; i < lineText.Length; i++) { @@ -97,7 +128,10 @@ public static bool IsInsideCommentOrString(string lineText) } if (IsLineCommentStart(lineText, i)) + { + finalState = default; return true; + } if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) { @@ -112,6 +146,7 @@ public static bool IsInsideCommentOrString(string lineText) state = ParserState.DoubleQuotedString; } + finalState = CreateContinuationState(state, longBracketEqualsCount); return state != ParserState.None; } @@ -349,4 +384,18 @@ private static bool TryMatchLongBracketEnd(string lineText, int index, int equal private static bool IsLineCommentStart(string lineText, int index) => lineText[index] == '-' && index + 1 < lineText.Length && lineText[index + 1] == '-'; + + private static ParserState GetInitialParserState(LuaLineParserState initialState) => initialState.Kind switch + { + LuaLineParserStateKind.LongString => ParserState.LongString, + LuaLineParserStateKind.LongComment => ParserState.LongComment, + _ => ParserState.None + }; + + private static LuaLineParserState CreateContinuationState(ParserState state, int longBracketEqualsCount) => state switch + { + ParserState.LongString => new LuaLineParserState(LuaLineParserStateKind.LongString, longBracketEqualsCount), + ParserState.LongComment => new LuaLineParserState(LuaLineParserStateKind.LongComment, longBracketEqualsCount), + _ => default + }; } diff --git a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs index 86eedbf169..b8e76880ae 100644 --- a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs +++ b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs @@ -27,6 +27,18 @@ public void IsValidAutocompleteContext_BlocksIdentifierImmediatelyAfterDot() Assert.IsFalse(result); } + [TestMethod] + public void IsValidAutocompleteContext_BlocksLongStringContinuationOnFollowingLine() + { + var document = CreateDocument( + "value = [[long string", + "player"); + + bool result = LuaEditorInteractionRules.IsValidAutocompleteContext(document, document.TextLength, null); + + Assert.IsFalse(result); + } + [TestMethod] public void IsValidManualCompletionContext_BlocksCommentText() { @@ -70,19 +82,27 @@ public void IsValidManualCompletionContext_BlocksOpenLongString() [TestMethod] public void CanRequestHover_ReturnsFalseWhenCompletionWindowIsOpen() { - var document = CreateDocument("player"); + bool result = LuaEditorInteractionRules.CanRequestHover(true, false); - bool result = LuaEditorInteractionRules.CanRequestHover(document, document.TextLength, true, false); + Assert.IsFalse(result); + } + + [TestMethod] + public void CanRequestHover_ReturnsFalseWhenSignatureHelpIsOpen() + { + bool result = LuaEditorInteractionRules.CanRequestHover(false, true); Assert.IsFalse(result); } [TestMethod] - public void CanRequestHover_BlocksCommentText() + public void IsValidManualCompletionContext_BlocksLongCommentContinuationOnFollowingLine() { - var document = CreateDocument("value = 1 -- hover target"); + var document = CreateDocument( + "--[[ comment", + "player"); - bool result = LuaEditorInteractionRules.CanRequestHover(document, document.TextLength, false, false); + bool result = LuaEditorInteractionRules.IsValidManualCompletionContext(document, document.TextLength); Assert.IsFalse(result); } @@ -115,6 +135,20 @@ public void TryGetHoverOffset_BlocksTrailingWhitespaceAfterIdentifier() Assert.IsFalse(result); } + [TestMethod] + public void TryGetHoverOffset_BlocksTextInsideLongCommentContinuation() + { + var document = CreateDocument( + "--[[ comment", + "targetValue"); + + int probeOffset = document.Text.IndexOf("targetValue", StringComparison.Ordinal) + 2; + + bool result = LuaEditorInteractionRules.TryGetHoverOffset(document, probeOffset, out _); + + Assert.IsFalse(result); + } + [TestMethod] public void TryGetDefinitionStartOffset_ReturnsWordStartFromInsideIdentifier() { @@ -155,6 +189,20 @@ public void TryGetDefinitionStartOffset_BlocksCommentText() Assert.IsFalse(result); } + [TestMethod] + public void TryGetDefinitionStartOffset_BlocksLongStringContinuationOnFollowingLine() + { + var document = CreateDocument( + "value = [[long string", + "targetValue"); + + int probeOffset = document.Text.IndexOf("targetValue", StringComparison.Ordinal) + 3; + + bool result = LuaEditorInteractionRules.TryGetDefinitionStartOffset(document, probeOffset, out _); + + Assert.IsFalse(result); + } + private static TextDocument CreateDocument(params string[] lines) => new(string.Join(Environment.NewLine, lines)); } \ No newline at end of file From 93b55cd5a10740cfdaa467a2d3ff5a2e6374c994 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 21:25:35 +0100 Subject: [PATCH 14/34] Cleanups --- .../LuaStudio.Intellisense.cs | 2 +- .../LuaLanguageServerLocator.cs | 88 ++----------------- TombIDE/TombIDE.Shared/IDEConfiguration.cs | 1 - .../TombLib.Scripting/Bases/TextEditorBase.cs | 2 - 4 files changed, 6 insertions(+), 87 deletions(-) diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 6fc63ca757..40cc31c9f9 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -41,7 +41,7 @@ private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() { TENApiService.InjectTENApi(IDE.Instance.Project, IDE.Instance.Project.GetCurrentEngineVersion()); - string executablePath = LuaLanguageServerLocator.ResolveExecutablePath(IDE.Instance.IDEConfiguration); + string executablePath = LuaLanguageServerLocator.ResolveExecutablePath(); return new LuaLanguageServerIntellisenseProvider(ScriptRootDirectoryPath, executablePath); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs index 9c693b9ffe..58c73878b8 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using TombIDE.Shared; namespace TombIDE.ScriptingStudio.Services.LuaIntellisense { @@ -10,87 +6,13 @@ internal static class LuaLanguageServerLocator { private const string ExecutableFileName = "lua-language-server.exe"; - private static readonly string[] ExtensionRoots = + public static string ResolveExecutablePath() { - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".vscode", "extensions"), - Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".vscode-insiders", "extensions") - }; + string bundledExecutablePath = Path.Combine(DefaultPaths.TIDEDirectory, "LuaLS", "bin", ExecutableFileName); - public static string ResolveExecutablePath(IDEConfiguration config) - { - if (config is not null && IsValidExecutablePath(config.LuaLanguageServerPath)) - return config.LuaLanguageServerPath; - - string executablePath = FindExecutableInPath(); - - if (executablePath is null) - executablePath = FindExecutableInExtensions(); - - if (config is not null && !string.IsNullOrWhiteSpace(executablePath) - && !string.Equals(config.LuaLanguageServerPath, executablePath, StringComparison.OrdinalIgnoreCase)) - { - config.LuaLanguageServerPath = executablePath; - config.Save(); - } - - return executablePath; - } - - private static bool IsValidExecutablePath(string executablePath) - => !string.IsNullOrWhiteSpace(executablePath) - && File.Exists(executablePath) - && Path.GetFileName(executablePath).Equals(ExecutableFileName, StringComparison.OrdinalIgnoreCase); - - private static string FindExecutableInPath() - { - string pathVariable = Environment.GetEnvironmentVariable("PATH"); - - if (string.IsNullOrWhiteSpace(pathVariable)) - return null; - - foreach (string pathPart in pathVariable.Split(Path.PathSeparator).Where(part => !string.IsNullOrWhiteSpace(part))) - { - try - { - string candidatePath = Path.Combine(pathPart.Trim(), ExecutableFileName); - - if (IsValidExecutablePath(candidatePath)) - return candidatePath; - } - catch - { - // Ignore invalid PATH entries. - } - } - - return null; - } - - private static string FindExecutableInExtensions() - { - var candidates = new List(); - - foreach (string extensionRoot in ExtensionRoots) - { - if (!Directory.Exists(extensionRoot)) - continue; - - foreach (string extensionDirectory in Directory.EnumerateDirectories(extensionRoot) - .Where(path => Path.GetFileName(path).Contains("lua", StringComparison.OrdinalIgnoreCase)) - .OrderByDescending(path => Path.GetFileName(path), StringComparer.OrdinalIgnoreCase)) - { - try - { - candidates.AddRange(Directory.EnumerateFiles(extensionDirectory, ExecutableFileName, SearchOption.AllDirectories)); - } - catch - { - // Ignore directories we cannot access. - } - } - } - - return candidates.FirstOrDefault(IsValidExecutablePath); + return !string.IsNullOrWhiteSpace(bundledExecutablePath) && File.Exists(bundledExecutablePath) + ? bundledExecutablePath + : null; } } } \ No newline at end of file diff --git a/TombIDE/TombIDE.Shared/IDEConfiguration.cs b/TombIDE/TombIDE.Shared/IDEConfiguration.cs index d82c0a616f..a2c51993f1 100644 --- a/TombIDE/TombIDE.Shared/IDEConfiguration.cs +++ b/TombIDE/TombIDE.Shared/IDEConfiguration.cs @@ -48,7 +48,6 @@ public class IDEConfiguration public DockPanelState Lua_DockPanelState { get; set; } = DefaultLayouts.LuaLayout; public string VSCodePath { get; set; } = string.Empty; - public string LuaLanguageServerPath { get; set; } = string.Empty; public bool DoNotAskToInstallLuaExtension { get; set; } public static string DefaultPath => Path.Combine(DefaultPaths.ConfigsDirectory, "TombIDEConfiguration.xml"); diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 1684ee67b4..28ab903ced 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -29,8 +29,6 @@ namespace TombLib.Scripting.Bases { public abstract class TextEditorBase : TextEditor, IEditorControl, ISupportsFindReplace { - private const double ToolTipMaxHeight = 420.0; - private const double ToolTipMaxWidth = 540.0; protected const double ToolTipTextMaxWidth = 500.0; protected static readonly double ToolTipTextFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); protected static readonly SolidColorBrush DefaultToolTipBorder = TextEditorColorPalette.ToolTipBorder; From 1184a01d27f06de4743c66bb6a05b7fb160d3a5d Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 21:33:31 +0100 Subject: [PATCH 15/34] Address Copilot comments --- TombLib/TombLib.Scripting/Bases/TextEditorBase.cs | 2 ++ TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs | 8 ++++---- TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 28ab903ced..2cedebca9b 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -646,6 +646,8 @@ public void CommentOutLines() if (!string.IsNullOrWhiteSpace(currentLineText)) builder.AppendLine(whitespaceBuilder.ToString() + CommentPrefix + currentLineText.TrimStart()); + else + builder.AppendLine(whitespaceBuilder.ToString()); totalLineLength += currentLine.TotalLength; } diff --git a/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs b/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs index a910b3764e..56d239664d 100644 --- a/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/BookmarkRenderer.cs @@ -3,11 +3,14 @@ using System.Windows; using System.Windows.Media; using TombLib.Scripting.Bases; +using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Rendering { public sealed class BookmarkRenderer : IBackgroundRenderer { + private static readonly Brush BackgroundBrush = CreateFrozenBrush(Color.FromArgb(40, 128, 128, 255)); + private TextEditorBase _editor; #region Construction @@ -23,15 +26,12 @@ public BookmarkRenderer(TextEditorBase e) public void Draw(TextView textView, DrawingContext drawingContext) { - var background = new SolidColorBrush(Color.FromArgb(40, 128, 128, 255)); - var border = new Pen(Brushes.Transparent, 0); - foreach (DocumentLine line in _editor.GetBookmarkedLines()) { var segment = new TextSegment { StartOffset = line.Offset, EndOffset = line.EndOffset }; foreach (Rect rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment, true)) - drawingContext.DrawRectangle(background, border, new Rect(rect.Location, new Size(textView.ActualWidth, rect.Height))); + drawingContext.DrawRectangle(BackgroundBrush, null, new Rect(rect.Location, new Size(textView.ActualWidth, rect.Height))); } } diff --git a/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs b/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs index b98b34cd12..c16c9a581d 100644 --- a/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/ErrorRenderer.cs @@ -15,6 +15,7 @@ public sealed class ErrorRenderer : IBackgroundRenderer private static readonly Brush WarningBrush = CreateFrozenBrush(Color.FromArgb(224, 226, 165, 44)); private static readonly Brush InformationBrush = CreateFrozenBrush(Color.FromArgb(224, 88, 170, 255)); private static readonly Brush HintBrush = CreateFrozenBrush(Color.FromArgb(192, 166, 166, 166)); + private static readonly Pen ErrorPen = CreateFrozenPen(ErrorBrush, 1.4); private static readonly Pen WarningPen = CreatePen(WarningBrush, new double[] { 1.0, 2.0 }); private static readonly Pen InformationPen = CreatePen(InformationBrush, new double[] { 2.0, 2.0 }); private static readonly Pen HintPen = CreatePen(HintBrush, new double[] { 1.0, 3.0 }); @@ -117,7 +118,7 @@ private static void DrawErrorUnderline(DrawingContext drawingContext, Rect rect) } geometry.Freeze(); - drawingContext.DrawGeometry(null, new Pen(ErrorBrush, 1.4), geometry); + drawingContext.DrawGeometry(null, ErrorPen, geometry); } private static void DrawStraightUnderline(DrawingContext drawingContext, Rect rect, Pen pen) From e13e1bbcbfcdcf4ab3657ca65fd069e660d5f322 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 12 Apr 2026 21:53:10 +0100 Subject: [PATCH 16/34] Apply Copilot suggestions --- .../LuaLanguageServerClient.cs | 87 +++++++++++++++---- TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 2 +- .../Utils/LuaDocumentLineParserStateCache.cs | 77 ++++++++++++++++ .../Utils/LuaEditorInteractionRules.cs | 14 ++- .../LuaEditorInteractionRulesTests.cs | 24 +++++ 5 files changed, 179 insertions(+), 25 deletions(-) create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index 80c7231e09..76209f7dae 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -12,6 +12,9 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense { internal sealed class LuaLanguageServerClient : IDisposable { + private const int ReceiveChunkSize = 4096; + private static readonly byte[] HeaderTerminator = { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; + private readonly string _workspaceRootDirectoryPath; private readonly string _serverExecutablePath; private readonly Func _settingsProvider; @@ -38,6 +41,8 @@ internal sealed class LuaLanguageServerClient : IDisposable private Process _process; private Stream _inputStream; private Stream _outputStream; + private byte[] _receiveBuffer = Array.Empty(); + private int _receiveBufferCount; private Task _readLoopTask; private Task _stderrLoopTask; private string[] _semanticTokenTypes = Array.Empty(); @@ -323,27 +328,27 @@ private async Task ReadStandardErrorLoopAsync() private async Task> ReadHeadersAsync() { - var buffer = new List(); - var singleByte = new byte[1]; - while (true) { - int bytesRead = await _inputStream.ReadAsync(singleByte.AsMemory(0, 1)).ConfigureAwait(false); - - if (bytesRead == 0) - return null; + int headerTerminatorIndex = FindHeaderTerminatorIndex(); - buffer.Add(singleByte[0]); + if (headerTerminatorIndex >= 0) + return ConsumeHeaders(headerTerminatorIndex); - if (buffer.Count >= 4 - && buffer[^4] == '\r' - && buffer[^3] == '\n' - && buffer[^2] == '\r' - && buffer[^1] == '\n') - break; + if (!await ReadIntoReceiveBufferAsync().ConfigureAwait(false)) + return null; } + } - string headerText = Encoding.ASCII.GetString(buffer.ToArray()); + private Dictionary ConsumeHeaders(int headerTerminatorIndex) + { + string headerText = Encoding.ASCII.GetString(_receiveBuffer, 0, headerTerminatorIndex); + ConsumeReceiveBuffer(headerTerminatorIndex + HeaderTerminator.Length); + return ParseHeaders(headerText); + } + + private static Dictionary ParseHeaders(string headerText) + { var headers = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (string line in headerText.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) @@ -362,11 +367,61 @@ private async Task> ReadHeadersAsync() return headers; } + private int FindHeaderTerminatorIndex() + => new ReadOnlySpan(_receiveBuffer, 0, _receiveBufferCount).IndexOf(HeaderTerminator); + + private async Task ReadIntoReceiveBufferAsync() + { + EnsureReceiveBufferCapacity(_receiveBufferCount + ReceiveChunkSize); + + int bytesToRead = Math.Min(ReceiveChunkSize, _receiveBuffer.Length - _receiveBufferCount); + int bytesRead = await _inputStream + .ReadAsync(_receiveBuffer.AsMemory(_receiveBufferCount, bytesToRead)) + .ConfigureAwait(false); + + if (bytesRead == 0) + return false; + + _receiveBufferCount += bytesRead; + return true; + } + + private void EnsureReceiveBufferCapacity(int requiredCapacity) + { + if (_receiveBuffer.Length >= requiredCapacity) + return; + + int newCapacity = Math.Max(ReceiveChunkSize, _receiveBuffer.Length); + + while (newCapacity < requiredCapacity) + newCapacity *= 2; + + Array.Resize(ref _receiveBuffer, newCapacity); + } + + private void ConsumeReceiveBuffer(int bytesToConsume) + { + int remainingBytes = _receiveBufferCount - bytesToConsume; + + if (remainingBytes > 0) + Buffer.BlockCopy(_receiveBuffer, bytesToConsume, _receiveBuffer, 0, remainingBytes); + + _receiveBufferCount = Math.Max(0, remainingBytes); + } + private async Task ReadPayloadAsync(int contentLength) { byte[] payloadBytes = new byte[contentLength]; int totalBytesRead = 0; + if (_receiveBufferCount > 0) + { + int bufferedBytesToCopy = Math.Min(contentLength, _receiveBufferCount); + Buffer.BlockCopy(_receiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); + ConsumeReceiveBuffer(bufferedBytesToCopy); + totalBytesRead = bufferedBytesToCopy; + } + while (totalBytesRead < contentLength) { int bytesRead = await _inputStream @@ -634,6 +689,8 @@ private void ResetProcessState() _inputStream = null; _outputStream = null; _process = null; + _receiveBuffer = Array.Empty(); + _receiveBufferCount = 0; _readLoopTask = null; _stderrLoopTask = null; _supportsCompletionResolve = false; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index 4e7e01ffa8..a147bf47fb 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -62,7 +62,7 @@ public override void UpdateSettings(Bases.ConfigurationBase configuration) Foreground = _themeBrushSet.EditorForeground; base.UpdateSettings(configuration); - LiveErrorUnderlining = true; + LiveErrorUnderlining = true; // TEMP - Add as a setting later } private LuaThemeBrushSet GetThemeBrushSet() diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs new file mode 100644 index 0000000000..9b596ad089 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using ICSharpCode.AvalonEdit.Document; + +namespace TombLib.Scripting.Lua.Utils; + +internal sealed class LuaDocumentLineParserStateCache +{ + private readonly object _syncRoot = new(); + private readonly TextDocument _document; + private readonly List _cachedLineStartStates = new(); + + public LuaDocumentLineParserStateCache(TextDocument document) + { + _document = document ?? throw new ArgumentNullException(nameof(document)); + _document.Changed += Document_Changed; + } + + public LuaLineParserState GetLineStartState(int lineNumber) + { + if (lineNumber <= 1) + return default; + + lock (_syncRoot) + { + EnsureFirstLineStateCached(); + EnsureStatesCachedThrough(lineNumber); + return _cachedLineStartStates[lineNumber - 1]; + } + } + + private void Document_Changed(object? sender, DocumentChangeEventArgs e) + { + lock (_syncRoot) + { + if (_cachedLineStartStates.Count == 0) + return; + + int firstAffectedLineNumber = GetSafeLineNumberForOffset(e.Offset); + int preservedLineCount = Math.Max(0, firstAffectedLineNumber - 1); + + if (_cachedLineStartStates.Count > preservedLineCount) + _cachedLineStartStates.RemoveRange(preservedLineCount, _cachedLineStartStates.Count - preservedLineCount); + + if (_cachedLineStartStates.Count > _document.LineCount) + _cachedLineStartStates.RemoveRange(_document.LineCount, _cachedLineStartStates.Count - _document.LineCount); + } + } + + private void EnsureFirstLineStateCached() + { + if (_document.LineCount > 0 && _cachedLineStartStates.Count == 0) + _cachedLineStartStates.Add(default); + } + + private void EnsureStatesCachedThrough(int lineNumber) + { + int targetLineNumber = Math.Max(1, Math.Min(lineNumber, _document.LineCount)); + + while (_cachedLineStartStates.Count < targetLineNumber) + { + int previousLineNumber = _cachedLineStartStates.Count; + DocumentLine previousLine = _document.GetLineByNumber(previousLineNumber); + LuaLineParser.IsInsideCommentOrString(_document.GetText(previousLine), _cachedLineStartStates[previousLineNumber - 1], out LuaLineParserState nextState); + _cachedLineStartStates.Add(nextState); + } + } + + private int GetSafeLineNumberForOffset(int offset) + { + if (_document.LineCount == 0) + return 1; + + int safeOffset = Math.Max(0, Math.Min(offset, _document.TextLength)); + return _document.GetLineByOffset(safeOffset).LineNumber; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs index 307127e580..30862abe9f 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -1,5 +1,6 @@ -using ICSharpCode.AvalonEdit.Document; using System; +using System.Runtime.CompilerServices; +using ICSharpCode.AvalonEdit.Document; namespace TombLib.Scripting.Lua.Utils; @@ -8,6 +9,8 @@ namespace TombLib.Scripting.Lua.Utils; /// internal static class LuaEditorInteractionRules { + private static readonly ConditionalWeakTable LineStartStateCaches = []; + /// /// Determines whether a hover request should be attempted. /// @@ -139,14 +142,7 @@ public static bool IsInsideCommentOrString(TextDocument? document, int offset) } private static LuaLineParserState GetLineStartParserState(TextDocument document, DocumentLine currentLine) - { - LuaLineParserState parserState = default; - - for (DocumentLine? line = document.GetLineByNumber(1); line is not null && line != currentLine; line = line.NextLine) - LuaLineParser.IsInsideCommentOrString(document.GetText(line), parserState, out parserState); - - return parserState; - } + => LineStartStateCaches.GetValue(document, static doc => new LuaDocumentLineParserStateCache(doc)).GetLineStartState(currentLine.LineNumber); private static bool TryGetDefinitionWordBounds(TextDocument document, int offset, out int wordStart, out int wordEnd) { diff --git a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs index b8e76880ae..25b92b5508 100644 --- a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs +++ b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs @@ -149,6 +149,30 @@ public void TryGetHoverOffset_BlocksTextInsideLongCommentContinuation() Assert.IsFalse(result); } + [TestMethod] + public void TryGetHoverOffset_RefreshesLongCommentStateAfterDocumentEdit() + { + var document = CreateDocument( + "--[[ comment", + "targetValue"); + + int initialProbeOffset = document.Text.IndexOf("targetValue", StringComparison.Ordinal) + 2; + + bool initialResult = LuaEditorInteractionRules.TryGetHoverOffset(document, initialProbeOffset, out _); + + document.Text = string.Join(Environment.NewLine, + "--[[ comment ]]", + "targetValue"); + + int updatedProbeOffset = document.Text.IndexOf("targetValue", StringComparison.Ordinal) + 2; + + bool updatedResult = LuaEditorInteractionRules.TryGetHoverOffset(document, updatedProbeOffset, out int hoverOffset); + + Assert.IsFalse(initialResult); + Assert.IsTrue(updatedResult); + Assert.AreEqual(updatedProbeOffset, hoverOffset); + } + [TestMethod] public void TryGetDefinitionStartOffset_ReturnsWordStartFromInsideIdentifier() { From 06097ec179a7ebb5f05d783448aeb1efff6c989d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 21:19:38 +0000 Subject: [PATCH 17/34] Address review findings: improve null safety, clarify logic, add error logging, use named constants Agent-Logs-Url: https://github.com/TombEngine/Tomb-Editor/sessions/9974ccc7-84ce-4ed5-8fb6-8d79a73211aa Co-authored-by: Nickelony <20436882+Nickelony@users.noreply.github.com> --- .../LuaLanguageServerPathHelper.cs | 4 ++-- .../LuaLanguageServerResponseParser.cs | 22 +++++++++++-------- .../Objects/LuaCompletionData.cs | 2 +- .../Resources/LuaThemeRepository.cs | 6 +++-- TombLib/TombLib.WPF/BrushHelpers.cs | 11 +++++++++- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs index dc9ad4292e..c46991b421 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs @@ -25,6 +25,7 @@ public static string NormalizeLocalPath(Uri uri) string localPath = uri.LocalPath; + // On Windows, Uri.LocalPath may produce "/C:/..." which needs the leading slash trimmed. if (Path.DirectorySeparatorChar == '\\' && localPath.Length >= 3 && localPath[0] == '/' @@ -34,8 +35,7 @@ public static string NormalizeLocalPath(Uri uri) localPath = localPath[1..]; } - localPath = localPath.Replace('/', Path.DirectorySeparatorChar); - return Path.GetFullPath(localPath); + return NormalizeLocalPath(localPath); } public static bool TryNormalizeLocalPath(string filePath, out string normalizedFilePath) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs index 05b1e2b00f..2d66ba3fc6 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -145,14 +145,18 @@ public static LuaCompletionItem ParseCompletionItem(JsonElement itemElement, int private static double BuildCompletionPriority(JsonElement itemElement, string detail, string description, int itemIndex) { + const double preselectedBonus = 1000000.0; + const double localScopeBonus = 20000.0; + const double upvalueOrParameterBonus = 15000.0; const double responseOrderWeight = 100000.0; + double priority = responseOrderWeight - itemIndex; string searchableText = CombineCompletionText(detail, description); if (itemElement.TryGetProperty("preselect", out JsonElement preselectElement) && preselectElement.ValueKind == JsonValueKind.True) { - priority += 1000000.0; + priority += preselectedBonus; } if (itemElement.TryGetProperty("kind", out JsonElement kindElement) @@ -160,12 +164,12 @@ private static double BuildCompletionPriority(JsonElement itemElement, string de { priority += completionKind switch { - 6 => 10000.0, - 5 => 9000.0, - 10 => 9000.0, - 2 => 7000.0, - 3 => 7000.0, - 14 => -5000.0, + (int)LuaLanguageServerCompletionKind.Variable => 10000.0, + (int)LuaLanguageServerCompletionKind.Field => 9000.0, + (int)LuaLanguageServerCompletionKind.Property => 9000.0, + (int)LuaLanguageServerCompletionKind.Method => 7000.0, + (int)LuaLanguageServerCompletionKind.Function => 7000.0, + (int)LuaLanguageServerCompletionKind.Keyword => -5000.0, _ => 0.0 }; } @@ -173,12 +177,12 @@ private static double BuildCompletionPriority(JsonElement itemElement, string de if (!string.IsNullOrWhiteSpace(searchableText)) { if (CompletionTextContains(searchableText, "local")) - priority += 20000.0; + priority += localScopeBonus; if (CompletionTextContains(searchableText, "upvalue") || CompletionTextContains(searchableText, "parameter")) { - priority += 15000.0; + priority += upvalueOrParameterBonus; } } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index fb427e5f92..463fef1b7e 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -66,7 +66,7 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in if (!CanResolve) return Description; - if (_resolveTask?.IsCanceled != false || _resolveTask.IsFaulted) + if (_resolveTask is null || _resolveTask.IsCanceled || _resolveTask.IsFaulted) _resolveTask = _item.ResolveAsync(cancellationToken); resolveTask = _resolveTask; diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs index 1f942e2f6b..192b5938b3 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs @@ -75,8 +75,10 @@ private static LuaThemeCatalog LoadCatalog() if (theme is not null) themes.Add(theme.Normalize(Path.GetFileNameWithoutExtension(filePath))); } - catch - { } + catch (Exception ex) + { + System.Diagnostics.Debug.WriteLine($"Failed to load Lua theme '{filePath}': {ex.Message}"); + } } } diff --git a/TombLib/TombLib.WPF/BrushHelpers.cs b/TombLib/TombLib.WPF/BrushHelpers.cs index bbb11d0c90..71c5d314c5 100644 --- a/TombLib/TombLib.WPF/BrushHelpers.cs +++ b/TombLib/TombLib.WPF/BrushHelpers.cs @@ -1,3 +1,4 @@ +using System; using System.Windows.Media; namespace TombLib.WPF; @@ -13,7 +14,15 @@ public static SolidColorBrush CreateFrozenBrush(Color color) public static SolidColorBrush CreateFrozenBrush(string colorValue) { - var brush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(colorValue)); + if (string.IsNullOrWhiteSpace(colorValue)) + throw new ArgumentException("Color value must not be empty.", nameof(colorValue)); + + object converted = ColorConverter.ConvertFromString(colorValue); + + if (converted is not Color color) + throw new ArgumentException($"'{colorValue}' is not a valid color.", nameof(colorValue)); + + var brush = new SolidColorBrush(color); brush.Freeze(); return brush; } From 4f58ed958555d45755ec3a01e20869c08de98ba1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 12 Apr 2026 21:20:39 +0000 Subject: [PATCH 18/34] Name remaining completion priority constants Agent-Logs-Url: https://github.com/TombEngine/Tomb-Editor/sessions/9974ccc7-84ce-4ed5-8fb6-8d79a73211aa Co-authored-by: Nickelony <20436882+Nickelony@users.noreply.github.com> --- .../LuaLanguageServerResponseParser.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs index 2d66ba3fc6..817b3c3cbc 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -146,9 +146,13 @@ public static LuaCompletionItem ParseCompletionItem(JsonElement itemElement, int private static double BuildCompletionPriority(JsonElement itemElement, string detail, string description, int itemIndex) { const double preselectedBonus = 1000000.0; + const double responseOrderWeight = 100000.0; const double localScopeBonus = 20000.0; const double upvalueOrParameterBonus = 15000.0; - const double responseOrderWeight = 100000.0; + const double variableKindBonus = 10000.0; + const double fieldOrPropertyKindBonus = 9000.0; + const double methodOrFunctionKindBonus = 7000.0; + const double keywordKindPenalty = -5000.0; double priority = responseOrderWeight - itemIndex; string searchableText = CombineCompletionText(detail, description); @@ -164,12 +168,12 @@ private static double BuildCompletionPriority(JsonElement itemElement, string de { priority += completionKind switch { - (int)LuaLanguageServerCompletionKind.Variable => 10000.0, - (int)LuaLanguageServerCompletionKind.Field => 9000.0, - (int)LuaLanguageServerCompletionKind.Property => 9000.0, - (int)LuaLanguageServerCompletionKind.Method => 7000.0, - (int)LuaLanguageServerCompletionKind.Function => 7000.0, - (int)LuaLanguageServerCompletionKind.Keyword => -5000.0, + (int)LuaLanguageServerCompletionKind.Variable => variableKindBonus, + (int)LuaLanguageServerCompletionKind.Field => fieldOrPropertyKindBonus, + (int)LuaLanguageServerCompletionKind.Property => fieldOrPropertyKindBonus, + (int)LuaLanguageServerCompletionKind.Method => methodOrFunctionKindBonus, + (int)LuaLanguageServerCompletionKind.Function => methodOrFunctionKindBonus, + (int)LuaLanguageServerCompletionKind.Keyword => keywordKindPenalty, _ => 0.0 }; } From c35de24105c0225471a3cc0bc345de10caa5c7fa Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Tue, 21 Apr 2026 21:40:30 +0100 Subject: [PATCH 19/34] Ship the Lua Language Server + Update all .csproj files (#1190) --- .gitignore | 2 + DarkUI/DarkUI.WPF.Demo/DarkUI.WPF.Demo.csproj | 14 - DarkUI/DarkUI.WPF/DarkUI.WPF.csproj | 18 - DarkUI/DarkUI/DarkUI.csproj | 19 - DarkUI/DarkUI/Properties/AssemblyInfo.cs | 2 + DarkUI/Example/Example.csproj | 14 - DarkUI/Example/Properties/AssemblyInfo.cs | 2 + Directory.Build.props | 38 ++ FileAssociation/FileAssociation.csproj | 18 - Installer/Installer_compile_instructions.txt | 4 +- ...pt_NET6_x64.nsi => install_script_x64.nsi} | 11 +- LuaApiBuilder/LuaApiBuilder.csproj | 22 -- NgXmlBuilder/NgXmlBuilder.csproj | 17 - SoundTool/SoundTool.csproj | 18 - TombEditor.Tests/TombEditor.Tests.csproj | 14 - TombEditor/TombEditor.csproj | 19 - .../TombIDE.ProjectMaster.csproj | 20 -- TombIDE/TombIDE.REGSVR/TombIDE.REGSVR.csproj | 17 - .../TombIDE.ScriptingStudio.csproj | 19 - TombIDE/TombIDE.Shared/TIDE/LuaLS.zip | Bin 0 -> 4338564 bytes TombIDE/TombIDE.Shared/TombIDE.Shared.csproj | 331 ++++++------------ TombIDE/TombIDE/TombIDE.csproj | 18 - TombLib/TombLib.Forms/TombLib.Forms.csproj | 20 -- .../TombLib.Rendering.csproj | 19 - .../TombLib.Scripting.ClassicScript.csproj | 19 - .../TombLib.Scripting.GameFlowScript.csproj | 19 - .../TombLib.Scripting.Lua.csproj | 20 -- .../TombLib.Scripting.Tomb1Main.csproj | 19 - .../TombLib.Scripting.csproj | 19 - TombLib/TombLib.Test/TombLib.Test.csproj | 14 - TombLib/TombLib.WPF/TombLib.WPF.csproj | 13 - TombLib/TombLib/TombLib.csproj | 19 - WadTool/WadTool.csproj | 18 - 33 files changed, 155 insertions(+), 681 deletions(-) create mode 100644 Directory.Build.props rename Installer/{install_script_NET6_x64.nsi => install_script_x64.nsi} (99%) create mode 100644 TombIDE/TombIDE.Shared/TIDE/LuaLS.zip diff --git a/.gitignore b/.gitignore index c1f4f5edfb..a48e09794c 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ packages/ .idea/ build_output.txt + +/TombIDE/TombIDE.Shared/TIDE/LuaLS/ diff --git a/DarkUI/DarkUI.WPF.Demo/DarkUI.WPF.Demo.csproj b/DarkUI/DarkUI.WPF.Demo/DarkUI.WPF.Demo.csproj index 573cdd5283..cef484f9f4 100644 --- a/DarkUI/DarkUI.WPF.Demo/DarkUI.WPF.Demo.csproj +++ b/DarkUI/DarkUI.WPF.Demo/DarkUI.WPF.Demo.csproj @@ -2,23 +2,9 @@ WinExe - net6.0-windows enable true True - Debug;Release - x64;x86 - - - - none - true - - - x64 - - - x86 diff --git a/DarkUI/DarkUI.WPF/DarkUI.WPF.csproj b/DarkUI/DarkUI.WPF/DarkUI.WPF.csproj index 054b6f2730..86b2e21b3b 100644 --- a/DarkUI/DarkUI.WPF/DarkUI.WPF.csproj +++ b/DarkUI/DarkUI.WPF/DarkUI.WPF.csproj @@ -1,26 +1,8 @@  - net6.0-windows enable true - Debug;Release - x64;x86 - - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/DarkUI/DarkUI/DarkUI.csproj b/DarkUI/DarkUI/DarkUI.csproj index 114d677da1..9d4cc7468a 100644 --- a/DarkUI/DarkUI/DarkUI.csproj +++ b/DarkUI/DarkUI/DarkUI.csproj @@ -1,26 +1,7 @@  - net6.0-windows - Library false true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/DarkUI/DarkUI/Properties/AssemblyInfo.cs b/DarkUI/DarkUI/Properties/AssemblyInfo.cs index 7c7a1b5e65..30e9112df7 100644 --- a/DarkUI/DarkUI/Properties/AssemblyInfo.cs +++ b/DarkUI/DarkUI/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Versioning; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information @@ -12,6 +13,7 @@ [assembly: AssemblyCopyright("Copyright © Robin Perris")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] +[assembly: SupportedOSPlatform("windows")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/DarkUI/Example/Example.csproj b/DarkUI/Example/Example.csproj index 6896affaba..d3231afa10 100644 --- a/DarkUI/Example/Example.csproj +++ b/DarkUI/Example/Example.csproj @@ -1,22 +1,8 @@  - net6.0-windows WinExe false true - true - Debug;Release - x64;x86 - - - none - true - - - x64 - - - x86 diff --git a/DarkUI/Example/Properties/AssemblyInfo.cs b/DarkUI/Example/Properties/AssemblyInfo.cs index e7033330fb..21c2a82454 100644 --- a/DarkUI/Example/Properties/AssemblyInfo.cs +++ b/DarkUI/Example/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Versioning; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information @@ -12,6 +13,7 @@ [assembly: AssemblyCopyright("Copyright © Robin Perris")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] +[assembly: SupportedOSPlatform("windows")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000000..d09e563946 --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,38 @@ + + + net8.0-windows + 12 + Debug;Release + x64;x86 + x64 + $(Platform.Replace(' ', '')) + x64 + true + Build + BuildRelease + BuildNgXmlBuilder + BuildNgXmlBuilderRelease + + + + $(MSBuildThisFileDirectory)$(SharedDebugOutputRoot) ($(NormalizedPlatform))\ + + + $(MSBuildThisFileDirectory)$(SharedReleaseOutputRoot) ($(NormalizedPlatform))\ + + + + none + true + + + x64 + + + x86 + + diff --git a/FileAssociation/FileAssociation.csproj b/FileAssociation/FileAssociation.csproj index d11c102854..efd217a151 100644 --- a/FileAssociation/FileAssociation.csproj +++ b/FileAssociation/FileAssociation.csproj @@ -1,27 +1,9 @@  - net6.0-windows WinExe File Association false true - true - Debug;Release - x64;x86 - - - ..\Build ($(Platform))\ - - - ..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 app.manifest diff --git a/Installer/Installer_compile_instructions.txt b/Installer/Installer_compile_instructions.txt index fe3f8bd3fa..99aa16e4b5 100644 --- a/Installer/Installer_compile_instructions.txt +++ b/Installer/Installer_compile_instructions.txt @@ -2,14 +2,14 @@ HOW TO MAKE INSTALLER: 1. Compile Release build into empty BuildRelease folder (with no stray logs, autosave prj2 etc.) 2. Download NSIS from here: https://sourceforge.net/projects/nsis/ -3. Run NSIS and execute install_script.nsi in-place from Installer folder. It will generate TombEditorInstall.exe installer inside BuildRelease folder. +3. Run NSIS and execute install_script_x64.nsi in-place from Installer folder. It will generate TombEditorInstall.exe installer inside BuildRelease folder. 4. You are ready to deploy your installer! IN CASE NEW COMPONENTS ARE ADDED AND FILE LIST IN BuildRelease FOLDER IS CHANGED: 1. Download uninstalled files list generator here: https://nsis.sourceforge.io/mediawiki/images/9/9f/Unlist.zip 2. Run it onto clean BuildRelease folder, it will generate new file list block ready to be placed into NSIS script -3. Overwrite autogenerated file list block in install_script.nsi "Uninstall" section (there's comments for that) with new one +3. Overwrite autogenerated file list block in install_script_x64.nsi "Uninstall" section (there's comments for that) with new one 4. You are ready to go again! HOW TO PUBLISH RELEASE USING RELEASES REPO: diff --git a/Installer/install_script_NET6_x64.nsi b/Installer/install_script_x64.nsi similarity index 99% rename from Installer/install_script_NET6_x64.nsi rename to Installer/install_script_x64.nsi index 9081fa5b9f..641616744f 100644 --- a/Installer/install_script_NET6_x64.nsi +++ b/Installer/install_script_x64.nsi @@ -3,7 +3,7 @@ !include WinVer.nsh !include x64.nsh -!cd "..\BuildRelease (x64)\net6.0-windows" +!cd "..\BuildRelease (x64)\net8.0-windows" !define MUI_COMPONENTSPAGE_SMALLDESC !define MUI_ABORTWARNING @@ -13,16 +13,13 @@ !define MUI_ICON "..\..\Icons\ICO\TE.ico" !define MUI_FINISHPAGE_SHOWREADME "Changes.txt" -!define DOT_MAJOR "6" -!define DOT_MINOR "0" - !define MUI_WELCOMEPAGE_TEXT \ "You are ready to install Tomb Editor ${Version_1}.${Version_2}.${Version_3}. $\r$\n\ $\r$\n\ Please make sure your system complies with following system requirements: $\r$\n\ $\r$\n\ - ${U+2022} Windows 7 or later (64-bit) $\r$\n\ - ${U+2022} Installed .NET 6 or later (64-bit)$\r$\n\ + ${U+2022} Windows 10 or later (64-bit) $\r$\n\ + ${U+2022} Installed .NET 8 Desktop Runtime or later (64-bit)$\r$\n\ ${U+2022} Videocard with DirectX 10 support $\r$\n\ ${U+2022} At least 2 gigabytes of RAM $\r$\n\ $\r$\n\ @@ -75,7 +72,7 @@ Section "Tomb Editor" Section1 /x "*.pdb" \ /x "*.so" \ /x "*.vshost.*" \ - /x "install_script.nsi" \ + /x "install_script_x64.nsi" \ /x "TombEditorInstall.exe" \ /x "TombEditorConfiguration.xml" \ /x "SoundToolConfiguration.xml" \ diff --git a/LuaApiBuilder/LuaApiBuilder.csproj b/LuaApiBuilder/LuaApiBuilder.csproj index e74a4a1f77..8d526a4720 100644 --- a/LuaApiBuilder/LuaApiBuilder.csproj +++ b/LuaApiBuilder/LuaApiBuilder.csproj @@ -1,30 +1,8 @@  - Library - net6.0 enable enable - Debug;Release - x64;x86 - - - - ..\..\Build ($(Platform))\ - - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - - x64 - - - - x86 diff --git a/NgXmlBuilder/NgXmlBuilder.csproj b/NgXmlBuilder/NgXmlBuilder.csproj index 4483ea8969..3d2e677899 100644 --- a/NgXmlBuilder/NgXmlBuilder.csproj +++ b/NgXmlBuilder/NgXmlBuilder.csproj @@ -1,24 +1,7 @@  - net6.0-windows Exe false - Debug;Release - x64;x86 - - - ..\BuildNgXmlBuilder ($(Platform))\ - - - ..\BuildNgXmlBuilderRelease ($(Platform))\ - none - true - - - x64 - - - x86 xml.ico diff --git a/SoundTool/SoundTool.csproj b/SoundTool/SoundTool.csproj index 844d37c439..b4fa0df6c5 100644 --- a/SoundTool/SoundTool.csproj +++ b/SoundTool/SoundTool.csproj @@ -1,26 +1,8 @@  - net6.0-windows WinExe false true - true - Debug;Release - x64;x86 - - - ..\Build ($(Platform))\ - - - ..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 ST.ico diff --git a/TombEditor.Tests/TombEditor.Tests.csproj b/TombEditor.Tests/TombEditor.Tests.csproj index f0ad47e018..92b3dd0927 100644 --- a/TombEditor.Tests/TombEditor.Tests.csproj +++ b/TombEditor.Tests/TombEditor.Tests.csproj @@ -1,8 +1,6 @@ - net6.0-windows - 12 enable enable true @@ -10,18 +8,6 @@ false true - x64;x86 - - - - none - true - - - x64 - - - x86 diff --git a/TombEditor/TombEditor.csproj b/TombEditor/TombEditor.csproj index 6948354235..368533537a 100644 --- a/TombEditor/TombEditor.csproj +++ b/TombEditor/TombEditor.csproj @@ -1,28 +1,9 @@  - net6.0-windows - 12 WinExe false true true - true - Debug;Release - x64;x86 - - - ..\Build ($(Platform))\ - - - ..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 TE.ico diff --git a/TombIDE/TombIDE.ProjectMaster/TombIDE.ProjectMaster.csproj b/TombIDE/TombIDE.ProjectMaster/TombIDE.ProjectMaster.csproj index 6470e3e658..d8f5d96ffe 100644 --- a/TombIDE/TombIDE.ProjectMaster/TombIDE.ProjectMaster.csproj +++ b/TombIDE/TombIDE.ProjectMaster/TombIDE.ProjectMaster.csproj @@ -1,29 +1,9 @@  - net6.0-windows - 12 - Library false true - true - Debug;Release - x64;x86 enable - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 - ..\..\Libs\CustomTabControl.dll diff --git a/TombIDE/TombIDE.REGSVR/TombIDE.REGSVR.csproj b/TombIDE/TombIDE.REGSVR/TombIDE.REGSVR.csproj index f04c35af9b..3582bbe966 100644 --- a/TombIDE/TombIDE.REGSVR/TombIDE.REGSVR.csproj +++ b/TombIDE/TombIDE.REGSVR/TombIDE.REGSVR.csproj @@ -1,25 +1,8 @@  - net6.0-windows Exe TombIDE Library Registration false - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 app.manifest diff --git a/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj b/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj index ffb6cb8f7f..4e50298760 100644 --- a/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj +++ b/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj @@ -1,27 +1,8 @@  - net6.0-windows - Library false true true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombIDE/TombIDE.Shared/TIDE/LuaLS.zip b/TombIDE/TombIDE.Shared/TIDE/LuaLS.zip new file mode 100644 index 0000000000000000000000000000000000000000..7d8cb0555055dd40f2fd4b70c27cee78f67c3c79 GIT binary patch literal 4338564 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 z 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 pq0kg7|xukHe`H0(Cn$xyl)182E-H}zS)Nf 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

0$fYT>& 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%0D2dy&805DR^s<&X4p(|y1vSAKHF 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�sE-A7Tjzh(R>*DX34US7PIKWHw<)L!) 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

N_F}%iyK_}hKc#xm_tiVM00p<2DqLHBY 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⁣ za%ddY9{d{z?wX2f2~~VrzpSL9&g+O=aR>Fwq)NAEMa_bWO0Nhv2B@ZJ3dq?Md#5Yh zt;OZA3yx?JEyB~(4mSj0FDYKprpJ$YhmGwdC_baC50UONCp9rLJIp zA0!G%I;1Y&QYU$)PhyaQ>r!uJ&0Rb%@v_E zJUU=P4H0&eoG+W5b#Xg|C*xLx=0zw;XxBOGRHUYMfwzQObsipJ&EA`zm}x5}C6$-0RqE zm!ylKxhy}rYS>UwT~=eel79u|fBeC@MMAi-0($}AJ`+DD9tWH`61ETGvjB~wad!Fy z$N^6xyn^_z01u48xf?&c{xIOl44f?x{}mwpneJM|Ujh83&oC2IY8TJ*@Er5F`QyaLg)H8+0&jDU-;c*+_eHPxfR=}QXVecUB&cqoYlhY`G z3|b&M7_of?@BtR*u${#@>{R1V0w!f~J}H3tYTOOz%OV;MA5+s00iICP ze+Afi1?oY^Ja0H*?=W#ycF=!o8dFNlfw%)bDr-3&cB7n3jlYh@tuIb zzJ<%J572%q?ASYz4!9);|t^EjWKfZtN%ZGeXuJ%_z4&fx=?s$wOFdOJ@y z0T$YM`-=hF5VltW2Yd;k74bg6`1vS@xCwAILR%&OPHsCwdnLD{KZo#eCAX&^L^w!% z0AHTZ>pBCd$>;6V=kv4sqm>+8p$ARz8@a{q&&iXcCCyDB)eAQXRsLl;8ICpdhC(QtSk zp{Ihww8a$X@EF3@|LV^4|K~sdXao~Ke>TLX(;jKPM0%ng^G@}*NxE2mlr{_RRl;&% z1Kti{8DdUhsjvjN6Ym9x)AKX^TOSa=8`;f_90X)t&-ZRm&83^>w7H-BDsx$H54C*UNjYe4~)u4XGS^_SS-fp5+MYUii zlh+2up%k>0s_S+J__&aN2XP>Ipod$ir${Lm$dSEYF#jF0n}HlV<8L0urH(L?B5Um? zyh}levn}h#QkAlT_aiKm>c6``D}?dj=cbk-)sIqANGcyPUaOE=2WqO@OxlNdDeKSo z*qzIWSf0_N^$}xLz-HAd8u^Q~nH~$92`iWstHHA}N)zc1cMj@>zvppdU%=${Jy`!> z!-Lx&Y<;lpLDR0BUAA4~uJT>JUG=+KcRjGHZCCF@eGd&hBz=kf2lsUB>D|+}XJC)8 z*RgwH``r7A_xbiU>}%cE zw(sD+j(xrR`t}X%6WUGf=5}klt=-*T-0o{{Xm4$AYd_fD(catM*FMlL>^JQ<@3-!^ z?RW1l-tXJru)lSG+x~<5JNEbP@7q7HUpQboU_M|yU_0PGP<+65py5F4fwlt&4|E*p zJwS^X|ISX_<=$1at9Vz>uD)H$u7O>?hw2~N{!r^f4?NWNQ2RqP5!8RXukBQu@SyNN z{jh&qP^%TJ_ql!Xi8tIY-v3UjCPCYFpSuJ}>$DopOrte5KC$?IQRCI=wVF750vw+- zEgp{9`)<{0^leM5F6+2qDMo7|eyXxfzf0R7SZBtR)teJPHfqM7zyABrmVIS(*SW{O z^;W{YgRg%3`Nb2@WM&?C^b4c&+U`qTZ@n+R)Ow%Z)uz*GwA#_xm=dW^{^2Ko{{GMa zu6_su+fZXQ$!OBH&&*7=CdTVl>f=XiS1zA9+B%XD!|0^dC3WTS-AFanGfmbJl$bC& zVVSqIs;0Vh=GE2-l#(<$t+2vVTT@q4CgB5(T3<~qJ~Kgy9P2HVuN!?+B!4x$2Q{1P z%=ou1YfH`Ul3HmC`=|q70al~5-JE5enQgs#Tx!DUmMK!rwvwx8g538re9hMJ^ZevjU}}0 zN-lS8ES)S&9f1H4#gF|8y4w_{^@~`_m??Ar zqO?vkBD{Bv+iC!tUub0jhu_XYsRM0Yu8_{h&V(>*&|OsYO7tk2%G}GCXQWTx__Dw` z1iOdAnR$!9n%XDBsAA^?+H|zAPong^uGLIyngzV}t?UMkkV$F@Ww9LO?oG+_o=a&% zcB68yo!!iTe)A#G69G{#(Yqy~&()&`tU`irDc_%@JT1d|KG_&CtAW{~eS4;5cP{RD z9dq8VO!K5bRh_yf^KBz);sFeP62eM&@R!DDG#3H7Fm?Ij%2B><4mfZ z6*auaigz1cH6}^OMpY7f8@-Vz_i8|Cqp1}8JQ(WNpeF&K=g=N02S}kEO-v0(0O0-6 z`H^7>5w1bg@bHMRumJJZ0qAgea5$ry`$Sfc@9MuNvfLRP4Z#{0H*EyOuZpk32?G32 zZvi~t?kvimyR&!z&Q&=)HX0i{z{A7K$O&-pLV&N$puB2^ACB82ICt7g6lp}4r0w+& z`ZT&oVlII5)d8e%wtzKYnPr}38f<#O72pfFKkU_-_h;r)s zy7XyqlsP}oy`oSBb1h82#`>@ZjqXN)YoZeRR8(ti#nFr{W8#^dc6syC~agg&8R2s zTfRgL0$9kWZ3_HX=|J< z^g1#)R5H+`dy0zKlt)xaC9I)YLNtC-J0(_w|edXJG3klf{`S z1$|o6Jf56gJarPIUY!#Al)mfE`)flMYOkwh4+$=O(^C3hVc?WABOBi@4j~Ko3!C+z zUGhx$FuT_BZbkEcyC1>9y>|>R8tUq%jy<}poEQ*~%t`Xiu>!6wqEImk^)&In<2 zF+U+8qZQ-mGO*~V>6acN+|DCxUzpYyd_`Thq*(wQ@7o*E;Z0_}i<+jW%d(e)Jy5(k z=gxvDj^BJgNK5s)mZen#$@HdcXqHor(#e~Ix_5^PIB~HE=2sB1fGT zTL{wbb@rgJ2j)cS(WOI-1a(axFlVLFwtVLBZMh!Ds!z!(q8iJ;QD(_fSEZ48`)ih*zoYhN`v<(!v;iSiI9=D`~_Wd*TF{Rczrz7%ErYM%EH2Mp@nh!kO|rIl`p zOloCgz)_LvBjl&87u8X#><5Na;baWm}jH7UTV{a zQd@9OQeVyQRgn*Ty>S4)N|G?~;|;fO@G1+1S4jX90qGZ1#Rb8^Lfzv#p8g!?Zv62C z955UzRDPoh4ZrR}15XhE_@P(M`;LQfE-PThk}X*yR($zgJA=ev^-T?}5nU@;Gfs-N+a@mk7s<{Gtb* z+iX5LL&yG9Zp$p*hX2ZS#UT;nZW&YpBi3hCpPWb~%sDz;hUf#;+5;1Hn^<-*2>RVr z*k6+#6{gM>zOy@&U13WT6HPlv-*d&sdl1e>Hhc1FY;w0-7!(xtmN=&*w?vrsu|r7R z&U~L@?{+d#qgS~yb+Rj1kQAb5oC*?h@k2P)s<&DbtrxSXeu$uf^*Xwx4SdNqiH{2V z*<=DI|F8(F2mMU@A!1RY(`2(#T=kCLTFDF0q(OZ-E`p)eOdmlY)ieJEIr1j3+N`+C ztX6}C8zWjO?ck#axICdpUsyftz_9rOO>y`Kg1J zuNZnKMJgI!wuC>9;fO%5NpnLJBj`qPkL1QfES2uh*%VkD)vDNjm}Z9I{@mko}3fZGp%fZP7i*beZ|`;WtkpT>K?2_v)o zOMx4I^lT(p2K>?aJ7-SC&I3+C`FUb> z=aaxY6ynHde4Bej=fLeBPDh16!8HrV59?3ap=?4wfQM%n9fCL&niAj4=%%1U!TB_Fy}Gt zS)Q^Ye?j4ElBBa=(Nn$PdG;19OGTT0+$eMMS=>^4{`2S=7fZgvkN`cmG#8Y;qPXT( z!M?7M^mxK@8np#5dta~@3k%?jA}&#I$MEq{w%MHeI8EsiR((&3lk;M9u4LUqq*u3* znQ0p{t1PP{dthc92k->Sp90NG_!Sd@9}LZcPF%3RWg@O3Q*8v4Z#NSYN=5{Lq@jH)4lNLYy7w}*`x0GuBfbdcpg{?va2@PGF&8AHqfU+7gqp1y4mO!THVEXka zCo(xpTT5qC69_Fp{q=AXJ5>uyQyUX9HC0tIaaDy|8~{Xw8Q>HLn8kQGxFOU4<=3%E z^u1oSE76UrvyrU>nJV~gB%44)>qbVSIA!f zlAfResJ^zC_@^ya`Z{+2UuYK&fSV1)TJkUikGzqx z(7AJT;O2HS{4;2zPZ7t1hUg?%cP&57miVU>KX$oLof(EaJ@41Ht1)z;a1X+7-(p!P z(C+g?n+l_)+~(s-Zt{t8?Hs^|c+(Tsa(Lu6iW|Gxo{jPs9c*rSg&QqmP;B=hu+d?N zr~iAgTHvIK$vY(lk$GmhmN<)9@Xn?C?Ya`AiL8qP`K z;KH7^DEpF6Hx5iPZ9SOgS_6IFUJ{XKzkj!{aeF+we``|=-7+oInkmA%lScaP1bTX{ zyuJ)}4xxokj>kcP%M|=Zr2SJm{8ytFbMLF8EgPFDKW5{}MjO$K9HjAqU$il{iZyq) zvna}DZmGB74C;hXqlw=l?MQE3%pf61mK{99k;j{RMYGNVj-cZSkXSic;?Z{J8-@X^ zesX+-{O|#CD78S*q(5qEkeMj!=?Lh~=yD6vn;VWtpaAExjqqp9PI%6;uRRcLo(R+! zIO7_S?u+D~%Vsv}xX)w5te^4eEjmc=&t&Kr`U(rNU6{8Gn&R3XvWyM;%z9U(7l`{>A$V4rGcxt@%uX3 z{*7noAvITEitp;t#S+G7<^q0-vKlL zwJen^rC^2MrE`8mD1CQfsG;X_lGsH((nG()w1}n|Fz$; zM0i&g^_7JRApeofy9S_NN@qRX=u2kqu zRTuPP>w2OWm21t_>MqA`eMBNRsR;N0X_s@+qXb1jP|WNU<=Y?!(~(&4BLEL)tXB z*&$}WkRsLiafazemvHK=&6&j;F(7f1qZHp{kn%F4-PVzBVs-H9dV46RPk6a6L_kT| z5PV%jyqKLF#x?NVHGjgKAD_@-TOGq~c+81}r|Vd9chmq@pO;&sWJ4*^+S7*}=osuz z6l?E)P#^2oOx-W(@cx!s6O|8Sc|DVCq`H17)hXK@Y2h}8a%${B14d#cS69mTPBFZc z$5^gv;&mpG>*JCzah-J)@1rPaF``k2rUu*&k8+RnsSg@VA`YnI6!_Q=8QUTP9(B-& zUz@yq^C%>-_2V`Uny_<(%`@jqRNDQb95Qf6WbtqngyXYMk;6*6w*vXu&Ox(T=M?t! z(~d&Id&35O*mpcq?oGCGj;1>lEAK(EQtJmc3Ac0AIs=?0odQimt^Zgy=__zT z0A6+g!UJ98a6*BT9r$XpUzz`ASpPkMTbj?4TYc_Gj&eVzZS(+fqZRb<`$Y>2;v*EU+OA$n|(@9y{En4Bcpv$$7TLNf)cel68o(i+e=J> zHA8PJl|ZrDyeJ84M4bIj*TZ0?saCO9_jHvZ+*!yxc9C177-KZ5Uc5$NkB-7~N6Rwe zqT(a2W=xJ)?0VVWzYGR+6`2<9R`$PGhzwauEC$ImG~X-0*D*JoIervNLM(7j_SVT;Bvrzt zzr%oI8Y^_iESzlt>@UdkYuNeckXrALH2R{~a&+%n3<|`@=#0KeCFlS&zM{Ay zAP>l9NoPq0i~oJ3mci8kWd^vI*}iW4X#W7-S6jm}KY+L3-$-cvs_vhYS?TKDXAC9t zOr+)@2$jx!hNJ9Rf&GRqPK}^~q=|b4LR^vnguR+~wCx_3(1eMN*MJMJZ36~msV(}{ zW-vRRfMR>y%>0(B{B&}C4T<|07t7;<01X(}a`@)ZHOskrq;1bxEBj{pKD#j?DHqT< z!HjJH>Y**A+LF7f3zg=J>CF8ofv$avS<|DZ8ik({YUtEy2dJ8avs!M{U}0U?6QG?F zPUI>6^qD@iy%E1$?ZNG;Gt`Xm8=o+8@A|q(Vr`QmD!bUirco2OQ3p#q!<$Qi5=V*^v1(!LRE zjh6Y8Zp!=y9aTM#Y^vQUxtg_=_;tyGkF}+*)uz^wr}p7_MLp^*+3tJMQ^grO+W zTod(jpVKap*Ex=#`D8)Zy&L=1JzIDj z#0FzNzACyEcI(<*-*E?HRr$#60NY%6%+`AdR+!I;)!FYQ%5^2OKu0ThHHS8L%Lx=tAF2RV}n{X_r_zdyV6B z01`ZbL3DH=MWpBUmTY(o;suZFE(nDx2GpLF--H4g=(iP`@F1TdF|xr=bX*y#bMKSG1v|X zfJ1|Bjv{@biR1pg{`6Dk>9?G407wQP{E-w!`xQ6%C%kW-n&wW5On>1330{)Z3Ed53 zti_k_r$X+rP#n*Zt_y7f{wF_F0A_{wZvg(Qfd3NU-vmc?{lV+$Gu2m_1cRR}Yl037 zoj!E&*!rAB;?)Qj*U~xP2mF)&0|w&HI}UpB#$%w58CC{#;p9DYdxub7 z{2|NBQN8fL-S~zJ0K-^Fm=CU9YM!f6JH{kF(#{H`TYBJg;uGI{R=}g(+)!}i^D~F1 z3oEP=g01xQ$J`L@52FtUADELM-%~68Ja0YvSXg4}5t7y^N$v9dk)Zy@W+nqQo~F)a z48{TOA<|TSOVIO2{d%us@bq!Ddbc$mFpb0+gGI0ROBV||YL>Xz&E-A3ohg zWS(zo6Vk({dgq3*N8*q?O}yV*O|IY!J6j#WQ{ZmH^8Vpe#)tF8tkKW#Pvd%7hKdV2 zL0rYIHuXa~`=QE+r9s8o7ZgR3V;)biaaGPGJ!$Ts1%=nngAup^l}FUVaFJOXRW_H% z>0MRR?RSG-&_9Ff0qNww?}WfX$$B~gXddsc$a*>kXco=CMKum-n)oU{wFfdovZv$|jf63T{!p_&RN%~{Ci7A;X^!$d4+)D>2tsmEd<1 zaQ>IH@0W7eKU4m@I=~DSgGOvR^abDD@wo+TA?jrWy-ztiNjv;agn9&qUdEq#iWA{S zb5)6zAM|jv)sPHhw0e1nTqj;#uZ*bKr%T3Y5>n1beQi02|Ne1oe*1mpz~F|aitVUTkB*z6j_F@DF7ceHfv<2YL2 z*&6ekyc^GT>Pot~=tOR5u+2VpPu7p$K~QjE5$n>q<{6HrPbL1I;bY(ynVSm1BEHPjbvX}80I%p+HYU3HDYor8G#j zf2@0i{3b|{Bx5%&?OU|z1nm*~pX&f|f2spC2%24^A)pG<@;L6Y=v#F*+kRs759t8e zAlzScfB^Te0zN4_lVv6NcL9a?+}sq^w$FN9zzKlb*MJWi?g7wnFH1aF)WZ3%qHUqB z3w2zm&;C(gzzlFR13X{CJ)`g8-YWK@z=@tOkeca74C-f@m%;% z%@9xVgq`&IVw@VZZ0|dS5?4M<5?CEBl#1|-B@RjNo1e9RV(mvMB3$?QlN4Nro7t#l z_1@sL?^4E82OmnUF6kKPs(3>69HZ?NaU7u=Ap(u;n%8L6`y%VhF@9GbIDFYwb z8Q01~7%F$N+jECpQs!Z93<6PYE3h9=+wyP{Jjmw`WSG+9%HQ2&&O>RIkoWVoOu|No z6sBOiw)yl^ZYJP>`O~fVj`}_#bYO@attp{DVT~QhYbTn@@(OP-&*^G^d#VwZdcohm z{H7}s2r4SG;I{SC>Z4UkW@;q%-L6&cuB>36#m85)(C{xAXD~FZ0*mht$iqif>FT22 zvMA*kc`bIMA!K#uS$r-mHcqW@bI>3gi$ig!)Ms{2ok}E`=2)X_D+7#u9AU-n8e+xJ zWY9Jj-N*-fi8&RJS0U{(yLp)+E7ioH{q%DvvLT&KdI|7>uuik|b zN^1r!GuYirqhO^dty*m@y1uL6X&$;;LVzpt-;PYb$G8^lo;YF>v6PJ26$W6+bJXwE z+#%1reUrg@U0bQJ4uOXdPP*Q=9hGF7+qw&D3}u(6Ed`<-FqV2Cm5nB9^%@ewuba89v8m8tv91q=&gk+1`+OMvuZ8H@G+ON z-|4IsykL7*1uIZdS@wv>XDHo|=}8)KbPx{;tx%u9T! zwcXKU&T*A$wnZYPbEl0+b22b;Q(hX#FN&Jo)X6M6n=Ut7Xif6>+#1=EU6rQK$EM56 z_cr%i3A^iVP{|rJs`*&A#f^^c6H)~g*@Gs^L-1!Z6b=&08zr)Al85F-LLyMUVc-@N1K0nOSnsD`^v~fn|L4Sd z{+VAHX8$C>KOXvs$R9h21s3oR{M#sI6DY+Dy)sK%==(X09h|;U%))=H01R-Du#pk} z@Gzgj)x&wv?<-N$eW>LG;|$GrhL+nx|JgxPEM&w#Ltpc~;N0XnwflrD@5Y?XDbi39 zug@DlO1YirJ#-&6rq$Gdg-P(Z-Eq)1@S<604Y`-EMY7<@zU8EG3k7FxlAdW$jCZ(% zlKL3xBd;MsS)zUZ+u%Imf`}~iX)6LZbBC*m-Qsx{)=hfE1l&C+_p!b6Vw?jb z5Bg}p5)5r&m<>-0;8D}IEKV#~60#VC7_9F|8p-W1ZM;AcZyB0b^+RjF>u-nP}MknLBG%s=&a$8qP>2l@xByNbZ z_#Ga$d$feU6$iA(GfcP0ER!p>LM`m<^J|^kh2atMKn!$(0YcdFW+*SKn2?DtVlOH-S&(r>t@nXwr=7W%t*FGlh%GxE|RPiW{Mx_01SO+MOvDR(!vK9cf!pL?v(okvX>)Olol>4WhZCh zA5i=@EcwdLfGs$=sM%Q;TjN-P!E_A;#TGwJifs4mY~&t0BFGg&r_WwL)oaZTNz=Ti zp&%vx@^(*}s}8cCl=b=j%+@AbTdN)wCu}qirG7{NAr}xp$o7RNO89pJ*U!Vg->L^& zp{+vxM(x~ygTO)?|6eaCq(xR&;kDX$6oYUyO<@^Oaf|KV<-l?Ui7~^{MiWvz7W&a! z>z1+S#IsyPxLwXUXV;?TaMc-{Bp2D=vmKz;-jj4kLZvt-&P*S!4$uXEf}>mH2Gi1B zlInfebX#9m+gJN6)>$wpgm6SF z$qXuyLPsDcOhaCK_MH!!Va+imkA0*|BeleKO-o-#NzS#)M`4C4FkHe{*wiTyuTI{ z^8ObH3jdxP^}DP8p0$Lb7*9J4p@O$7kI1H}@9$F^j|C{2$(e`DJRZnxcWQ6aL_k)%RV(&uoGo2=)!qDsMlf zZb@}O9WAmc8Iuz3jq`+kI9xx3)x-7VbcDP&#@2Jmfi19j1v}NvYtj1Cr&m~UFXLGW z!d`1ym>x^Sv>K@t5DLH}J*KFnvFWnK|Ad|*qlnJyc1DXcb|)-TV!6sis%S8MF=VmC z;#Py+Q~_ehjZ(t%fqV=(4u=+&=Wm`9S)YpzXS@}TLE^1hu&k#TwJz4|s;E)Bbf%3) z37vM(BrMap@Nviuerq?Sb;2UjE}qo?26v7L0@&vZFEVeg*=LFRSbUN?3eU^4EJLa= zn7U?=gGOEji+5+FgEO^OE{)$nhqHg9y@#Depn4KdF64%m>Lc07coLlC*gDiM$C;4a z8N@iyAuJIu?Vl4Awx1*{T|B>Zs}LFl@dbGUZ@1%({x2x}dj*BOl=4fxvf+&RX>aO% zszbu1^sLz;S>PQKe8ILXrIXPLKX%e)(|_45kdO!uj$Mv7}bO4precqTQL zT}gnY(1`F-P0cy5*U}t3_dt++#uCBoRtsOSuRu=%;aFE*e;o17g+>u)qjhzmk3{>_j!zLGHDjT<&(4!6*t<={*X`bxAxn z&~wM4cnrfmNdh$NKGF7l*MQmM;araj0C%0h`#RE-WQiZjlrEcv`UxW zoZp)&sb9Zi)FJaJH77`qq6FpExp54Qj*>x(>1*|l17*|9cNEjEt?o%YcVdov&f@$GiaR=DScZv6o(>kOrn!< zduq~S9~m~^Vz2K}Y3F^E;l*|ufkTrQtplmbTG%pErsa`uNRQe+h9yj@%X1BJ8^pR) z#`G+_pEeqL4ev@=2bVcb5P5L(78w@y0ZWv%LS7z8jMzu4Q*$(fXPC6JXA`;%AENiO z?4>n!69@aZV31hE>Mj!uaqxIz{AQ9D?w~wtVxHb;)YDwii~r9P6#j;J`bPzYOgCyo za?Ppm-h0Y)^s-fm<~eF~p^<*3Lyk2U#C4K5{L6yECAOXB9ujT z)sUI2MJaKw`p5a_|4D+v-*z1I;)l0P2etT%as#|wjBj!AVxIJK+Vc~FILZ+2H(+j; zrv5}w7(ujm@q(`Gz3$=lyQkMNo(RRb2`v;ocFi%~)&4|a>eRp#V(_94ouPOF$-lEx zUA?Zw^l;rc8WonaV#`mZlIH!28jhs^8TztU@$m6 zl`=4AruEAz9incV3=0mNX&@ewaLLn(f-q_RVzvCqwaQ*>1eQ44UA~rCmV|x18xu!N zYkufw#_%`tB~Hg@Lic@^9+`xZoncRr!C5b1JPFE3&r^=}G{?8F#OpK1@a<>_3pZCT zGYQ##qrXGO6C%&!A#qn;_U0`_KuqS2z|A#|id+sR@B>zBZPbD;W@^E_Sguc%)FaYX zbAzUej9nkJ#Ncf1a6V13r=%uJhs&J1i&%x{@t#G?$wFEtl>US>6=N;}ois|<_$~Dl zIm*&GYc94L9GsBC1LmY1BZT$Q)h8)uSgGBYLw%RTDe+Fc-eUJNk&QXFou&3 zBpB%59{^BG0|XQR000O8gH(uIr;E?d+D-rffR+FN8~^|SVrgzKc4KmNZggpFWid1` zUvy}4WnpA>LL`6iIS6lGznlSQK^D#c&ADvVb7^vJ#wCK$2Mr!V;9^2Ej}a z756dgo9@JX_h#Soz;J@71QY6+4m~iuw}7XZG45B-%n}Tr^Z#g1RaaM6S65eeb@z@2 zja!PbFbrcu((5s-2%{b!?9X@@7-re^uqAfTpL8jVA)_TrR?@ZPKYm=) zicB>?x3088BC;Q?4@HW0QO3onV=!!tfRc&XLK3&<^MSuE6dP8;MMkDu@dR&9Q#?=glQF^`^Lj%e)bS+rjys?j)yWSO z8zaGoNqGfkAPdPtWYnyu zZkwS)KH;EH2%+T+9}E=fNdkC$2+_wMD&r0VcOxwhmlC{s#(^AmPP1GvPqS^ zt7bnX@>z)Fgj9mYpx3>TSkZJVLSI2*1=+MZy-^b)-E!2JHV|5tp4DBnBy|fJUxsWJ z%Lt5>u>+GTbSxkj)wmtHmh)35U-?TNQTo~nhKMND4JKICMA8YLAv`RwAdC^{T@uLi zyF?r|s2h}5IR~-Iol522CuXw&Ed$zgd!m>g?yTVj><)6LO1XCx!5eX+46>$WMA6Ie zyW7^E6k+lfQG^#`?v%hJ2B}S~+_+UE;${73G#bVryemMXs-V1*IhJyyM~U3KbXE_@ zf1rc0+^ItDT`8w^V3YxO8KE@+Cz{j+IT4{fIcl_Q6bu?pl>1zN4>}R~WB5dVqL9$O zBJv4iy?_ADr9|#rKE|6@1%kCBfOw=cGI0};SHhe3Eo!ZZkCrlZjKA~+p&iPX=MLmz z>Hwm^Vk!*1+{>J+_8O*5_TUqFzo`2SEBEstS7wq`>%b+n7xaP)q|9@KwoET5gGNbW z6%ggQr;X*=@6pPr+)PrpcBYHBI3Oh0n9y>Gyh=5P$Y(UNiTt6Uz9k|+L4YxlF9Ud9 zFSuf;HUW@E6A~Ru(k6(<5ZYvMGx>R!1sg_!1c{!C%H zuLGJ4(h}4tjvDnOv}&;rv@D7$D?$ry<2|47mewwU0BB2Xq!+}a7IJ+Z^ctgbUm>y| z)keGnl7|G0rzhjz2G=h*IL8? zA@`LY5zcpNzes&-3t5D0q->OovPr=><3R0gLVG4i+Z?EUq8C^~eYy6$&I8;@ss|Uz z%fk?br+uUgc%#?LkG0HvMRKHv5qzkk6F>#^QxQA%V(IAXLgAk2uD2tLs$|lMtMA5eV6aB|O(f^Kg|KA(>|0Ogg8EoOG4ZQ;;Tovys>b&FlfQDZ^xKC(+{$4}TLrek}%gm!GP zOF+jqc8R9!l8Ee*j;2McUC4C<)(NmkA{ZoHNaSaV$W=rH{U@}K^@2_vk#j~GYjvdL zw?c5@RH4S<1(%`b>jNA}>Q#I2TYckHz2MitepagYnj_Q*@>7LSS{^`76TM(RFf|6t zwU#=wSJ30)mZj6XRNaSwC2#~$5X>j7RsvRo^~#=%FTaES+Z+17oop}OzD@sd)W2C` zqWuh%MV67Q-u4D7T|RsE^ZmsQ{dKZ$*I)Bb_V>P!?C)&7V1xZ<`&$Z3jpJanxot;# zOY@)A_dp@p_Z@nHQfTP=I8(2sI*=+r z^K*=fP_Sq;)mG>Qr|szVr*~OfezRAf;a~j`f1vgRxpE3FzW{c<<5}RKN?PUV1=HHq z`?x&*Pn7@aGv%LI>kDQ;)ToCbL7++PWs7WgUKjHkCUp%Mxd&)WuJhV!5ViDzYFl!p zH%Ck*&~?B$N7xu0aT=hMbTw@m>3ywhKD9470g+2uf+7_pJ|tn;hx*Z4O$V)RkTSOm zkjyi>FlY@3+Ut5jE;K{8KneeR|46@80YCT<_^n#oC28QzH1)(gSf0eehQ9vMqBMO}FxYC=x*ANe^V2re!S|CYlf+Y-Ar(8#FqcGFQY>f(D6C z&bsB$3^~ghRk?#UK&f8iq8EsPn$KAb+1zHm#uoNFi%^l^2Wupy^K8g8mOxW#K(w4W z=v^)Ma;R3D=}R2-;NO}@jfF&>9=1*U(Tc?LzaY;yuZ9-$x%r%6QkKyAvoo3=U+oR3 z&mfuKbU@4;HtKCT`#Oe^*>@7q!yNqcI=vglP{$rYtus(UIs#a7uN7&@kLOcM8(&IL z8yl_AK5ngq+{bA;06mYSX8;`>6E*}Kz<``8L2Whb1rx~<=qGFtw0^bxw)3v#`E2~7 znhz{+?;;`hJLD|vNGf4NHoUq6O>Y9f>VRS&Y(q4$a0KAZ`!)3Uun;C;!3c(4(AUav zoX~IzGTDt&wH6m~M7j#`oRXp!e8(q^R)GrgxkUaPV>H*w%RtCf>x%Q&Y0{dWt>=W*< z6~erd<=%xYV5RH@#tzh8R9nlmKE^?@A?%me16db|*owd&7v-^K!?ZTgo-bcZ7y~eV z;m2U{)O_9{fW=KHUiK&rWK{%8p{>gC^?b}Q{PFR;uJfq-1aFJ_ei#OGptO`9|FTrC z*D%V6(n@~)W)^T8_WoYE4GeW}^s>!;%}|@R>a0_8(NeDS1;9H*#YDNb8o_!VFv0BO zttut6La0Q~Up1P)v&8h+Ls$&dK9*MM?tqYaa1gA3in=7&b1b^P5YGKR-!XCr#kd2J zmv;)@<(yE+Fc8y04yvIZq5IARau346pKCb#jXLN^*0Gp@R4A#9hqT&Hsyv49c>sUsl6k(wD^kJw#xh5-6 zYcUFh$@CZX96>*NTpO9vl9oyBNje4X3dKgG{_tMfb{^tBi(Y9tS6q<7b1kUKKGdoY zcP5;pP@o&ZrY$4N9W)Fnt?|&sa-iTn3tsics5AY5jvnaA11^eBK8r5sxJGD@uIu7C zC^$B5p>)8J4oeMlQxur*Bg_xsqcb~wr1ydFsC^AXly^zP^AdQ14s(s9CH23D+66=O zxy_6WADB;HL+`1HH-^!O&ig!Q<$6AJKCgy1Zx1ko!L--V8DkrqF`&o~ieR``v@Kfv z*ie+KXJ|Y?o-33|FQGCel)=mghti#aT_CjSMzyK7H1OyJ=$-~GM7esFW?+k0X`2?+ zj!^S8uZ^~R10TczOM}*pTxku0)UuojgWyA-=vyCyKhr@`u5Cs!@i9yi4M(?^f%;Xh zy$m}!gA>qku6_yV-!^_rEA@gja6@v#kZO+BpD|>%;;;!DD={qL1I^nm;jMRfp2c=# z^tT~BU2Rm1{PJ8MaPR@nFvQ=GLBS6i&*yY=L5`2`+!ABR?{_9wLsK9_Zf0MK(+BXm z&d8HS0tKm1&KUt1gPeb3X{^W?37%4dW>RQhG9)pW?dV#Id?zG0kS#J089+Q}Afo#O zOVIEs*kdWWmqamd6f&j{d22D#4C(W`W(=+R{?Zb(!H6dBV8)tJLqCwv0tuaQ643_D z6C=H;0$B!!VMPV$DAQY7iAGDL7uZ2feR-~)IcpCZ)TqeuWo^e(IFislpf-k_vtK|X zM_f18Iy&DIgg(6%vF`H$^yb3#t56l=l|` zp@}H16A@B>A*3ckT533tfutUgk+!x*@cc?)AOgOiuNa7z)sW4AELsvKmYoIj^+91t z@A%pTJOkzJAzyE7Ovb9tfR`B{d6xPag@s&WvF<*FFsaBxmT8Sh=jo;(v}{M5bQ!|9 zkps7cY8z=u6T#bWaSsKHhpyB*zmL)Q(r`u_LDe;#|-L>J3do?kh&dWZgv$sZsB|8jTpV3Pw@lXOgBtT8={bYZQ+Qv>=V=rExl- z`2)vJxESDcrY3(+04Up&%Ju_rn)AvTl-$RlP7}o-1mX-v?+qXXmKFt#gI^iEI5F2? z^N>lzTC4;F0&FM(tg37;^qZX~s>qCq*knRYM4;0N-glukMD7V8!Me!%P6js==2?LS z=2b+#jacq|Q7zOCGY|AGRhnvt7_&;@;#_GA+`SuXVZ8D#QC7;GA;xAS%oO~P3y?{= zrLc^$(V`o=BWx7-pwDLWYBWZ~0zpsc3e^vT9XmOr7`j; z<`icTu$7f_x&uH@8RcgqiGp2XA9Ssl{h)+{#)Dpk7jr4E*Pc1or7jloWWOtX{B|iyZGu9eEaBb)8Md09ff@zs;pqxWR;$q8Aj@A@K1kR|Z8oC?eN6 zBo-ke6jPi?>3J1ob>!Lkd8j3%3rUm}t${2R3i1{rRWGwzYe2k=hSov^uonUtLES7Z zKz+TAu34an`emlTzX>6PUhrE^%Wp_KC=axN$)+|gAXvJ?WYFFqu0}lBCy~u2mbE+6 zckX0~st>XO&}ap_D%5{2-20L9rp%b|u2t5zIbF1?`^bWTZM55$MR-_v$TdmP8q10uKM^57gmpDOK6{X*ri+ zO@~V$hF?CX0?9koyVv}bsS@0zI0pdJ(I zEd_Sii_NkqGC~_O;x%uxpY~Fb7&6|vSx^b(YapnN5F>-sy)Wm;#fFIPD@L1Na@ym7 z@(%xOqv{GwkIFgX)*^uz@!G+gi;+y7c)3y#0J0g?MClz7VFm#zLM(zJ2VU-5dfOoq za|d#HdB31Fi*pNpnmVG2ny-?dz04&b7#Zw+}GZlyek-aw+vk^+1*drl1~3 z`}=k(bAorcNeD&WNCDpAJJzaUt?~xTv}a^6xk~H#j(WI0$h{4RcE>)*c`M<~AYNW1 zdRSmRkZ_Av-QkyT#xye`_x5qfHgu;13RD78AT(5Gtug`NejbX9kR$d+`}^e9eIcJb zE|cB{2wcQ)P68{0$1=SmI*;icSCa4fBa$NDOp(7T0k+MX*Mw9h^A#|`Q)O8oGP%uBKa}8cJoiyj)dP6f}(Zi&6FgZltk5# zR%UyG^OW#bmTF6Zj{O%sdxlUj$CrYA{V8Zm!?%7EyidckG~7qS4K!Rx!^t!Zrr`h@ zifCv~!}oN1&uDm`hSzC$mWD+%oI%4l8WIM5X=p>k7j%DqOXnl$d@>DZ(Qq{l>u6X( z!Ke-83l*X`QQ(}EL!eE!L2mhK*H8%AzeR$hORUe(vVBTX1d-38m80q zJ#_vM4HteO|3^As@c}*EhWu`+6}nJxX*<~Zgpm2a{YmWsug-m1KXelDDJ@_=!HZcU zfLFCG!tBsX2(Kpe64}Gc2fd=vD+|2}(M!}36`)rZdSRVV7QOfm2t%)E^h!ssEc9wZ zFRU}d&?}@1Y6!j3MJ-=;iK#w+^mON}uxFt0@M`C|gD+Rk57&J0I_D_7W+^P1XX+4-Uy-7mrPt%QQ$fu!@gychg zt4G%*zX@}P)Te!!1)A%?5a9voi}q!F`jfS4Pe^^+m)X#tmOb-?)EE1QKSD^XELPSU z=z}NH$({16&fuTkpyYRu&O%c3#ITu=yrG}&(4PcITR^`9kZhb`U4-;PEuKK}gRh_N!V{*Iz?$#_R(SHA%hVkSgoq$#INkW5fbn3R+n zqfAn$Cd8z~dAKPRYDA$j6DCZHg%3K_Nhu168y=-jR4QWPR4!y0e9bor!-o1s1foWx zyU^biic?ZiU!y?>53H3Y#&Jro7FuS@cZx1a=(|9%JLSWaZCr3XHa-FD;|l(P^1fkk zy!Itm#@_8|;}8vRN0XC$p6zKQpHDkl2+2pZr;&Ui?P$~rKBhg5QpA@HpK1hKN{L}C~WtKbotkIAcPfJTyr^L~|ZOm$+&zLbIZc+l8&z^L< zN_DJQE~BD@S6kXRQWxX4vsRn2apc~Aic0sw%P??gkWk7!*cslYm|-@Ve`hmyvL20(rXD#j%w z3(%IbT4I$}7w!*jtcZIub0(VSf6fxjFlA$=Zd}aNm7C76H^uDLCYXJk zF=iiOgxLe#-c?XX(anGkFv0}rP#y+!8)M8S4ifO%0I!WJKb^s5VC*3v*TEcfh=UYi zhB>&IVh*mtCfhojYO509AWSW9Z6Oajb7|`Gp$aQ7nl&(gUt|lzZ z1O}1~^RPoFW2{qzIcDc(hM9#K)p63<(Y;+L-_yf`=3YN*s=xLEkhPqNmvp5*t7Vul zFcYLNlYudDD#mpX7-IskgCNcb6F|QNt{v)JT&Q)p84RBQL1i-?L#qJ4(k4&q8qxvj z3i_LdanqqLxz_UFOd^3)O!Kk<_lIu8Wm z>btBvwg0&9f*`F!7&C;y<6=DM1J4bht64hP*GW)r%*KqB>~vN%*wo+$C|R&E3m7Yl zFm8wmn?dSlXk$fhYJ20*4?)^qApiv&u+d>mz$n7Fkf+Aa2*!^K$yiiu zYFrcwQgInENouL<2Lul{EGk8vNfF?S@hQO3o&X#uxWz@Ok`;<{RNR__ve=m928Qe-c2(%Ch(A)6+0JLhLm9*gt90EQmA!9_# zz+k4Q(3A))W>T6`4XZ%ZBt=3} zDz*7kWJ3JF$eF83SHwzPN$+)SrFgiJ6c3D?WNL*n1?%66M=7wu7&v-jRD4o05TaoD zfVQJx>lUAspiwHKU@xpp%ZQ3mCQO5?NvdX2OmfnUmLf&!v?OI(Y6_Z)m|HuJv{W?z zqSP^ylA$l%p`V$GSdIFF0$XSgvQRrFJ;^ym<(!d}>Kv<7JJVZj=VXbq#2H6R+lL&9 zikS4a#UGY`SRK~Ws3_me%mDaDS_&d2H7;49l){b>QKOK#lH!wMqY|kC408m!N)1cr z^mGOED?ZJzYDFa{sX*UfVJV6fv`n;Ji|LkDV!p{~D!LJDHgl*#9SDo0KiCW;UuTEG zf)k@sgolj|gw@SIGd5YHN}8s?ZhTM@o*1K4#34VC#ZJ{EDL<~kpi4fik;Rh3P>g_e z+MhBzLa`j68V1NWEj14CwA4{>;vvVvo;x~b$|vYTk}gY5{hZ;Sc^{ z;2Dc}5WyGzK^;xJ%85u;$*7rf9pS(-DkfP2_C&dGL+%>N1)!-VVgXA_6VKUU>SW)T zbhSo_dQbj~uy=?Sn3gt0lOCW+jYVDaPldn)yEG1zj7n0fA;dGYf)$4Y3VgQMwN0NxlxeXFI0l^LM8Nb+N`>%bAYos#Adj{V0yK15tdiC)yzY$&8^z#{9GD`p+62Sfd;Q-IW`Q_JM)H&v;9h~tI z9bl0VW)H#v)(fe+O#tofDclEOD2+!0oJ!+a0GH8tA;8WZDSdnZ&VVFDJOH1Pbm|;5 zpc6&+0myZLHN}fM7r8<@is%5xJ5Vyy0nViHEP%Hmo%Ev4OOHBJGMfO(x=?jP03PT< z$u9wTyer*DfVa9*a_Rv3h``V*VqXF`IfNh zzzPzl;4K=j18Cd};S}sl<061ry^tL!xR0b$@Fa;-@I8rB|DIago6_^w0L6X4cf2V` z^g(nAPNngM0MSp`V}R!efP5!pTM7n}I0bJzgM4rDcMVJlNeK8-7wX8uav@CU}}6Lb^wRR?_+_iNUN@(|4p z-lMQ^EDGNKSQub(Yy=hzc{#iT07uU;_M`VmUSG@-a@u?YG#nqn|k$WvoV zED1}+60iV($(RC@LoOamL+1>{1Dd-*@*?37^0*m@*#g}ccv9eMF$VajgEldcQ;@QQ zKvFEGgmM+6cxXd}xPg*RzGHxr1Q@#5o&<{lqor*>NGenp^63Vy&&b?EN)>@sG{6JA zsC~!>0yYV?0*Ts848$zkv@r^j5~Q@smO#&3AfdMubBEK91pc_7zJhdns4GV;ko8hQ zZgQL6PD5I?(?CMnD+=<7P@(|NIB3lU-pTNX`lt0SATtok5|A`x8|dwHveyYv3tf7D zgNgnEJGwxLjFc~GBSnRB$fBg?)8HKkoN)g~_GtvonMC!e#XhNjQ{N)6jvzY(X$@2j zNKhNB^+(2W6i`*b9fNv+yb|y@vTu9H|8v0dLz(SI@lTAQA357bA&>aT%h4kyXGjET z(NvI`+|EPM2e5~gnl?3W!ZsUk7H$sNGG3o@fAZ%e&-OMq z!GEuUav;{AEW->`%3drn!%euXk!-Ftb7Z*08t;HI#@42zV^oQ7>{h3xO8B@XA{tp6 zg(>1v;G{0;f;%9JskI;|DOQ=LN{d&EeAATaY04OMHkEkd9;lpU-LJKLG@NwPGE^e? zziyOqqL3J+dOFleNr&s4RH!Wzx#AKj-o?(s)g5=2xJx`;J@EeHAnVa4i)SzUhbZig zdr=CzeyngfWHR7Zgwz(;CnY5(f$kxiNpO*qs8HfLjP7mi3d6<9Vel}Zn=*444D8sL zv|Skq!w2j;W}oriv3OaJr8g6@cdkDb?_hiR=)(xyH7ox>j$78FXM56n6>S?l{_&|* zi>w)w%q%vZ-pPA2&pY309^QnmUJE=QmB3kS}e(0VF%AeMyPIlzXxIg=Z?YI0c3mbm-8|jHY zF~0qO&e?NRK}c^i!LJ!xau^4}BKz>JVCc?{Y$0yj;{2wpj$C8FIUFMv3-62=EZMef zn`@(=I!xX$De{U#(xdCw7Fyl#R~*ItQE>wuZuNb{SA^^K7|Cz$wYa5ZA+%1*(j;7NrEg^KyH ziE4HFfPVclGBR9J3~jl@rls^tpOTc8uId-7Om6jeM^~J7AizkU2S|E7z!twpxC~y% z_g$bqo}F#51cSlW;3|BoA&)cXEB>Sg3Z+{0H|n6q%~8*-84Nuee!=`;#bD(yVY9h2 zYt4hRG2iKK^j7%Ji(xqbU~So_xp;=-y{|T&(pgTK)fhcGd~Kz554Og#^UaX@`gLvs zxx(Dx#5(JSDP+0*}Z{{yf80a~5XMS+PSbo;g!;6lLDnB~N*f$_j zEY_XawZ!T8b^nd-sZX+hYd(9c^!=d5CBIv5IqY}Sh|*uFb`8}0E^v47goC&HRorYC z^dsM*qnq=kxi;GlKA6BBe7N>f_OI+T51-fOb&K!dI4d^khp@X+nbLXmHMMm4mf_t_ zq{N4I`FZZondj|h-tWFzvFon%VP*gCpUkf7T6Ds3#FVYOf7<1+Ys>9UKKwn7UvJu; z$^B``$;~Gd?w3aAe$_wM^G5Q4;KxNv9c&hlGiCO?HnZ0S@6|jZQ||ttDZ0{qPB`Dq zc4b_*b;iSO6jhgZF7P_C_sT+X(AnGWflTj}8M}=}|Mtw4xo|(}u&d3g^I!-<`!fTN5kd<)Ey!HBFO=sMee0A>x zzq0qz*JGC|viHC7u30GjVW#li%GK4y$EHo<92R}+wQQK*=#5)$O&fY_&CDqQ1^iJz z*H4Lhes1e!>+W;n?HGp^t;kiZ_XRdnyO{@88Xz|@tF zzj2ya6e7JDIqlIE<4cJVXTKf(T=;(O`nBgOcsBc-O=G9;S}4+HEvlW->)y;&jkUVt zm+z0BUX~?%Hudrs#Yc*YZZ^+2Jz4dI(TjvGI})sNjPII>od#DP8+h4Ge7T$vFe`ff zPW`sy3x~fS=JM*S92WBqYiNi}f#pQHy8#$)d@g?OScZe#ob+oXx>9WDj^ z;=HAcsF$DH>8Qk$htA0_b$qzJW7(Zsqb^oB?!7nq8@%~xT1;=-n!?MAZ*?y!ObcW^ z8_}sQ(}nME_x<#FW5YX)O`3e9%dH2~@(WdmLSCO=Rdo4z@c7|Z>vrDe-w~GzCE7XEX_Ob8XD|Z5Se#LI=B1Yfe|yO8dXOf z&TtsPa+HS*kkyRc#AA!QMsjzouishZ81^)G@A#gBZuA$P+4kK%qWZ-5zeFAP2(F*$ zF>;puZP)G{_9UM%`|g{mLn9-yDt6A{9FENy81@^V&Knvs4B>S+gx8@spKC%#RRM#| z0{3W*r=N~<_AM1`m~8VdrdT)}vnIh|Q-+(NnmjfVGau)*LsU$`{N)s>8sk!`|c7#@NLw+WL&{#ckqG4fB!SAQz%E!rUp=oEb+YD2@Va|@~} z9e&sm(tK2O+KRpPNtTIT#d)|PY1FAc`t4u!c3SPU>vFB+P`56o)ob@zYr8v_o>)-1 za?kY9&A7wF>e+{~n)?feieHUgwdmQIhNb-yBN}#9SawyF4?O{~HT zQgrotHxHTHPeFHQ*k;u3==R0Qr#H79ueEK+zTaWQC0T6wFmqu{zpsDyQq?se!R?gh zQlH$2vfR}Zj=4PI3D0GONzZnD@!NH^zrCFLeE5CW^?ttVpMCjcnw@Q))>Tydy5f3G zQ@Iag-l7YgH}BrI+o#ut^o2!_Zl4)Z^>B^D(OLUK9oI}_{;I2FMC>}oU`-acdFS{#(-~o|`0MODf!&TVBWnFMwPTMYW;j`_>veH?p1?Ez1v7y6Y<^~OhV{2Y zuTJ%sd~-N%cbZoJ=y~pg?I-vA{-o88br+K=zNo5^?LS&_T)SbZ+pjGTt`xehOVM)x}9!Wv7)|{Ed5^q~7 z!27jUWJ|iUMZf7){d>!AHk~q)UAUUO*!VzP;?}_xQ2{$votY9C@H`|0AJV3}xdei1 zp-q<6$G1S6I%Ww!H)B5teC!+s7JP`mZpUJWgAUbwyU!k)^`*?;rU$#wrf}4l;o&jI z&5eR)Kaaloyw>ihU9HRAm#mEg5)%}YBv+y%Svy{a#!o#@I6o{&c(Yb8eRr*cBE%-@ z;p^fa3s>JQ4t}+xPej)u|2=BU^k2_doGeRJcZyzc?^Lr$-6gXi`r<2oWWf!iIhuY2 z+>v&h8{SrCY*Y7NHu-!`_b8L|vHMRsXKoY~hE+$3XAa4I+3n?-5&NDl{(V+v&a#n_ zsl6Uv9}@lheTlx2eO=wH)1E{e{qgHP>b`SlEh}xPS@&-BV@Xw)kylTACwr$Rw%=HL zYEb^l=+hsc#$~Y>k{r9WKwH)B zCck>nz9(5xQaNGaC7K0JB24d z=hsHe(#yN14qb33=CYJ(ApJ;!@P$CcXf63l6boGcY_l= zJB!J9R+xQbYxY$<`|>|z4msma)R|D+S}uqG;1qsB7mY|)P+TfeU{XqwS`jDdg*#I0 zT~fmn(f3`Vi12Wce|Yc!4|j>o8F%-`o&CJr`b!+~9@N})XqAh8_jV3f$E2i-!WGJC zNwJE;oDOgB9HZWN4u{|7Cg%BCla)swpAPvo#z46bcgVB;A(rTgiz$see^TQRYVE+u zYZo`Xzbo9cNF}%gZHnE|u+iE7&Vl-qJL|KL)aen{V{5MtK5snYKw!6&D4*}Y-G8la zoqf~@`J?E77t3E+*ag2#Fn%=S-s;V_-aaTgc@f{->DEuW0;99pA>3(?h5D-l1>JXz zJ2ECXlzC>8`wN?XcPrAaSME&TH{Oal*D~e($|s`RcfWY;zKXSC?1pa^9k1WNfo*;C zP;oRbWqG*mfv+~MoLSp>L7GF+^b}vE;%-&SKEagdmr91-4cOxN^7{dS4naQ(cNbJG zUoqF8y=7)E(~Cv1TYTn6&+qtZ1va_B%DwBwAHE#ZaN^#=?!mXVI;A*=T_~ROeslDh z@+TcuSnyW#ec;@;!?jXE-EbJcIpH1Qcf1h{(j zCT`Aq^Zd7Eq5)@KT|4%}=(}rsmd37m-{slC-(-wlE`8Z0|83g$j^mBD+6{YZwO_q) zdbbF(UF8S2U(KHXCV10@Dd2b0E=0eN*t;Ihymwv$dKFz0RkPdvI77_htkC z{)C&CJp!v0JD+sWE_CC-+ws!<9A1+y|j;}2Y++<=f*>}ryiVo^x9=|`rx6n#xCBOH>Pvrl^Lfy z>E0Q3)^Z%Jjjj9Wk#)1iKOg2+nBL^LJhCQn|IBC&quq9R;|{?@EOOGs+-JYPq}b6Z z+}*xjiAPb};W79qJfbkHFl2u4pS;fb;6ka@g&`ASxU|80OZt#|;^a1a;%Gb)pU`Gc z9P%gILfhg$zqJoO6=4|%?J!HMUY;bnnlzh?RX&27Oy?MV` zJoON#^4_AaJf`0))L;LNYQPHae(|w^&%(y0Yzmu*^? z?7t?RQR?=3-xL4Qds(v%GcSo|%MQI8xv}T5gIDgYCkT7T;NSbKluIM~4eu_EFR$;V zwyPRkKDE=^@%}SXeB4-xPF4*I%~mk$y6(F4yT)zLlYZAjHtTHu`uWph!aWyuvCG?% z{XTwCk3kDWfqRbMDz-|#zkV$v>gCc|MmvhfZL1l+evsGY&S4|J&31L)yZ-wz=0?{y z9m%l&X_H6odk@E3?#_ev8SUsLzHzSC;knh-eK%~|8xk_N>`YKx!wI6hbo9)^#FSOtgW?u_|IXKON9YwtruWk?YeEadbz^_~=*usR zs~8I+1GRUaciwsM5X8!<5G%*FxlIzB`gzJ%%=PlMfJ5%z_BM$MoD$qiic36Ulj9D7 zQ;JhrDa!tf!}^~JaQAL+5B&L{vYXlT&1bHOrysMtl5_dp!wp78m%d33)>KrvkAA_J zn>?)U&avWO*+onB6GoKBzg!hQb=;jf!^XWY@<_-F=wbeCf%Sz9*Al)^7d?A&Sgzl9 z+ZP8+F|v7jYTEPpAva6?DyB{dmGmz(^-L}J^X05eC1zzNZGGuc2w5kn%~axc;FHE!YTD@t5Dr>4r|Lr z)%KwN>Xi;|IlLzRlkbKKf7zj1J8N)Y&ECipPp@284e|{xm3jp(W*!}q=)!N97aDNq z;<3rXaWM>4Rl?@TYrUs2??{EpYdb_uCth2bUW-jLuk?u1jxXGv+ihYLu3onC5AB@= zR9i_DhVi0>;_eg=!Ci_=aWB4DfZ|Zxf|MWyin|pkP@p))eG3#_v}kcCR)UoRyJ6jZ z&&t`HljP0ZWS->B{O|try_1CL7i#Y@AZAcL6kg&Gx!F0g(aWlF@*cYrLk)E!+*yXk z3N>W!`#rZPT=t{iYjlSa#kY$P%#!kdj7mT(?pZ2RcTD-v_;pMcp^Hs#xlet)nC&v4 z>??trhY8#a5ck{G5%T9TAl)~02-nibQlxQZ(Vf-`juVmPWgf=)lmlt+8)f`);WNAr zQzK~uVNMVV=9kUg4fccO(RYC2Ux@_*JR$cliIlXXxhsc;rIVwpjhmy37XajD55)Ui zdA=(C7ko+Tyi`w7#WH3<`aqkvMH!v`8I zJ6oAsa>eiJ%U^Cnj8!woM(#eS)zw0)w1JoQ_suoC?|Oyav~$Nw)aG)are$ zIeHIlUx19$;f!L7Q$wN6tyi7vWObMeM%01HfY`N}1)HPJ{SW8kd35NooxFj9%z6_M zffSJd?shwRQw)|prJgL-q&z-CzsUUKlboPnU{K%_|G!zVzuQw0km24QLY@L?iLt+Q zQedCqhFw|Q`?`Yj%L%4afpS|FVJWS%4d`7X$=c?XMO*zlcI-nXaRJ z-}){BCll~C5c8WFM1&l4AnNtk5O3sC=YF*eAC~ijkp&(ejv7E-x)XgCiA9d=rmJ(KN*Qsk4f+H!&_|nA6p+}^$$MTj68e8 zt@nvo0<$!E)|2+Ob>Bc9Fq+Ea0SP7l8miHcGEXWF<@+(1IbYla5m5uuF2Xa>pR|!u z3VO!cOuw@ep{z`;)^$A*H~7GybO#L)iZssd=d3ZReH=vtm^4%5JVIdD5G5Z{LtVB! zM@Hk4wd_4o!PrnU!==C+rGD=t5clMw{bDYg+MCx(3a^AaxTN`^uTLkBhum7hMrO76 zk+snr=EZ>#Fl*>yfZvTTji3_3%fWI{tEwv6x^Sl{smf8hJl;hc-D-vwVa;rRJ>L@MJS7C5ka>$$aZgHd48}tE=w39>AQ#W~Zj!&S`3G&t;ge zyh>xUtk)iW#1w37&G13Z+0z+50cz6qA<>qXzQ&2hs$?!N{h?F=A%|rpr~q)~LY!fi zT?)G7XOEwh<5tZ|r^m8yA!iI@GrlB2$)4i~t1N#B3L$)xR2cs973SNa4*98Bew8z= zqlTr+K%z6H8|A85jTP3tg-Nd-n=&vaB$&hrldIZ*0;4AB6V?!KqYp<~_xeSkPU7M4 zH>R~_(MC7nERwxq7|L^5HQwZfKv8H;cY*JtX)q5m9IKe~)0QR~cjAfb>P8i|ERjgtjO)TZ`Y84z#xMQoVfr|QdYOJZ!_Y<=ARJ7&ed7dg-1rjkg zxc7=Xa&a5!Du=37pqGx&ftC={w{MPXY_yXL7^PvUnj?wij-H$~oV+QmWRP1-=+E6l z63k{(6BgyjpBm1*^^Tl-B2l@Wjh3cUc04XI$O=Wyt^kBCUU*(x`amjCoeH_kqU zYlwUcs%QxBO}A7iXVLE8CX^o^Oldk>XfUv9ZwD+7wv{k_Idt_{SK!H3t%y7DesKmd zh~HQnX9Gt`<(^*%?)gYds$?EKG`}kg)Vq5JKHn5frH!r7plfFYK;b-W0D_s6znKYv z4b5OCQCOYecg%Vw7FgBozXcn70874)fMCSAZxV2%01inOS54G~Z8*5=()SZ^|G%Vf z!er-*zDf1%xP>LPrj4}&tkti2C+D{*!E2c73rg^tBGBzG*}gC1h(8hkMGi1a!=xFH z>E?34!OYS!o;brAiqUD_e)7IZ3#k#YsjvBI-?Jp-sRB(3_0T?^&N|9*><(Y=JGUq{ zwyL7)piC*)E#m4$n6GR`i6%1Qin_eigInXy=g$oqXpKj-k6)(mBye^noBLi>HQXW& z&>t)_Tyr)|!p76#jNp9k7?)djV_L-Jou0m-V?0kAGFNj^i(m7lK||Tcd`x$Qbhs8X zJX4Gl_EA*a0n)t&s6LTc#`H21EboGMsXbf?h?VQLV^g7#VkIIIESzBge=co0A@=mw zame1QCMt7;+bIDL;Mj-c?+v$aHskQ;JJumd(V3(z!j6dJ zk8^+oKgt1`ge-2}CZ-S3_de?d4Q#ks?d6;OAr6p>lmBxL5Xk?XgiqeVVoeSC6L1L; zKR<1){nLJTghZg$7YQFM-2=kXy&Rb^DUjQ*vTb3fF6_jGowHx_1?)h6cA&uL>7Lm) z>E4%#@i*z7%rCCsi;VB5SMlpGKFb$<4kZVX!U9)8a|;x60ukr^0oWf*+V-GM5Q?gY z$)X$MCGt@|aTMX118)``^X&rZ?npFboXR6*d00*9)*g<|2drkzbqk|?Y!-Hr$|?s2*d*iK3J|}2p#A`(S_)e; zMZjLY`o~q3+>1m+svw=9vKbar(`p16=!i1%qiRFLn?j&+p2=6zBu(KP`%e=J5b^Nq zC0av9xd2YjAoB0IeGID56kFrWa&1kpq4*N2dvz45kXA8|r^_)d{to*6yPHJD9TG0Y zZXEaa-v*kX?H2k!yJL<;ki#1J>`K^47~5pLsSo2AMG7S25^G$)F6*bHqEg4%t)}KZ zjc{MeKU|a?jn0&i0@q!E**19>UJ0c>Y*JJgn2B$(AHzvD><*R?>hXK#HW$ z7|?}DInQs`i#v^RAkdkL^8BUX1Ux>ckYO(2 zk!<6VfW8RvBfq2~iCpJTSR=LAT;$ zgsm>?QGEvYrui8H*krbypt^-@Tw7^FFc*7^PNA8&LE2YlwWG_$d&y;kez8q9wP(MR zTz57&dPi9SSXBCGamOIL;$r@})pAF2kk9VquF{4Aa}gd>VUeG8;CjSIo+ecsAyc{; zhHV~9Oz(E>yO?6wVkG!gJKls!L%PxK_KX)uakwR(I-Ge@>#^Y(nI@)*sd9(BejZM= zkfm~z^t@R%=YGoA(qwoP##b7+3)8@@pM&*&RE+){U-Lf)>jh*+WkEyTqVOT-Rl9m@K;FD=LYua>-q+4&yAE!zt`HgvD#&%em z0NBLNx?D!>gRfe}H_`ir+vJM#p*FMTZM3`v$wrnTv3`-VYTDD7kA25TmB^tYl93uC z&oAv(#BKnX)7M4G3dUyXfrs%<%1dC;UmyyOtVOcJ)fh%WvI1Nq4sSQ@x0lKAo(l1G%qPoL@w~#R%NC5w5rZ?jqfNw7BSQ zZyqN)nyI6r+7_rwo9lUti^hBZ4tk~dho`Te7Mx9!t##l!Me8{`C&@&Uo5T%Y?yiGR0n{Z!ibU3#zswpHj~Svw?1oQSZE|JMVB zG~pOstdH*%iGicn;002!G?8xC)X5@fwGEnk^GLhttWX%uLJoSyu#e7- zI|Bk0L9ChvNi|qQH)tsLLOUac*$_}@T*K)Ctn4$`og(8fg6McnIBuLn6<61htJ_{s z+GH&IIk(J2kBkRVI+B;RJYVZ~vd$gO@=3!PyJ@lga+#}k^_A>o+tY?_KZ8%oY_za^ zM^Zm-c+Kn*X=g=$QDtcA5Lvx&MadQ*LiqTj4r9Ok+~ZDZM9Byuk?2L4M#V+>m%Fuf z$v{`~k7uIPlZ?-i_3uyNsCGUbDXHd+o^zgBDu|fne;vBcq1Q9o86Ll5d=C{I>KB&_ zCMx@TfkHUc5)V&&V>l|5+L&6wOHt;xF{0AyUDTncQRkB{k4LY8LiA>(iSGf0f&hL_ zu74L$$RqVTCNO>iDEt&x!1uJnaxxbV{<`!J1`0U^zYP?^ivN6|@OS-Czj*cEx0yH= z>*IheUOc@1n0lVU3(8i znIDuaTrzu<(6_?@!>o^?H+e;KqF3VS{g6&FM>AK#SIR&_O-6IYH^NEENiRo=uy~XAX{YR->GoFEX?^O(7=rhGqD zm>BR5Zg=%@14L_Q3GarJ=xaV!noXd@Pl;>5>~&cPFIcz{4}XkEF39*(Kw;N;;_6k+ zryiB!qwvBZe!$_q1hfBv!ru!N3eqXB_A5oQ7Nrk0`qzd>${X2nMFWs*=B-ry38_Wc z`!BffzIySI88Tc^K^Yh#Usn22i{}uTKI~tF!cJPVx`K|g6KCA``=(3>9!1d zPRGlY*IZ-^F;@6Bp$-a)lV$ohGN8q`o@5%nZh9&|om)kWtI~|puBGJ`+;3xzuoNoB zyZb+|@a& zy#qn!M)1D9OfU*WC8#HM`G27BH*e{$m38p{K;i#D;r~G4?=;^22MYfO3jYTR{{*@E zd(*rh0ENYPQTMx>8G0C8Tvt1Ad!&zhs#5>CK;fFkcYs2E*wux=w}8SgD}EX%gf;LD zP>3Y{1AG|m=Z<8$jL(>OWpG}MIqVKK*;lGdJ=|*IyZMZ z8GnK;f&mo|N4bML76Kod6v)SV+pXIeQl7#vE?pfJrKt0P?J-9tX*#7z?`XfXZLg=Y z(1VKCBV29fC3-6Y`eY$ntZ12gh7f$(;Az<&*1fq|Zzwuq5$JH>ae0py#`sFtZP8iT$!bC%Dehp0|E-$f+OYAf@N@tefCSH<=%Pt2Q*y+VFK+JKZjPaJ(jCPa;k zcLaE3r&3r*87ut`_k%T-$x|H0#f#U5EN^3=IgScC2T7xYyKra#>4r}eP4Ni@Vgnaa zmh~{6wy@7{Hyi1$8zubnfWq%NPk$6BL~O3NQ$wZl&#y778l`_fG-W=yh_U7Q2_&My zj!HQP|L1|iRj&QkJ_HY&XBo6Bc-sfU^s`Ymn&AsMEAleFjTuFk|0JOB`v(rT^W(dg zqxvGH1zyQqbz*v)&Raqw4i=BL-K(6PgWKr2 zA^x{iqvLj^>$;C3#Tc#zrD8LWILWXnZZDER0%|PA#dA$J-*yKML5Pa!KPs=oLoC^c zblZ~Dl_0de0}r;2Rua>rBU|p5O3VrRziqOtpvPCNt3^t)536ko_fJMsZiG8;L^#jU zr?#H(Pb1)PVzmYnn%}<&prR>VV2jm1Y4^hAV0iZg&oMR7ipGH*yNd??)>V(lW(CH`&?dGfwzn*=n2T>2->=b{=TE&GeVKfGM+o&31w*aXB$3s&B|Sw1 z&1xvk*wbFU1%OD~>;a;6BUP4yQ@`I7VKFH_D@8)<3qTazM`4;zrXiVT;e@Uf@6aWAK2mpgrh+Lsy*9Ib4 z004G!0RRjD003iXVQyz-Y;R{SZDhP%>2e!S5&upV@34d;7Fe=w*(M2u5Fqd;NhRSb zmn*xHR`wD}D|T101%%=w6tBe7@B+L7zwVxEXC)^dC@3KE>~zo7)A!7LGn!o|>#KB` zUw!>+U;o-SzZv~%U8Ku2DbxAazxL=G?RNBZK97>+GFqoMs&W}!r$yR{-d(4==qAIr zX&SBakLf(xuIFhHCDF&UD6@PWB~_%*MeX(z)x@CFJMHwo{m zR7F`Ct@A3{Bt;eFizu;(=ILyi6iJ0{x&7$6{TN6;p8f2n)Q_8FS4LHl%sxcrZZ*x9 z?Pa$9P}(ZL%;)F`dRAShQT!$?^X13%P5OszR-|#X*sf>P8is)WlqJ_H^KCIpqhGyw z!NWmWR$yes)pmtpbu8`|t4)!ARJikPwb}B3suia+oJSAl=_1)Ks|OK2-Nu;QEMG+z-|Y7X zgHfF4D2Q#TZCbF7K#Co&Op`bM_1`OEwWiOThfxR(&{>&V-Hl@V$Bm#$}0SD16o`~ zWx8BM%dD&(y?YXaN~$U?*7ezovrUo}k`$-h*9@ZC@sc2RthIJ&{)f{>+~pQY1jR^4PJNPm-J)8<8qUOjpgA4l<%C-nc{q5u0c{oh~W zR>TugrB|Sek4cdw7_8UCEMJ#Zvaaxb3F5*MV@EMJpyr6PW$ScqnoVyvm}KH%JWba* zRvr|YFRN_hV1B#ZZ1SQqYzROLGzKD0mJwF7$fny0YhG?=*R<1Z}!EM+3(J{g`%0^=sS$qTTZnauYRTOjRRbwFH# z;YUev9{nWGA1NZkPN43d_0Iyk3rMHCzudzma&KR!($7M%nPyLal;1uoE0PCK&aoAL zO=N!5iWOFno_v&^pNl8gC-%!iZjbi!C~!^3t>|0%RHI;^f>7U_5y&7@^(3+m2cX}&W zQGhb)nq6J9-j+5=eho2EJ*E9u}C<8Of_%^p{@u+b;UPgT8m_utsq`dRUk`>jVrC~7~tKVXAl_2yY}wa&{5y<4RvO|D~tY^xl-6J{m^ zSpq|aE;CE3XkwPzd1}UB6^ZFKTUN?2(OV^2qzQJM*E1kd``nmIS%dUG2azvyi&pV* ziJ|8ZgJWfBLZ^;q>+Nl=8Fy|hv6N2hReD=JpJ!Evn0a~aC@iRsZj|}jDuy(Z=`AY` z&%SyACNt>udSOh4AY1P6y6#poq~6fWEIIu+pDAlfF z&?$JNsNRnC_a-HxBNU75YOClZ-_Soy$Q?V4C4QH*Hg7?ntCXzTW|fa5aZL^^rRPV4&SyM#s zu?5niKznL$mYqFKqVDhUPn+41uE{e1@+`3LnFI4zR7GJjYgix2d|rzA{^w<~n$D9y z$HwGPf>u_l*g||_($-=}%#&jNmYo8zM*&re9g|e)v0|nP`7^i;UWt4mtCFj=d|jlN z*loGo9cw;FL*Vtjg?LV>?+lGO!)`c^rl8#$&>cx1W=0s+7Om{`N-Nx0G|{=NTLiO~ zUtz}@r1idcYKwtNMrS`tuSle}$s()A-6*6R6%xqjuyyvU$AMV zK)>1VO#-(+LAH(w#Uzx25Tv7~%=7ibN-I}bxN4_$(R?OS2Dp|bdt5{=V=QwSQbto| zQ1L>_rXhzBAz5JI83|c}gd9@_6k4Yg2`MiPWG9cAsf;1|46gwCG8(;|)-fg8tRp*R(azRU!`N2&{Mzz&vA~ zsXXfjp<)U6RM)^3&Y#58m0B@3fXw?>*&mf*W$h=HJWHNk%svF%QsiT)%*DDSP~RL~ zYtT8ZZtN_DfLNWEN;%)7n@5-$pJ+2^ve=_I>9~YemaM;E zEt+nTUa6n~enKX(#wcjkJonU9<054nh{6^{F20-+{RQ9nh+Ww2^kSLBN$@02YTSFQ zcXhu#wwqd%dR7yx8^#7MXtoOS>*_tGMRFySr&S2;V%J)J$$by?o)RSb9z}6Xn~Q## zUPjM&pXoAg4GM?&Fu(q_dfg+{`<8<0yguIxKW)I%ni-&rOBAb^&TMg2MvtREeL@lc zanZY^zoRMszZZQ1GzsmSq*!BKOr`!M14Z&5RASk})k-so@idlE^FQydvr?P*BFn{6 zwDr03vJl2VSDrYskBS_{v5rVX18+`{qDoaU1N9_IaBMR5kuP3zA*6!cu5j+aYC&ShZ zdDX0@VnP>M_>r<;cBnN#(XU0t(UlE3S%|?X^FLW0i#Br{f%hak-jcn*U^hXw7{lPc zhW7@({S$&~ZfP3|(FMX25n+56cb+BH4|KUwhu{6c>_lrlFOI4fHVSlL^AQ*xqx|99 z6=dtf7UiBq>;#FAxQKAKexP=nA0nmACQ1Q&YMO2m1NyPav5!nwDBp_frY;>hkxon9lmubIq zWzhIUj^29(mYfMxMS9d3I-uXWwK&xfTMd7t|DWdvn=9cfttf>o)LGT{ofXN zk^EL8n;LUJogZ+QFED&mFuYSq2CL&n#`Ndxs&S|^24rpBhj!iT&Vy$OIx+t}e2HS@ zQzjb?ex71e@~@wfD^*8mYe)wU(y_s54Dhc2*q`g=Ze-RuNk=@}JnYVP4Xx#avMJ;b zH~d?7nYmF!;%Z8tOQvAo2UX*JD-$!bY*UZgfMbt@i<}nCuw#SA&P3nL1af|Q&QvU{ zcXPJh>)ot-M`OsnGWrWA2r2^OJte`XlaH$t>Z5#k#{sSDWK;9#^lVpTrJJL*C`e+I z`HJ>yS;Nxxur&FEbszH*N@r;Ao<~okw=2pD;4&d`5otQdY+h3ol_#66=rSXZgsawy zgZr28D8U7Z&|7-rDFbD#N444(+t&x>Z zsw{KCDJa;uKd60HYD|gn9OgAgEjRzA6FnzREBdiN+pno3@5tEJ!|$-TJiD)?VNOYK zdz3>StsMjPFge$0epKHLpj=U?tT@uOeTC3g)isV1t`o6tXz>D~iA{IT?yDaqWj0f* zfJ!QoTqNRxo}~w@S88R@SB?4hrY^OeUe_xKwEdh!*r&b@YuTH1JIES-_q*EB!?A6y z@ZIm~9Ac}E5RurhZA6YfyEXgH*6g+i-93S!Y(@VtH&Jo(>muJ?U5jcXlCIn?$iu>n zPHB$F9KkB16rNX^Q|0+p2*IQkLJnkThAsb3<=@xpD;LF`M$g1OO^VodNx4Srns>)8 zS#8e$r2dL-&y|ID==H3b4!f3=1{J~4A=)zK zR#lvcN`9UoUokDyT9A#o7)85?m?$%=x}oGO%WU$MVY@#pQ`coUo28q|ooOZCg}7(S z3~+9+m}l5J%~|7Hm2y3M~6O=4y*uakQ2- zDk=Ha3{Qh=dIZa|Mm?|*t6f%IGCqtc8^!fr^?V-_GsU5t4v z9qiw;gKCBevenSL%5!2y-xGa6Lw3NlU##b3weS0?Buo0#@LFdVJ|~{Mrhy<^g7+>n zMje&O)^g%yiiNsfCB+Bj8F87*Dwp8;D*2G=MU-7cB}#SOuXc;1VA7UkBF#vzQ*Scu zBu{tE6``39PN^nH$FAvi#%33L0XWuE>p6!ivo0+TsmQ4PmS=!f%kxMx^+Zh!?MR!l zQ&PrzMnD}w96Pdji+;CF7TLajuqNp75}Hh(jmXg~%Qsw(f%@!Z7A7&JlW5ol`>@!` zuzTyAr{kTW`SmY5uhx{D2+!S5R2^1g<66@j&V#eGqVflO=h4E=zSQo0H{u3*SfuNZ z%q5gyf)*~3W83k&)wJo(gr+51O%x;y->@~C$nNH+=&&cMp*2#5%DSDeGu-W|2PWC! zeIo?Sy$G(gXFqvTqkQO?*v3{VP*8I8!%e)W-i*3|&P;-2PuHXyDoy|?7=rr%NM}x7 z(fDS>h)g8pq-HkqeApx)w0(9O=wt(+B*hJSp~D9xq392SPyGS1B_wrUE~rVW#sjUR z@U(seXDGA;gjHyRy9!1NJ1@Ihuy*sI$8q@Y-M)N&QX$S}QN zPo&$GiwBQz1mOvvqI|@f>XXZu!Y{SlM@eWx%XGjD%|0~WABwm$TuUVvi?euXIh|Gi zmT;FFZ)bvh^)_!p!^s{Lat!qWDKWsK@(5V zCc4h1^rmV9|1#+|gxdqUZqJO)+j&&Zu)a@TV%23o-1|f!uQ0(m zT;O;4mP|@HJF+B)721DbOv&;AEi+C3SH!Y%eWX#&>*-porTzP#f0Kp!_doxx@f)qs z9=K3vYtbcQpL_`e`5KfR#)3$nqDQx^JL|aqC-~5nzN$gx@QGgqe_v%BUsmBLMsLC` z9ovlN#CGYTqZTg{Nxc$g9F|26yA@j`G)m-3LTpackhRLlO5~6j9Wcwq)toym6LV)N zhpwGekePgbkTt1Np(9wicH&5Rx^#b^3Ii?0l>^Df{A0NjH6C+JTfer4ECxSN{2 zQdbRW@D>HlldR{i_9ypF+taE@x79dI=gI*03}Lx1Nj83F=;pcSCb7vnJ?%=kV+2pWY{Qz=3KZxxK zbwVuq*I)mE{|cz}A=ETXX9BE-iDR-ungKM&N9Qq^RPJCa?^-04Pti=6Qbi52TezZ4B5T4pbSh(nMq98Pu zl(Pg;z-fX{W2a7^>-4&+MxSf^NM{e4IXkt)JZ$&f)CbuBkmWl$6}^`b6s3`^2POXb z`U+a&HD}3ooF@8y6Ot#4|Kijv+}%3eg*|LUIO+_`RT7gT#fI^B-Nt%B zjUoE?1&zfxXwn(Ro#<_qux`s<7kgp@&X3&WYOyY<|4_FKF#S=Zss*hSvVVm&OnWM; z1SG5#RFFwN+)wERo%~SBQf>Z}gk~M1$iO_Br`kktxU<-GX3?HexBde@60NW9_~8W- z(5~~#*8Xs`K6!hrl0DlH-%$M+)G1U8GTqp2K zw#2JM#9cb)80b%8et$w4|L4^&@K^U(|M~pQn^$j8(laGLdHU|@S19RI31ubtEgeT{ zjCVBIcbojp(>E{i_rNsq;^j|XpZ;5B(T-*IgskH3ZQGQ@n`wx;xhg`>{BS;7G4AXnSGv*G#itD zpLoX%O`>};*T)(B^Mui(*H7R5>`Ba%v7VC`A^IgY>NWNnM%F}U5A+>J@&mg{?pR<2 zPoKau7uAWV&|Q&J9+>d5GT$YkiBop@! z7UYU?ud10iDZ=eh+yJa{I?O_QnU|+dZ|VzFaoXvm%*7V5*2)H)OFFcul@CGZMJELZ z4?H!x;~?r=L~bS#-y+$aTvAQ-^E|qjWu%Nv0(F|}In7P#%^|n^vQ{t{jJSRI7TP{Q zfr7Dxq5!BfgsvI_`L>5m)rWoj<|e>7{dsZmL+q$au{)K_FJWe|wr3Eqbp{CXRa#4e z-~l#E+X-h^wT*TipW7@3dl3u&Eb`nri%hP}Yg&9;l9Y8#U3a3kLp<+^sbixU`;S*b zYR3CTcSI6ZD+`q0WQ87mHe!@i4J)Qet7wR5dl-k2u{sR?mv|qmjn|r0yR??MNBPQ1 z3v?t6922gV^hd!zef^@dwi&ZzKb+nyEW z&#mY+Wgpd#hu$h>yI#6erFKqM=3wZmb4zQ2+R!zmU`Na17W|PkA1YAJSTi2Gv2VcY zujE3SdQvX$4hd&5JESZn@^x`7Z5CS}kEGg-F6%s`KlBPleXn3FOpT#~IRZd|g4+v4 z0Z^de9tNWr^##Q^m^%a1ur}PXH`2Uq((aEv_S_p9ZrlqWb#LglH+0(T#e2Ds?~}B> zqR{yVvAbsyosy51Jcc4b_-FW94@Yj72e!)-8y~l1d~Oq;jlHUS1|SqP6vL0hojf)dIkM6o*Zc~baDVHD2BmQ3{XKa4o5LoC{72#C{70o zMfhBtVlHH=Ls0-!Q1pZK9e}!YW)!XwYb#b0Rx$U*LR(QTRM&wTG<6&bZ>=TxL}Xs( zboI8$aF9PAzkc=RUF^}|!0g9f@Ja#H>1yvxcXjBptb^JVn+<#-FDBom(fPd{IKK1> zCSJkFuQBm!oc8Sg8ix)RpbAAWiwCHn7=`y@q3{Hb2}LCrDE zcUU7~uU>HGFIRWy6)4(d=up}uP(g7PI@bVIbKMOVvH%qn;hU^m-((Xz*JoDfsr+b@ zG+myn5H&cYic#of z15{B>uwF%=f}$TPL-I8~ywZg59{L)$K;#?S_@>7f<vyuZ8>WV!yb1htz)>Wp!|wPz=Bv_gwP{=zfwa)#?l(mvUhw>A@%qI4!JV<0H5B0 zUO3-d-*5+J^c?RjzKuAatBX-7O^5F*!Mv;cEbIK~^mKgb6-@ksGq2#x=Plhn^A@fg zEDHdtP=v}|0#ztNHA(^%6lcNv381o{y5a1p+jrNyYu9@c*Vkg~FV4iS#W;Kx#%dNO z!9xJ3GlVlcg1$e3;iXq_dil9A_Ussg`8PlnieR<}(Er^`hpLJM>dds!6npJ~<7KFG zCed7eZ0_&x)I#t!=QS%eoXUKY#Otdgz-N2Ny72jhM8n)N`QX}kLEeE9R1ja zdp)wF2X>q$+%wJJ70#o*qgtgrSJ$A}R&0W}z8InQM2k8fQQ((EIy3jp2zzhexs6ev zh!iaS(caOnqZweJ=0%EQxx9gsjM*zQHF?G=(2tO)ZBhqNZFA;Q|K>P0loBmXcd&wm z1jJ266=LD%$1VuzC8h^24>`%eF^W0BUhOmOtyXj6Pp2=AOh|(c`Cd7lO)9QWudHwS%jM@by!k#NC{eP}y3Wm2zi$ znH{)?rx9#LuJxVYck&%^Sp9Q{pSPU<^{kfo5$|GkYp!a#wp+(%-hQ5Rhh9NXR6VX7 zy!HSUA`bRt5~%Xfg>R*vt04`XweJnRc{v?kdJ`q4BYz7X13=YG2Ahrmb>lPc7+f_k z+jAeCdlRRUIoYy4%E|cBE138NXI{Z+*G$YLm_q?nPz1*n2vng6mKgw5D;%r@1Jrd+ zILmVyd#MkNm#yLr9qv#H(XISpVaz3&_F$Hrzm^mVQ_(#L!z$t?B}If z1^Du%(_mNVy}L9d)YKD{NvRi44w*Fjr`;&=gZJNkVB5XhEJ9uh-3XMHvQUO zYV($vxa7~(Twb^M>eWvvNje6sEiW~!n8g;J{z4MmYNM^)Sl#*xcijnU^;dJU3Y|w^ zgaA%2!BA-?#QwBqZ>`>t>c#pncDu?yP!7_$Z`Y%LwDRhRc&v*%RLvf{p#IM2_sNO8 zl+|z#5Og6+^FUrA>*%)MQPa-|N-oq=Z_btv&h5#B2gMdhY>6uMx`XczzPVU*@t+5} z-Y5JpS2osWpa;o~KDC|e3h2NgKTUG1&M2)@8Tcx}*2e#M2Pi#dO_6N#WN*UYNSc znp4^B`%Bw=_ELXCXK>OVmpag)4Wx`)!g`1Bit9N}WvcP;8g!0&=O%JGY;XZq?Xs4~~q-Wz;_PPjjS$L4WT^S>duR z8sp;-T|cd*lba=1C!$*Z*}&S-Mk|&U_`@9}_4?pI?a9xkgkmqW^~{{(r@FR7y>-yZe7gW|`y*;M&Qn)i5W?kATC%*#7? zoTlyQ&-y$`o$K93@4o1?@2$VfZ%yYN|DYV&=W**J7U%jUSL{DXFT3+Wv~J?-qj%@3 zgMZfN6Fd7RW;hsLI^Lsm`3F?r@Iag&Sh~H3A!|;~!`0P-KiTi|ymQ<>3VD#caVT>y z`xhY1tY(}_X&2#e!;0%F!23~!>(V@_X@^-fz9UWg{NEsR8WL_ z9(&63*zX1hHUKIp!qcJv$|wedU=#oq6vJQ-H$Vl&Bpk&=Pz(pbC;%!b!m}v=s!#+6 zJpd{w!adRe6%^qfX@Clf@UX>Dg)K&d;B5v_K@q+p02LJBD*{kKF%I6T02LJB5nX@^ zif|V@Kn2BV@MZ_7pg0R()HAiH;rXBd6%@hex&f-9Hr?>>Q&)wb!lT;&6%^sALjV;N z;VBCM6%@l@egRNH5uQ>9P(cxV7LY&%MetcbfNB)M1P)LY3=5ymiJH#vY~it!Ej-d$ zaeaC}!5(u{8hhaV?gZJYqY8Z-k09%)M%}<05(&~nH3;n$AY0BPj?5(bN#mn_=o|vl z>uu;2qXg;pc4&HAf8Cm0uyO}&MXnEi$U%b3=K9y#{a=pVppR-PFD+nUGN)vEs8?Sp zOi|QtAASo@^M_sZ79MtlrcElMMQ<-^-5Uh^af-}ob2Ev)z)XCndm~?-?Gj2yfb^*Q zEOcc6>7%;uO_3JWz(*BIdVp+sR2({2fOJUDCdr)Y(=@ibp|430q&M<@;N7nT>7%;u zD}5H#$U}AS2YM~4Qx8=zD*&X2>fUcuTU0#{Rp{Nd1nHp~1@~&?_i7xBYV4y5eYJ=n z-EGi!wn2Rt4DS6Zq-ug7z20_%d)poOs6u-MNDo!8_y(khD)b2#f^?R{Bo!}BdCIGai8W&|W~ zCF8)}^Hit1QQ%|u1ljUXg%S%OJygLP4v;>o;9iZrUIoAOOpqR`dq1~gQJs3I?tK-u zLPd~1s^Gbr_;Ym@%6$Rp?$NH@Egk3!8<$WheC;qk`jib%+`mN z`0+?x+bA_!=c;Nwte^^w6Q1uxt395ZE!E|E{3$w#9!hG^L;6X%DwG)XkS?=|Rb7dr z$Aa0ttMu?V%Y2Kw+nS@q5x+8b!VFVfi@B{Ny-Wh_lve&x6&&fT3H^8z^hdlX(QO{j;p_#}i;qp1Ki-4QJodxm@7yr~Hb`-P z;5xX(Tn_t`e+69tcdO7G2&#w1ZiSb#rRFrbn>9q5(d?<>0jiRE8Mev0Ag; zE^ve94h!-ttntonaLV{hD}L9ugJ&7Gc)PaR&a<4iJYrm{@(1+)MDmZHZ8pz-`@2pG zM8pQRgvmy`>-VuzcF>`)pt;=n{c-c=y#!^)(Tq1+5<9mw(<)4T zE}8&(3xH#&Qp;gvwy782PDbpkTPQFy_+}>%R&<9{$ zQ1?$m6+l3GsLn#oZ$SE}f_ru5tEIt)2OvFEyykZRm+S}90zrDHg8d7C z^iU0hb;+TxO9uNF0O_L&*1Ly}={W54ty(%ZTim;6lDM_HR$AqOk{HUCl6QWUR_2It z6I!^kEzn}*JbHx7+uy%@`pf4}*ab?Ajgynr>nidVUb*+en%e79bS~(vyj4RtRfB7- zVO^TMcR!2CXQ;xxVk4FQwC{!fPfDgBOMBUT)6tGxNhW*Ew3;X}apioD5~y`HF$rBx zKzbY}^eIR{x|HEM6-EbDF=gK0;33DC+433Dh@A~3(y4|gdPxWKGJ-|@W}O>n-~Wgv z^gCOJb1JQxq|(zpA${)FnKlxMKOH0c=>27xpDU<1-ab?^70EIkiARKd19AbnK91Du>WTf^G&W1Nz{+t?w;SDOitZ2+xV zb5@&oXh45shUI)>cGKuisv2l^CaXiVATcg zn0I@QqgY)aawh2e(b3MnOxDZ~S5(6nmwZvv`n8z&j!f^?d2LPYPrPqtde-QPJxknN zN`h=U+Vvw>S~lAqDMRs&@)@>TKeW9x&z;eMBoX0cVA|@Xe(7&-e4EmWS$)#yKht@g zfd@w*0qMzt;JgMvdZ>oM=Hk#d7w`R`zC|_gQ3Vfh=m@)k)dRDp5dlv^(W@3^5esj z%Sx??6xfFu&?L#(%#vvYf#&aMbg>sd~kmuPTtc2Y&VR z{Z~(4{`6N*fBO9W+vjh7{rt@dKAzOYMK9QC1;|z%Rj_meq=zcl+Y3l%&P-Y&y$x~D zWAeQyK5*YD1qLr35P3W}jvi2IMFl&6exp+l)Ej(tTS@uS9C)c~8>iFp6wfqq16>fs z=CMk5!@xYDpzp7WjE|SwzWxMY;B#_gg9H%Xyn6LcYW?ihFQ2P7@9ZIJ%V0iBoX zv&});uzhbU6GfR_aQGqoH-dIpQXIl`OTOR8!7%k?eN&VsL9^}Gwr!i!cK5W6Y1_7q zY1_7K8`HLJ+xD6H@4Dx#b8kK5Q>?70$jIEgvMP6|UsfP{G$kH+9TLVqv~L=2%o3`` zbBZ@-R1gDQ>gY*vBlSdHiH%?=i_v)}=eV739*ITi|H>R$q;NV%+&=B1Wv3XxIXk4F z%f@@t8`0&)k*PjTu2dQJK+pEBPN%j` zJR+N9+h%tvX$0C6HXX^=z0I67VhQ?n6nFfbED0x#B#V@fV4fCaP@Z!?fVy<}L)PWb z)4p9Lb9u|7vnuc?FNJbE|B@wRTp0w5l_(12%ZTQsW3hKNf9k?NK;y{+H+g_@=C|)I zoBpLXU#Zw{cuvV^jVbN}t#1JfHKvxD-}NUQog21ErO!I&F=^Y>;?`H%I&+biS8UT( z9V~2jG!ZQ;UvzYc75ns?x38W#uUlWZ9|%{#UqA1woHJ$Omh%fR*$2e!6zE~(_j!-# z`TweBZgDx}nTGOfcK(%EeHV$b_dzBTMHVRYp~SWr8g(S#FDyi3 zfZP%KvVSxl-_36oj>>WF&lPJT%c;aqh{l zxH)34f#v=@59p;3mh6s(LMpx?w>^w{lgS%@68Gf2h`7rd&`k)>wXOr zv_dQ3cS~y@IQCy?%X@b*8mnoVW-hIu zhU{^d7a3%oo7z+AiSfuQs~=xliMW!ODs!t}x8f^7@ePgXI)AJ-7fekQ2hli7h!4vb zov2wPZ>^lMC2Yd5+zri!AU;f5W27Xv%3$7V(cc-t4-2-nO~3V3EIyNI*)1T(dhEVG zXvJ&4G<-6Y)kz>G#YYX6db(eKb+ReEZ5L*y>R^E6h4=xjloLVo zwm=Bjwg+sk{v|SC9S#4$oG%OJFY&i~qWuToj*B>NrNC6b|6vEvg3Wa|_V0!+at}|q zHP85Rrl=i`cFNj-m3_;Ow!#MNXoP3-_t-4VnP$K2MqG08VE$CK8fN@aO~ZAo(dD$N zd7Q22x-k*75_D3DtJhY#j)lCqIgqxtsobxsT+_r^`t5jv5O)Aui<_6ScSOU&bV*x? zLOuozuo!zDNI=E;4%IRQNfH>xQg#mv}{wl&1l_1{aclGzT+8O6aqbm z%UQ)eHcq?5cDuZICn>>wE|hhjU6@!zK!#h+ftfzkn}VPvIhBEhnAua(4_PCOg*3yfnDhwOb>6Capnd{ z4^P1?7sBtGM);E}f2NWKu!IzZe*?(Pt6Ed!VXa{uB}=AZlatk9SS0}CfRRA~*7H`& zYbgQD;HhjABwG`)v_lEB1ZB_vnYohe*ICIBg7E0d?WEieVK~iO@kp6S!QzD91NwF% zv=;YG+UTbLrGf7M`wo&37;Cns3lXPmifZ~shzaxO=bjiaWzTcxb_zPJ^3s$Hq=ufu ziENj*HQ$&f95Ty&XAXn}C5sPuFBeo0z7EJgx3Td6+LEUllBaM_!tNjAc zz{Bxm89oDR`b4RPO8sm1CuW90nb6;z-PA7vDHPiWPrrMe`Z~$_Ucq{`D%EMsy6sQr zSSWh#jk_35QX{1N*DzIUbgw>zO=01E4q{1)#HBTYEw6nl;@E@m6;mk1mpAn zi}s0vD!?NYc$FT&E1c)(bY^{RQ|hwRw3gO|hM0i^y>_4%cv|eUQY)(}a^_~Y(6nH0 zy^z<^0hozg%f!*UR_~5Ayv`bA5;HhAU9{HPG!@h60L&H}BZAbKq=Rr-`K{%_fh>vw zmZ(TrjuHI86|!(vT0TsmwDO{GD~#L|F2+JDsRuDLe;{Q3@DzfV+2_ae=%8l#3`JV4 ze$vLSc4cKz$M<`z4nETcRFXg|BLS(2p`JbeO&0~TWE{YGs30BXU;hPL{`9Uwui1S7 zFU=@|7V0`$cL%E*`ojOkUU$Zn#SU;-uXDPmby$QBqLb!6CS! zL-JATHdjy^l0p)3AQC-(?!4M*oVpHaoi=es>e(qAS!Y)FAMcGyS6DveM*|9F$Iogw za2KB6`n=YKE(};fG5qMw{-i}ksfMzRO+VtTn@*xq?ih35EYsWVG+&lZv`B`Y*n(u0 zEQ`NJ1k3g{66Awk_^Y(dZSRE9_G8?kxwJU#g9kEnX^ULXkB5oHT zXCpfMHXGMm`JYW|dnwV+f;~L)Qd2anp;u`hVa!{sT1p9p^2Q{_WgH?q72e%AuIZGr zyM3Nd>NRxnJhk5(gM_kWQf@H!{BgHdseg{*1=^YK(%8z{7w7KZNBTlcLHQa@GI?Fj z`fk%OJYN1#Gy?tN46(K9lhgH(`1l@Drh1K1gGzD)h^+M&2i);M21ME7id91K)BiG_QGug2E?P1jU~1nTz)Y z(o|f~_=7IMn=pe^{35pNu`8FH>5Pq#f{N859z?%WBIJG$S+=tFJW;cqxGsf`Fu1(x z+D}4TULi>xc~#Dpu#l9^&G)B#0;cq6a$ApF!ma1|2+wO=3;=~*QK4GUt+8pse@!n{ zVCjB`?a&O@Ah&%7PI;@5oWa;B_SZ?MKal~iXu9%7IJIRR(J_w2DUBsmx{q-@8p=MQ zdyw?(yIcvhmR~L<6Zk-ecG&gFWhTOa;0@VwBqTqg`~^&DKyc_UTS>sv!volcLMqrB zEo%ZBz>_F{Kmmji*SVY%|DPFdI{+4`=nNPLlUUMu6hbeQa*-3@=V97e$u@Liexg_K z*n~C3M2WANXiLj)SQZLO$OZR}i=on^ML*72(xp`e0s9!lJbK$IDwlfCo(b@G5!_^|_aA1w-2U%JxwevY8&u*7h0iUOu0eqP0AW z@Vrw6C5^@-#@ny@+SaReuoEW5tGQQ5~$Fg zjKYcKsi1#-X3Zb~JQn7(Nf6XO$@&_kmlgr#ehn!38mt|b;!_Mmb;Oq+1L<*CmvJ%u zi%NmPzsF^b2VoRUEF}i}*TFkFKuEak3gK@wWE9!oSynDed?@CMcKH=1j%nyMfaNg5 zsz83}QwC*hDYpxD3%chkWV1DN2|L8&D_I;u0nUEPI3Wi6nX1 z3QkrE%N76KZBiDb7g522SQ@~0aS`wkXOWc?Jf3MW`q!;MC6|9g_CM|HkW^NIg58?v z8eahbdSnZ>IXfbF!(=Lo{-n zKgPY58vfiZqnIIm)OVe0ZsuzZBkilag&u$6Rl|lHjiVLaafQ=5)`F2VwLZgYWy2BA zRDHUB)EC=h$3tPh|0cCVQ=w7dnUY9-y;XU(Mj7JNNCx3$LJpaTT^3T@-h^sqx(G`q z#6NB2d(_}q(sjWLe08H&Czu=|1o3KgSkcW7-)EcA6kKCv3c3*-o{SkXhMayIa6kD5 z6%>=sX?U&J;77)$MxJFz70!P@FV}^sm433bne?RF}bCTifjb8$|dolunKIR zA}8**BWyU}4Ud@m2MfYOhRle~Np_UN+I5=HZf8r;$|~utAcTPQbL8OFB^=wk_GQ=g z8Jzp9^Gz-nkAOQ0Yx-1{%Uw*p>1D&KrhpBS#kmWpzy=mz1@XIa&0P?;*XZ+Wb4>B07 zk3+&zQl$1ns`n+~kgtnnAT!w|!LE$u*x8!}F9krJNNF%OsUR^|l@KqFs9f{jowW%=eF^L}!kJA;G zdl3ej+s9%X+v{`}EzVRL1rg~w^LXmt9}KD(!6V2)@#WY(RB2zgMja;-b3w|+o(J&N zG>RxWxgWOGockrT20#Z}3>a&h2#G}%uQIz@9F$A1umwfZiLULTXe% zsoao!RW$_{m#}^Gt`^kwr21?FmdKXAWM3jCjIH_9a71Ionxhh*-H~VvuT?Zs1j1zL zJx3Jxwlr5vn(@M5LW1{7)d-QVKsq-qAuZn2iSK=X&t0+&jo6_b2C` zyx}5h2Pa;PJ=rUeidvzyP32aiK_n?Ca(f09>0kUb)@tZwRP{+}u1Fn+#;hbeJ5>_J zRIWkf^d$@wzo-CDg2G`+(EnCLWg-Acd)i4ljDQ^baJagqq4A;r2(};_Ly}TV2mQFF zgBtN})nt9g%Ea{I)-lTS4tl-%u78=-K)tHGqu<>T>TY;yCnlh=W;du4jZ440Pz z@(Ru-ROq4LZ+H^p3LpjCZ`` z7b`ms?y1HVfdZwJno14gFL|daa*Fz~H6J~l-0L6nalpF``mW%@#MxhGqE(IXzV+e?On#HGFA ze_lzB4Dj@^=We~o;!?;fBZCUj8+$1^i38V*IIEuDjO^zzfx>!}FkFhLeMrD%y__Mn zA?Hf=vV9(fWRaoiuA_n{5`4G0M(eBV^3+C1Y)nBhMKs*2w^GJw04NRNRq2l=8OpeT zkiu&LgXMEiksdpyq-o7$SEa!14-NArKN>pfh+*PKrWbuIy!ssp8pzf&#+!y_@RK-Z zJeVf27GZkaRcKMrv@%W^iWP7TC~BN~c4NC!9rVf+Q5ml$Fwo1|Q#_!*@C05<$Q zb1Al@)nfge5J-Z&X467e0l0Ux95XC9KlU;X347sNuN>zvA&VZ16_0~l?fV&eqIY8{ zq9KWWUnc;2gHn|}qhC!qSWAPl{jns;%@;BGl6BYowR-Gv0SGK};k&UnFthy?7_lei zI`{W=qGt4`eu5xwkeoU?xcVzFYR&nk>tOj4?~$--Rac^p$if>bYZ=0ScuMCZ05(R> zg780!KG4xWs(C~M{EuXEWBi-rHCF%V7~DRfG0}(xGX^zbF5Njj3>?BX38vten!WU^Y@6L!Ug>|khhIoAv-dL@e=UVJ34 zr7OPLFZTjBsJ6~HZA+1^=J^+3y*Cm+3H~giGk6`}-1S0p3 zLCS!__3G(Hes*K>6T5TV2UQ-9c7N?gxUO%4b|FVWR>=5krm3BMh`|$o_ft+r-wfNp zb>W$AZF;b&TIj$b>Vh1-(WHn!-#>O(=EfPVXB;viU{K$-0_5c)dUD7=?L9pfwpY9r z8?hxPF*x_L3dhm_uv{#W+zU$U5oF?CaFqJNle`Y`V^2Uc2l%i4oxhHrKN;BMCAVBH zr)`TiZ|{+Y?5>NUZvhXEOdgzSg}3`n;S^;>EC5V+QspWj0bazeRub!6l<9cKJ>F-@ zc>DqOC^AFIjHnW)HR@_6J)t;}ndp9^q`3psRWpIAI;7` z8?JA2d{Uw`zTTL*aq+;Xhi`S~EFx82F5#-dedm3`@vJUD$0<_D6%?TP_HEdi6j{mf z1Y-p`S%5?NigYI>3LI=UZU#rp;riyVtTgIg`5?7=nXx^E<|@oA+*O}<8EOk;9R!I2 zmusR#GZKl$4RjLpmea#$-f4FdXX776U!DYxCUDCgsgLEtH^HOAlg{FG?&A_+g#i?t z;_%6bTRM*RZmuu$DD@6v(l!e{`o#dp>=1r;0W0bDxGfb%u=1}v`} zDX{59MYmSrpFD2v5QDfea5E9g{f0NBi_(XASOqL#!GgZBxui*?+UVwn-JA9^0~S-?4R=uJ?e1 zYuQ^D63N$MCsr3k8> zP1DWEt*9ba!l^tC*{c&ushrQjsa$ewWw$3cEwQqwuS zHs?*Zx*)r)6AEIZHGaFk>|iW&VaJA;Bq{482<<2z7FBh7(N})W#vM;)++Cucj-G$t!_ojsjeiu`5y0M)d zVS@2j?mXghiaS9PdA!|ynldWxOd%=saG@xp&ji4xm}i=y0{vYAl_wzty0*S7@cL=; z6uDaxdI5qe5p}f{=6`jQOX>RNe88h_?*;Fc?4k;Sj-6dCFEu1w3~?3)Bdole*7<3` z*>RFY1mBxeHM>ITkdK9*l?b!|PuSU56&l2lt3;Am%s%TjW@0v~xEa`$o)(DUfW`KL zg8&Uz=NWJ5wKlojQ^f{P8r5s1!Gb!CX7#b+V1^4fEnk!81yP;mq;^98s=z zrA@kjl>HG8@b4{_38MGPPo-y~?-rkrc-aQXwgrOt$4C3B&<_cjN`&66eg`fOLi+NT zyJ=KK>0cP)QOg{iEvvLs4J|I3-7h_ApI@FozY||{6&8ai;K_mew73`?g2i9qf*WMk zp#jK?e4bX-%=z(ATu-3Si2#u zAGaj+d^g?aP0#xIvb7+a?3GY2!ov09_mw2C0d~Ha&rH=0ud(~X@yUkG3+Vg^wU2ZmL;t= z%hq;>k5!88;ql6?;8ZeW?nchZkaLEK!!Vfew=s5<$eelN`DW>z)#X8|=ElD^CfdGU zS#Szu+#=&Mltv;x{EfeA14bF#R=M=|R&WA2% z7Ta8wZLN`X1x@`yDmn84T2b^AocgxW-r95!IA!CyC<9{$3Z14UL@mYc7erZnd0^x5 zUVysI?T1uq*3FP>^IR_@3M9WVsh!Yy972kYLWaqd2oy&UhV67$l6$7C7A!3)S$wcm z5Lp`;p_?sNJK~l+|Ex9RUtlgmb^WS%n}PeQtj;$Iu}FSh$I}|siQXlYU)^Fa?5ma| zoJ>V{65BO1X%>QR*Zs5Qov`(sFAkT#fh#VIRd5^d183oR%Epl^BTA&7<{GLEF(o=# z{?{K5Kd=B!guh~PFZ^9>t9%I*?}vh_*di7qN~_7l80E^O@5OHyvW?T#j=!*eA9@s*w@?4YWe$TU_-l;3UAnF8vH!p)%Q0v7R1aP^U%b$U}K8 z?1Z;td?fZg^&0b%Hac^O@)jjV?!UiChB|5dwUg$}g;{}y)AK>;v9BkF{Zu#!5ERi!akZkL}O+-yH)F< zS(oyq7F#@eip&0*rvkds6*n^NgU6N8#M^Qv-eJWxl`NZ{h-_zLnt(~N9HmR>A=Y*; zzaMEDrZ;U^*Q#jlxbHVP&fw;V4!xiJpkmg+U@*qmR_KZoQNWO$RQ?V7Io_1|Q_*tX zA1aQkn7zW?{en+|wCtGg9mveMYgguHw)sW?1m78>GbxD>`SO;bEgMv08P6x0!aW+_ zM@^F(URr+ez&)lenuf$Oef4+brB4J=5-xq9GfpExV+PvlH{1A|njpmHz!>DaB@cIT zhLJKsOvrpm!QiSBQ}(3jeoEay|Lf|hnM$_I(RjnD)el^{;cLud7$&1)>R_N17$mZE6Tr#o0t*ix1s*za7RLx}6RBwR zlSU%boR^k?q&AIp%`*<1RajZnW!D+;FufZH=0Xozi$SkaWd4SMd}-o}(K!|iaB(|< zapvb@wUYX`C|2=JdY4VwV_d@OM9_s4yN+sxmF%m(`hds|wGz89P+HcMXC0U%oDZ{Y z(VI&pJqQ??m;QF$2&aA~_8PE2&p=5Za?a3#b_!k+wr3&&cl954g3(ucOL=@J4%R$i zK>uV`xyir1TIDjRzdNbr_ym4Fbh3g=-EHV>^|0%|Grig-P}%t4>xt7A^Y<0a&32D7UDgQ5J20p57m3F{WQZ%?j`NbPjT*TG)WtBC5tQ zfhf2m_|HQkmzG?zs8w#OkTs`qA@XIzg)r!Kkm^!u4onKy%kUh7Wf#wVl+FF|b8vcE zpfGbJZgo1zz_OXkdLUlB02bJcsJj{r+cNo+^t!qSx|hUBQNNuoqBXHjzIyz*%N9w_ zb1{u~w6AA=lMo7ZLU?EHyg&+nKtl=&It+n zy#=>*17C+&6=i(gWQVBmEItCbkjfM4y#45MfH^gVA1R*=7;aDALX0hJBy0NG%32si zVMYZLW!d0{d{faWYIwW)+QlI2OW10)N^@8&KEk6Fm7(R=QipEODI5Pa)oc`U+MEL9 z)2RoU=Q<=HKpYq*5!1R#h20sF=VA(r&^{^3Y zvN#RH(pU>Vu_~ukzZlgX4LyHJ(!37|c393-F^1Y6QF{t%Mqtm!!d>r!l9dSR(oM4S zAcew|h)>~hDwQ?!{pE@7EU$ub(0Vq%fnE4n?a=&qn=DE!7Db63ZQ=#;8m_lCHujaP zYctJg_d{%m!8pQzK97smSJ64``g(tVfT*q^Yds|x{L{^#gDPN;->)-2>_N%l9>%~KWzP{;$1ov@HZ{Z%-&iAzX zz%ku!{HVKWXYApB9PLIk@u0Tta9TW$IkraEAp}mv59{`PuQg0-5qjMn!y$LKz(s98 z&X}pIRGhy@tK7w>ceUxrZysOF=LhR4D&YZ&)2u~euTd?J~^QA)~cSBpr19R7K|fI`fiTRxOQ&Rrc!jYO{ko0_-3tcz*Qpz>5o{ z>)`bZeGT@>@tD7g zA8FI9l})6lc{Ca_CDl;p+pMqK2)+XvoSn*0ak*~2{NzHqMAGM|sCHO4v<845XH98D zXEtjggwe+rjFeb9x(z>dTScz71%A>V_#(QbfcVL8!Eb@SPGwZ3#KVc%taOuu^ocAg z)Ug9NI-0cJC&!yS!irHMVzp+0@%C6am_g4UO$EE@-Xi()0@KOImUnsZx)x(&;c2yw zhq2}fqJF4R`LZK>Ff0Z#(8GuA6&g?L*|Hw!<=I4WUV2+-KqVOkDg5M;C^a5+7*BjI zTjdr_?$n36MT;#)^)>kmbtt;Ki(R~)SNxBPhk_9nD4uD3@2@O3r4p)m;rys4(V8t` zp^vDc&q9pITln6i+>)H`sbUOOJl9bkRwi`XAKt=ri@m(KQ-pTGsS7tV55Z9bXtI8r zK~py`Mz9vVyy%tsPifu=l={XPRE$4R*_e) z-m@MFjpCuCgK~GQ_NF&?F({-)HjiO>n7Dm0{O=iq@6FPa2n+xSf&u`4Ck;SaLP$hb zQN;L{O!zt@>K2Yyh?okqUNL{gToy77io!5cJ(GEIG~Fv!mO^W3|1V;?|$_W!tU3`)7upobIo;+soJE z1lv)ip5-Nr`QObmr8?FG`pXzuiprqQHK?iBW5p+~)WD{>C-}R$9uXiW=g^y{HV|Nm z;%MM2XV?RE#V*77sw>(*^{c3yfBVU&IjmGnp-rJIwJW3BXcg$i=TMNhkVqAUv%xw+ zbi0-HDRd0M!h0BN*GM5C|GpY?DU}~=+BoaNr;^>@2e-l`ywFo-k&M!_rPhA$!Op@9 zwyv;7`B}vK)~?OL6nE^ATGo_9 zE5?&*wb)E^rTl&=7RyzuvvI)_Y-tx{Mg#_8-gE4`aw`fM9o2y^#gdq^7MH1yKuy{( zH5PYY0@RWm!;1`v8&u*D`~_FM{Wk(_6iF@t^Ur(SR!ETM31rb9qjT!@;p!d;in!98 zd}hJZ*a~D2MxA;;(mfl=&>FykjmD74*%dG+(xiFMGGPc~k%(5Uk`RGbC5?DWC<#S3 z5{n#vvp7j8x`#BTg1q?w9l*qsX4AlqK*K>YAer#2L%Q_D*6v71|KKbtjgm$=YZKLN z2&^>*{h=Q3$t7za_|tR66&>;%?2&U?{3b(UNYTmvr3@8Q)J$pQ{38931(;av%9RPj zD-7Sh#3#@bl|OY3$z+4QlLw|b@|L#a+4gX006{t008a(HMKT&(*K7c zm)h#__biA$CE?tuKo;b&P!rSL=x`Y7qD^2+>OTSDGQv?lr2%blZ={(w5a5{4rWyqEDDt4)lssFn3*#~ z?Xykn16_W6!{F&5;hfv0kb{zNA5gbVeqeH~R z1j$)ocq|G$7I{FrcCCB`S@Nw1??3QEH?_4n*F^=N+7D(WG; z5awd))@yXpEv&9?#x=DeMK*hbwX17s38)C(-}(+*b*Jn{px)p@?#jp;@!~VcoZ~kw zR3Z*^D}LeuDCXuAdXS`d#QZIq4dSX)8afo*6Z_O_Xsmq4XdXL=Vo3!Oq*w-uhHn$g zdK^VifzsFc8s(R{AZGs^9g zzZAbjWg&4e+d6U8+FHK)Y1qpu3=(2b8Fe#6Wb80c>#n+%)BVm-GZR^{4_2d-C}Z{N z(an=)sXxnK{?L{nB|E0aDG652T9<&$d@8`%3w8T6?D<9II~&3!pZqEW@2Xe|plpR& z`mUb}KiT`zM7V1mk+xWO{==+H&ckZfB~nrxht{V4`*trqu-8kSLR|xh4vXmoR(&}Z zfIP|({dYrUdKP2e44)URN#t3Yn^%GGhq9^ehLDwr950$amYM91 zqyS%59>|(!I`9ZAM}D1u?d`yvUzp8?)hPJgN$6aJA79x_#=Ui1eEzz%@#x{BiH#(8 z#z#%kH&4~ajK1>AG36l%CXvyYm_?qL1EhlEC;4nAC6hD_B55j3f^l+TTxKtuIx?cj zPUmoEsoJ3R>Z8adZ{>Rx?kfAjs@$eCNff$G_Z+G!*;dQYd#C8 zvtMcmOye7MW=`a44a8TA?(k}uZ_4N0QN+7*;GsmQX^)3UT)jlAWDoKvXoFd4dd7?K zhjxc~w@#|{pj7J%GzyI2Q^@O9!--HG%XVsgET3#aIeSzzelfBaIh%H@yKb>=5t|4P zk3u*DP$sRQfXTCg)XZ~Iq*i_2XHeLKg(xJ>%~^$h!Vlgyp_`Ok)s7Mq!VS8bYl zZe%`snIIm90b`wor2R4?vxxvYwy7130`JD&DGM}M|drl)6S{<>V{0+1Y#i6VKwu0q#ZXbki>2FpZ-ZqJ=gHanzSCWl;zs0+NXN89@{$NdR z+3eDdQB(31K;31qR$ zYKw0CQ3AQuuyl8%ZfxjY)dh7>yPe`{iD@_*L$M_W!6WQ@iJ$^c@5SxTBukA%j$tLp z321-l#;_$<7FboHdEuX@S)KFs`hM8+d2?J9pY>#GQ>>&eq^WRm&>5C+yk+U^L?v(d)TSZvfJXG~Ki8io@+!Sch6)lYgqp zmT9w`j~j9Pj!YQ7(xi(%bjQ?5{FxmXmJP066qJ#s43<#ku>YbLU_PsgWPKi(;rQLD z{+j|lzbQY@IAFE6LMveoYcJC(ox{dLpaDzUp`9!_U6{&IODx=c!e$zf zQjli7lBgDOMNC(_H7arP2k~erEZ0~C3>PIB(ykbhmZS?UPREpJ0FPY7^(zm%=_CHj8+TSF zrN6>iN0O3+V*JO8r&=Pz)?*v-MN;WMf}HDLh{yC$n5WOc&kFN_%402$2r z*L^~HO4-E3zEUuy9~(6OaVX7vHheKf*H$@*nmo(zPiEm1)gmU%uS-{*aa=5bmtPUIlZCD)ZRF%$S~I4Fr<*mN(Fa+vOzN>admaJNV51r9LK=qNNX~tC+y{<9vT$D4Y15I*!Wah7NqRO_R6q%Wpz@1nC z+WmdmK)Gu)YNzu$Wq-`C*faa5pcCZqg&oYE8aE7{zu@H)x7N|t(gtu0KTx5IHSaC9 z%S`(3tzje#t_^NN4^5?pN2v<(Sh5(R_SFR&ukT+rE>Y(yMh}+6eJY>_KsL1+4TcAy z+_$ur-52-G?3gZb%i@S`qW?TG$j5bb)e|g3&=jg5UN>I`S&9SNG3~Jj%{SGaHyDh2 zHqpF94NLwdOCr0=wM^FKf1Ddkp_{M1(?Aw5m4TV_tgLP|kQI7r>%dTIqv&&uM=;%c11dBid*T&sLsh5A zSWt8zwuab3L6Ay;2Qg9S33k&l#$0_?az-PAO`IMY;M;J*88{98lSpMh*``RhFilo3 zLsm}W8ILm#4gi14YCW$+zN{Gz*e>oTq}+aX5e) zaU%LGghQ=#suin%!A<62p~5=V`_@;u{t>IAN-y%Nwfum8ryS4Xs3E6pfpOK@5J$WOIZ1-rFSG;2(Fp^+#_BPztiK0j zjj_y5E(e}SSc(7^+FAt>nG52o9ii)f@$^|=TH?&%mF=~{nD@s?C>g7HK{Rh&;iEAM zx{%*hFm50@-a}P;Wy{Od87IXlMa41rm5pwMvb!Fi{h?~8=~r^w=CgFs9cCZT?X=~U zwmXepM6%;iUg(UxI}NB6y^%0hybXW26&8Ga!JH+noos$6=5bTY7vlH}1eF#1#K~?y zzAe1ONHCpjKwa>LUZ2a8?#|5)HH6*0FJc8265;G0{6lgWyYQ)t51k zY&Z~jnX%ff=e`p_OWD%-x0W=nZ&L`S25h|lCRXBxYs@K51QkC_;tzMYdU0E}cB<@n z;xO-c-dp(CUhs7sHd}Y&h%&^2Ta&xu1_D?~{_)^^`O`ww&2*Q6E=Zzp!GPoMK&=2% z2s16d0%v%dN<#&fuMS{tP&vEoXX-pU-sjL9Oa(PQa?XfphR{q`Jl-J*=Ji~+e!yOs zBFOD%7KM#gp{0FKH&bc;lx#4lQ+}h8=!N*&2$VRpD(J<4tTks8)(Iay zP$)Q5>I*xR94{nX+C6bCFPL*Z1rmz<$sW}_%@~#I{7=%Z-~MutO))P&!{NuV2%$Ft zXLV#0A1AQC$NUd+%}HjH4mt{Rk$ACD_P&RT|$U^xvs9RFr)+~RS^3ASNJlDI*3GlQm)AB&lE zjMXbM&;D^tPpg2eB8i$6otUin>5%N3c_# z|NK#pGR^-QzD6D>c_%^kQo!JnVP_|Ni$g(-?MM#!^aii<86R$_PNcM^tII7Qm%2PJeK?Tjv&^eAh2Dr(!j}Ap-BY{;BCmr6Hm=r_8 z6^I&sl;F1Y4Aqq^qpXqMhzWEQ2R>(!YtM|Qj>L#d&LYzn0Jm6CRaXcs@gKdd&VXpZ zb_IP3t zpl>VxaBKuEaJnubodc%AS3$s_>qh-o@7x|?iPUKeJWEgfFHyN7P2HI0bGyxQ)%8A~ z+-@G6Q=(h(m{>fwBSYxak|1zvaLh`4otc`7z)^8T%2pIgB5IKsAeIM>SQ3{FFFwr~ ziJsz^vF}KA+)tbp#(YihkBpJa+50OE6)4oV-{0$kI+9zTccHFp2yKROvoM<&c$*_~ z|FnLFn|>V;Ac(*pMCFu_X&)R2d8bMTQ&H^&U58e&Ac@#o$=LM4(Uo}?;>mDxJ4|pw z@OgSKWpixgkgbBSfsGig=*=P}*&(aCXhzXF4bc-xXdY>xC083oLU^P6>xOM<#@3e0 zHI}g6i0CsVxDU39`dF`3Y!ICjjvacrzUkamLuvwi!KhtNPyUtg_hUsMUphyjUm>pC z4LJHBdhqt?KC2oFS(AaX)YrKxop3h^ue6qtiF;m$eTESJ5C~RpY;w#M&;oDyb8Es& zv^9JTs7EftPj8+x6O1+ocv*j^6a87g+lzCF2h`ZCEM4Jar0xy8&9{f&nkY7NXCSnF zNZyoV-r54>-Cdsx6(@7N&}PsWZTR>k6TTGUdz@x7pY4<}J9wsZo1)1{ z#M7GefLALZ1DQ+P3(t_QYFzx!tDkBE#V|UWEop)Uw3ps(mD%-n#H|a$PnD;Jc3aSGho>@X#Bq2*pDMEPd{xY zrIyhSGuL@zPaMMZk63&|D4>6`@&0sEokF(bNCK%&W~_BC%XuN%M08lm5pDmy@X1n3#2Y$3JiW; zIZ7yM$hoVa3zMX+9$6|F?|#{^Fx?XF-tQ>SmTeogQq7bIO$l-l!|CD z^HZxQG?wnbT5yYHlXCS<*O919zGSvm6`yW6VD_IgA69oks?1@r3c#-#hLh5%ocO}8! z=VZXgu-L>%bzQ>!7XWEMmcL4iAT1eg#lrHy>1B_g-)3r7g_18<4Dar>holt4g+W4)pTUF^cuL;Q7zeP1^N(@4WNQ=$?CC zFk85!QqhB~4D}xUnca%-xkrj7DrdYHhu^Y!UIa@LIP%OTQZ1)Zmj;2@4lONkvjvfa z{Z&DPKxZ11UFvJ=ldpaM;?Hssd}L?R;o!KMbivVXR+j-`Z=?A#RVH zQ=`XijSG9Ao6XVf+RO0B@YnJ`W z&W`GpgZqB26sxT-YtIuq?pf7Z_t`=a@SE_Dk{UnrnRI(8& z;!-k-7JM}VpISPeMk3Y%ubo5K?R>qpZNT85^#Q4Lm(TlI?FYzxh41B63&(1NHDUZja zc9j>)7`p6ubR6LXCxnl;N|hq_luPgT#bW~U@#*8736WXuCswrJKb{5n6@0Pv5d6D| ztNWvpwF-Q)OI8(q96Tj$9A2%T^PiC8Bh9lQ=ZM-$%QGCZp(0q`|KfDP?YD(e*vm^# zhvF7ea`|y6XppEbK+}&mNA7uQ$AqDU00v?lfm#nQaqYGr zpU%MA>E&Qs<(fz;*CcmHIE^Zow^+o&)-8K4Nr`#gV0Vl>uxtlRf`>e;5j=8537Uk9 zUK)Z;tWjf+DH~7TKgTVAi0_0Et(i#@R2PK$25Zbj7vGSLu zH!~fs?U_5hHjNIN5VU~+yJ;RfZJ#iIQ#~5PiZ&enkzYflDm{(0FEUIwAC&&^Zo6#u zcOu;JHvYeCXjrpN_{b9dMmYn;R{B)%pI|mYui9)0)iAw&W}{J#EQL2}*Km{-MN3pB z+8mlz3EKXWdCpJpP87$esa&7HG(0*IdByh|4duve-hLa+C0m$sdfDb^vmgGvt=Yt_B2IOvOhDg>J=W{c2cIX*XT^@ydDA|B+I2g z?$(;^MRAnKbY?oSR7kMY<2^0b1K#x!c-L4D<-EY%ls6}_G*_d(i&WqX4GeW=2r26q z#iMS<6^qm;(ReO9{7gZ|d*4GHM5#HZ|;=r?8(WjA_z@2UlcDVFT?ph#r!@ZU`4mgeOMGlnj zSvaQ;phEzy@oF9=8di?ls(Z2C?4fCN5oUB<L@!i66V}bz%U&R%lgxVi`0H)FVg&1_9D%1 z)QdDfq8G(-bwn?`UPG+yY_%)f=-&0)byK$Ks5|stGse8EY1aiyZDt-cRkEuqq{$50qX2) zoR_6OJRh!(^5PZmNFDJJ$%|W$p3}jWm>R{BeBldz_)^KetPPVTnlFA?OD*{zTleE` zo#DpR_GQAa)t~gE+a13)$rlk_z_8Ib&q%u*NuTBn*yHra4P7mO-_V=8DSIecB z16xA;ilV0vs^qAStK)qG)~e*Deg73Sik=D%*A4`qQ$3vS+3BEwn-}jSRZlHb^m!oS ziBGiA3003N!6pSjuoB|uTruqR5_wu&a1)wpNGqORU?DxX{ zgbt7qf`d};PMR%1EA)3NCXg}2)di_l_vMx&q4(sD>}=7=70AFsUc(&g(vddqa(#7Y z_&oj2LNVe94K6?T_|wWcyu%d(T9Fuzx>6J2)m>;SD;s6tex?F)af0_EfA!tBekB3y zgQHUL2({BJ>~UKa%_754uNUJJm+&YFxfo-F#0!QFxreRz?ipZ0!dxHh8XNw2hPWQL!aXvL-mPA zg*N$$ukOl{t7$0c=Gmfi^U2k?1T#=c=itjwayoczX%IZU2Gn~E;hv@D?c+W8GqKIQ zHhh7tCocZ^?@HWaJQv7s3=xi=GjySyZB(;QJJ-SC-}bwGb$upCd+~O`C_&wzl`APR zg;Jy*OHaWFmWV{F+!@{ic`00WCU=#Dr_ll{lue^9S*b&BagsL6pU733G-rQ?POQ?a zfgF=l2pEY)na=T%uSs|BD?VrSBdu$xIYL}a zQ%$t|%W{Bs(SL(j-RS_C2OUQ~`s!~N60|)+rTuk;Fv0lBSRJ`8Zd|z3H<&x9-;@l+ zj_Q}buszEjOz89e%BC0})Y=6SJjB0k_$k@bp8yyr`f+Sr7z^yOTN*4N&SWiy2E#2A z`v(lP;HLg|Y`)O6o#Oynot);)->7xmMrtraWA%rfvj(wnr8fz{3i>0QgftC)6G2II!Ufz0r_sKZ`9 zA2>uJ&Lyk4kk*D9vlB|yaU$RH6)TqSSK%Te`ttc@JPQ;F{07dA+-&G`_C#^$;>@YP zeweFD0#n#X-O~w=m*%&9dzHuC;C)$dw#V__2+0!N6AvyT>tDKg>7M2__V-NCqmgq0 z?g}Z0-yr?hQT!}RB3##tc#g|!cpXsRV|QEG!#JyTF=>}yb*Q-L=8vXAS04Q)Di7_a zB602B84EFTxGj#v!G%tP^47jyRn0E1OPM`lsQ(_p24h#;rTzDR4ZY-{b$7m~mH-rv z(=&F^8JiZlW0i}pn>Sbj?-pN-zJsUvIw*Pt5Z!&I)Ih`EqkLV^4q)oD33e(M$>KA= zSqgDF7xg~gzM08Ve@`f8F9=1p^cNnUgu9)u6>k``GoU}YJGu8n3l!y#P&~Vy$S>_; zMc3Ze4a>dv1{o_GYTUhIAt51R>y8MvWHfI8$_x4Yz5WyOSelp2@aOi7^kl;=!Q*9v zrC~a9pnuxCH{VY-kNaLpY1V0qY&=UWIGLDs-W-PQ?QJx8=QaVdya>_1y~J>PQB!~6 zOg!}eOwihOE8^hVb-n=gv%N|wX-r|6uFKBaCb+S65ZVFQ)Eyg>0a@aE(?}L0BHAhskShC%fpt=@wE+mCry;{j=_MiV{#< z%fkjimc2j7Z;D>!Z4h#2s6>*k7iA2sYnJ^2Z`7NhRqNeUfn5q$_Km7{Df`}L^97gj zR~PXVf8WC2IMYAlV4q$yS-Drhp~#arI`N|~-DH1g(%UakHz{lwY^v6{+=2m%T0Nlm zB_4TcxpSK}KZ8%I2pj0S_fQTo#OH+D4=5RmJt#Ls)ZROG=fZ(|?;yy`|P=eJN9b&kWZx~}|lBA1Bt7dEf8HE4xu5o!JvXaT9$cK?D9SKuzsV@V?u{BnZ!vZ2hm&0UH^F63 zO2lCZ5>;)50sYA=yjf33B7yp)6No8zv$J@8zJ7yvk3kLmn<62`6o%7@xqKyWH8MrSi)B@bcFh zY5$6Rm)`R)XzRb~fwpbA3vPQRyyYP;1`xS7k_FZ}JLm1V@C`h)-7BnR3qIjm2>%Vm z5RJ<^Z+%={PF3We!uN}hSMK{1UkqX)_j1HrK0Z>8*mmt3EVmfKMQQC9mPqD*$z^f$ zUMyI3HtNo%ljv(RNq*D4@F&h%_TMAoF^5qL6$gDD`H75`%0crU@V>mL9%*|bZmNaO z(zOl@SX@6cat;(vEbB5qalD*GY}{++?n(1=4v_AdHdy`mf?s^2U+$#88)`~T$`LpH zk6n6B2>;+K&!5}5)jefHnbP!Yt>owO^-fuxO__rhp#;a!U4{N7*ujtTi3iuw@U}I1 z4HV&W&oI8A+IxFqc;zDH=?&js;%_esBF8b=%9$E{Ssy~I#*5W+`irw8Tu)XOUznV) zYGLE*U%TFYL%O^aB8Zy~L6~j*A-&0%;D?^F85$hv{%;p= z)x!B7QLcY>dN`_(2jTEm}7b8di=U}X>gVha!#I3TF`f&zBE$0G6`v0JK=KwhKtg15=?MafGl$r}BZ0~=Rmab2x{&q?KupG;;tuW#ck zI*9C!>0Ib2FTYer7wqmr83Pnv&Ha&gNp7e@g90N;Rh~jEaqI*JT`rWnd{*0Vju;}0hgXgQ9 zr~Wlidc8t!hPSuhfA6L9M=UJT@T6Sq)`%NgyeoJ?PXy(A!zNZ>!S^{*96A zw{{@TBiJ5wm0jOUCa~Y)dN50;AG~Z%Sh-QZ+dby|PsrEMB1A2wbg<$0r@x&Zl;_8eF+^rGa8#^Ts9`?H(ZIxt&!x94U_>>=6)x`# zY~y!k_iTZJM4#Af4c$a@VI9UkK7Ht+)63&nQ{s7#wCxb?Ok4^X zWiMrJEp>A*b7OL8aC9zgbz!|-c~dJz5dT}M_zo*p31|TC1J4ka_o5-e9HOE{mSlnT zCA)EV14hNN{KGHcH`FiUue;~iD-gV1>3d0bx~FHR@9CL6Y}TKgx0-GDywh%ddEPsz zH(UpQK3HGdYz3k3+y?2jlgzx4pEyxCS?q4EuUVjzPOrZVD2=^f5`~=7GN~oAe<-u*qKBlZ{iGpyc=c!4&9^kC#}vw0buN31|eXsCecMT&{5NE9Xgdj zmw`VSSHZaL&(9lAn}939+<0-|T}*ribGD)zKb}P17*B=-HgvX&{TpNt;R?be82ipN z8qX)bL8C@}-fW+@n=R@?&@{svZxWc1Z>jEs#2JRcWVi&L$*F{wZXG|o3F0W6`eABu zl@_jk;8rc1cj3z#6akI~?MA=ZX%_%4=iw*~qA)48|GeIhqCiUZ4?57~pO9+&Joo4Dxy#+N0eTZA)#S15m9B+(P z&ajq4&z$}5qIaU$8NO$G>3r^X&yVY0oMSb5wwL~OkeJ1D{O@P}C`}v>xW5mk^QjYE zIzR4@?;I@FoH%JK*>*1GDX2#kH*a$5EfOfWd3wDl&)4Vm z*1+v)+B;C1&b0?>?~KqVH70ct&7H(g<;i63TT!SVA2go~n*A@&U(L=#Bbv_UsnQvj zL7b$!&X+(!>l*t0Sg+?r?2VrJsm0gooVwjcz2_>8pzu9m`8Q-??jSa|emwFL`Vypp zH>o*?!I(*%1_`){<%*bvzt8;11XKMHI$B@DOg5ji&l{a~udh0?qwYA1WP`*N3}|4vL^zKWMqpdjQ?>X?B9$=`4kaV2sbq+|gfc*tuq-mu=dbdzcyTDvXje7}=@r zecA4V2^vpbh1xdnEyC3M-f3L>8T4(Jbe`Mok&3kKd-K^WiXpNfQi7|(HU_}6j>q}7YeN(*(Lb2jnt`GMi(9(xm~QNoDWe=zZc=ixCgX^9I238!c#0kFq# zXJ_YQ?uKW_f^2OM!NrU|hkV;EMz2xt9;(UfWoTCur-Y|W`iNP96<3gqyci)&PUngB zqL{(VNSoY?5m_!0CMy8VZlmRbI~y52S>n7P9?fBmCkqVw+K+>jaFG(V%s?naMPf}# zxa`=p(wxqdG^2S%8oBusIml7pE9z9Ru-<`jI*0s#$-Gb0;kqf=RAR9er65 zwaz7GayG%B9CBeibPap{m}z*pKN;pq{XH=D-GWzeZah7wQrw?~(QW9AO<=>mULF(T z$i7;c{+A~fPdQ|_fn{PfD|ILO{_<-Mn6+s{ zb>Opc;QD@+IO5Q^pv}G zsl}t zT;nj8yKyJJ+SgG&Wl>VZuI7S>vd^l-z=Sm*OmpF@cf)<>$Jg%c;3*?gj+4rRPi#C2 zeBbgC-~%K*9exsJjaw?-X; zje&V7&OS**8K*Zv23>|h5?|wd{E)~4(L5v-8V2-OGSbJVJx)aQ1}Eg`=1~542Qq!h zG$fJ}M(jID1Lro1pYhfz6ATHiInCToK}DxFJa+nhzRLwi}k0dW-ho z4zr2oI3t3AWP#I23@>H2G27wQ+`FRHis4q17Mv%{V9Z@Y!5Er&1cSZUbxz0y^;Lpy z0sQ2TUj|om*#g@=!}B;}=^ZSXAEyY#+$ z;r4p56C^tr`i>B>laQXq6!34iafDBo(PZq$+xeMo)Zr3!I_JlO##3!S&@ssg?I{`A zyYXf27;k}>^pAFsm?xefGuXtJ&4RO|`ezT1XYYmU=ynH4cY>W@3R{2U@33N<&vud- z?d5D^b{Q!evfQIFH2G*UAA@au?28KJw3RN~zzO292!;`E4=Vwg`Lo>Aqa`7UVj9N7 zWIk%zMRpNT_ONBs=+=8ri|X?PObfb4v6n!{J@2#-s1WOolYKC%hSh#zwO^RXwxu7( z5h-i~#h!yo99pRNDU1D~Dh$A)7CWKr{qaGkWjfI<(a-cEqLK~ya5pS;r2z9z$trMe zuW|lGc5n4Mnoq{0sb7OId=F(k3Z}GY9AG_?EXDn!cg}mqkl(C3uj9Q}%fLn0<2v_S z?iv53x8QvV8c8{-P$+}J?RJTD4WBRl@xc`{l7a8$9{=L!gO)E zt*tysJI$&wIU6K(oKOoPs1?w;p5I49%MOLsyrYFr?V_K_l9}B&BdZ$Cs=@1D6u{Z~ ztN^Z@Q%fuRlS`@9B|x@4Z`D--a21Q%Og-%Mdjc?o{0yB$FNP3CyaeN#lN99&l60Ap zD8aA=6eMEXLnWAOKXTOqDyegq!T72BB^0!fZpnYP6-ok73XJakQmyjlDq`-iIH%_}WTy@fq&8g+YceBgFvUA+kzWppGv z!?wL5NoHEb?7w_2j;VI{n#`W|qmKLbsBRVv1l!Z_J0i=3N)t%50w$Ye6_SV8P|Tsh(ju~9Ce5exI4}~9 zjpnJWmMX(D`SUU+P0z#X-Knq*{rZ!#0rJu`4zQz|*K)0XQ#H3vUuC3Z;gc$ITU4OP zf+j1F+aECDI8O$qAWVbH0F!KGq>RzcV?5Hhylf$vl{v;UE-3z%+QT_V8H|Vk4P|En zF39Bi6RS(4+5n#xr75;p8_<{t^%ZVin52;CK=|y;`Q{r5gQu097D?^(yKvZ# z%jn9hYrQU)RKMgqZ1=K)wr(`rxh-OPR1K36qbB7US$?vmkFa$C7=922yd{NfBdQ#s zm5c1yrjF}KO?MBiYAlc3@?dem62%<2{ZrRfjKuZtrsiPcU#7-^6Eqnjq_~)-EUyMA zxEY?2tc!3>i&i&~oB~>~)8g?bTPR(jE$e+q-oXG_6RWzcw#&%gkY`(#N=l6kGF5Ae zYGqZrXdF!rMBm(fmBL>cv?(mrg*6uodS*z}Go*$hIZM$V3I9+Yi`1LoGfRV$t2eRb z$ulpY3LN~4*bs;$%W6^d`m$S$zmDtOPc@1pRRR0(>J;R>bkrcJVf{5Ia@Jg&Wnfhg+lDSa3DNAS^m1--=#kANJGansDp$?> z6Gf^sW34O^F7J361);jQ7iViw$DX;!E+$XMqy=AB^7iH6w2VX*pXTCC<-YF^4eW9P z39?}EJp(snA@j!><) zL^A3Yf(Lj$)p~ui4s#+$$nzp$|GA}6SZ_+ho|-B zac7WcxOy0ci)l1ZKIFDfX|fR`yQfsxG~jA*-S+bUTTz%kKEIP}s>Y@r(fQ`9x-lhA zkvF})z1>CbbT^8x_GCY155`-4+`UexlNWxxt48(ODyUvt3DxVXpn82JRBx<;>W!69 zy_rRoEW`EYD!4vr_E#Wl>Aa(qt@*iIT1kbHDiPr;?Xwb~SeP+`5k5NG@WY*XviD{V z^WKkl8{gcE`?bg5e(iC%Uw;hl*B^)bjmO}A<8ip(d<^b4AB7v-@d(_@)>3D2xJ;uX z+Fhf?<}24@M5Nl2Z3CcE4F_NL-Cl8@{9=I&PqAg=DU3%0TEACpS#$8oMv(=Yked^_ z@-*44d%zcIEDwrYdJY2(0%%7Q1$mPUJ`0aiur$f=F#1n3z4x$#H=+{>>GeKugc%5J zXNx5t-_N{|gD5MR62_nRo5wD;h_l;7bk>gzDNKe`T-e=BIwk<`n}X5m9nxKc|Fow! zaI1ImC$f{vJHLAw!sKuVZ5v|pEMW}$;jD)sQlGvqF5;SBs znKn@<3 zG4-c2iYe7m`wVRT@DTZwW8_3yHuGK|k2&X3Xm|;CPTCz4`WAxSiGP^;q$BiwbIGP$DOWk3|X0q%k#u3$^IFi4z z07zI>IP*+mY^z-RZgN>!YG@tj35@8G>Gn#?zoz_nzW>sdwihRDTT$iCnm!=3VPkggY=jBD2sZ1fAlo!pF z>G6{u{_1zglx2EURpRteiOXh5Rh#=omZ|C}l?@7~ z=4%MHvUR0xd2Yf^my~fbZ#Iv4clxN?IWBZ3465CPO$%kkmpNM>GR||T zH%}v7hn$D4_ddDbq)coghG$=RAji`D9dkL1P(_h5i@3)mUgg|w(bzzQ3t zpt(7964>d5sf~d?43GiA;p}OIpTY3YxVSA}))zqfZ{^MwRjbR}$~CmjRI@hKLk(BT%-P#_3RSt0-aELaOO=*^a=k>8mbwbmhEhx5Ef-gHZ8>>4xDxXv z;7FA%g|%E-0juho?;+hD53K52p9|#L&dF>k4!fIB#=-2aH#3)EIJH|6WemoqJ%|S3 zOdaaFfylVkDiboFOdubKFJXirmCyX}VN87NsDO!bpD~|$@K#3nw3$6YQAWrf$2ATo zEJJWGz-?btC|0jRa4`=iW4`4f3s2`jQFzp&kQ@hf%*LZVa7tlzt~%YqHd?rY!YTjB zc>ks`ZOr%8LfWF~(ghe}e}Z^Aignm;R<`Is>00t6qf$C;_=ZpMss5ziZ0E_@IE3*{ zX@vXJ=$E_>62YQrB5w(bL-cTAQ|Ck&nl=AXS9GntlKL`dW^q z{`l>8`EPygn{O&QG!})r?u+kzBIzPK+jb2%??-Xmdy>2B`!&wgIo!c^5K!(iJYkfctaln zCTgj*PI?+#T~F{oUoGQ@oM{_M&>PQvbqmNdzo^5Ulz#LtFKKtj4x!Hn!TQ}VS(z1w zAhq*SBLIX_J>=;<8{sMk2SYskIF_1km^Sj)=&mESFK7fM9b=%eBbD^ZW3oA5r%PEm z6vN9wzR?1{{v^OZXZIgIP_183ev&SM-*zg;=eE@utfK2((O9X3lKH+4F7n#6iAX+s z8tYsR)YyX?xQGfSrBq<478ld0xk^P2>9sk$XU0olP7^6WaYQ2`KZ|2OBO^jd z1#vuZxW!Ws+#&b^mAZ&7rA);jR3#+#%#JM{{`;gsTn6=)qK2Z3LbU=4jd47Xi+Ox? z5OMe;7s~8^haAUyOE8i2R$@{IW>!N2>wK~diJa_->F8@pg^BbLxbmpqD=L-Kr_H|B zEG4Bvf}O|d zH%W8|pZQa|a*eh(s9(bZ<_O+q4wn=LRJnjX0VFuH{UVAzkA*hiDzVrrzA~7yrG8jR z@)l`=Rgyc0Su%)OUF?&&&7DCa&$B!w%e!oMtp8?wpryU; zudlt7J%~on<%}MlPW&C}i+`&rt**;B$w{ZXIf=33k+2(=*r9mdx+=RGy*6?G)Sm1T zQ;AhqAQh_GXmpJ3$2)P}$}^Q)^oM8a?{*BR*5FA~=d%sdmAkHo$^(f;v>LWXb~c$` z1)ezQ|2(KMqh!a-Eo%T;c#vV4lr1&DgLx9Fe@0XOU$*s~Z#S4T4Wz2z355k^4@v;N-zP>1y~RdJIY|KwwYR=D+}gQiNr_QvE`q zQ&MR@ey+koXSv8o{!7?Sx^R8ITpd{!iBwo1pT>F}8Go^JloG|{1D4e-?dEyOv!q6t zuISW_5_6q&HB}9}4#mSHSrSrtblTU!!Aw3fBt298i(c>ip>$ipM$2wnUE!}0S5VUKC}K1X_CC;ZUzRW(w82r1u0mX% zFwWyfpzl6$yN{Ymx+eb0kC)7xE}(i8N>SWPF&=a}*ga`K3gtxFOLh&%AcE0#j{0R(%R3?HUI^2ZPF~PG zLev>)b&Gs8th{O5FQZ+8#tRqO-j<>rw6Sfm62@g1Iw!RAQ55ygOclWq1*;*FBf&;< z^gEjK^+Kuh!R48|@bwLK>ReH%1)#DA{>7rNxadyxq%RE=Z0dUsY`7wuJnnQls;luy556+=jo;oQhi9D=oTN!n$l-Z<(eOeime6=L^LHT?8z`n zoFaZ3t5ovvV?M+(#Nf;8$Af&I{{HanC+Cbl(0Va)yI?Qi;}bt5b*dJ^z+&7#G1)&& z7kqvF`kJH#-S0i}xttHsL_-OtdK}{|7ez!eJ7?c$_}Mjl<2L`8Xcn+ITr@AC*gzn+ z@zVxeGC#z>7qE023Y{d=foEeQho?`Zmk{xQ-q+EBTFeg>Djj+;RlJR%{k>Lnb%h7` zozm+yd4?R+4aA^#Jx|9tbB>3XU{!jG5oP-P(K(Y2zu9MS=T7(cy|c6P{n^IGH!utQ zC^rIq2)sB5zUiCN2_NlaVlW-I8{7NJkZR1+g@*pe@;-+V@i)0AuN59aSQuehU~H9ilwK?SUF@4_7TK!cNCbnrzOKj6in*)6C!*YWlr33^wIrg4e430b?S2RC-rX)j@)1$w6vM9N2 zhfD%`gl7DFi`$lmth_@WIzLb{!On6mf+y@kFsc1w8asmrJ1%DckTG_7Ilfqk?Xhe?N4d_WLKgjYvW`&Vch4 zKZ5j+v~$&$?+_Ke$)Dk$D?i-=B{hw(roqc>WDZi-Ri-E@4e^2!gm#SlUG1G9HHS~x z#!x5OwsPd#wzfp7AGQcvjlh_;f6OjSMVVdn#o}C5vrI6HlGDT?t0 zRmb4!VWn3i$j*{c1lRmt?*`CIgDh5%lp{UqpvoQ(3}$*|(_EgbLYd4{tpTgGF7bhC zVOT+~j!8g(?R^<`u9{U6K)4hw{Bs$f1;eX;XpEX8>*@!+T|>X61{)D#xi~)$20Qg` zz7%)E%9eqdS`ZUI8AvNc*B*139tG2#d1t^ybb}EYun!pV20I|vs21DU7UZt3d$BPc zg^oD6mf&~alm%b-;OET!MeA!a_6AMl2Zp>|`E{4(_aBQS52->TbxzmD)B%nyksG8_ zxwz-@iTXrRBhsis*ff%&1$e{X*v_{x<}=i7UVWv|M1{m4`9im$xKy_~^=UWE@;_fx zdKrmaeT$G!G85d^OjGPhl!Sv7W^Y&DYOfp9h06Md9bVO(A!~Ru4Bp;zq%c#%vOYYD zBIWVZM@}%1g%jF9yoeld#=LK`eQnq8cU785fSNs>2S^m6GgfTB6utaI0 z*`huSVd|SF{ zY~+SoW@C}$rn&9imtHC;LQS1=Dwenr4GuSy{-AY*#ky8bwnCsDmSdEED>~VGK{~2f zD0B6SSt_pAR3=w0>yqQMl#|p1n)3}y%!7UrH|Nq+yt}XFiOoatw{K{u<|`V=2l~0v zKPz=Y?**0@{YjA^iNf~2QOTNc<%kA+KyoXs(TTT!9w@kfWx8L`lvT{Pt-rG~PKWlA zYzD#0*5K_r+Ev0TkU^lKWu6-_z5*_RY4K^He0oLa&p%hLl*NM)|C2Er zL{+2a;}>SUP1HD}rM{;>RT_}rvnlyIQgljmwQoXNB750GNf*k?@Od}h6sf%qix}`_ z327jc#F`aU%PaA1k5py$>aHW8w^T)gj%lVz7Ad{9LkWX?kNA=$dVTG+UFRvSJy&qs z_mrC4V*!AVT_D&wqhG!;C6%Jc;p-;RWX>-eq^Rn3i5`bX0mj|cC!>aD^`(XaVoAZ6 z9ahzv)6;*r+JvHFo%LzY!oE=8CuA-4Y0u2MTk^SDeKdiCb3?uzFJuOWwu*4Q&9FxQ zye9v=F8{ni|KI`?2?M+8UF4?3R!22M`)+6;quUIzoJX__J@)R0dViu)PW0sq@2d~c zQTFr7J3kr=sI@wY8J7>QG($YdWEupG+FLVP*i1r4jJ*q-jouqwT)gGK_1bH1yz=fFqc{AEciw)(_g;PXwb7fG@4V@~ zHM;O#dH3Bn-+5Z~q4nk)mD`<}Tg=|~c#JUK%8FM-b^1UT4U8`Z zP+V8QRT}@ky(M!;PJ8Fv?qe0-kQ;S1xfdy;BEzx6p1yMU)o-+)c?~_z$NsV3Qo`Yf zWfcEda4h~x6WKW&w5<4?u%F8|(w;M-Y>~Aqm5K^Gmvc<~`)y^w7_=kFiaa7UQ?x>eU+l7{W?j&yyH zxjCSoK9sguz8TQHBzX5R>|}|=6Z}Of^8%6caJrw7l^LirO@)frUMDYPM#SyR>e917 zNY|Qgy0YEpT`mC=>c7n>;)hkw>>1$8UbfMWJL_k+3U^B7IhD43{X3Ok8H<8k=Bv_K51lpdxO65mN34&Ltic?$V1}Gt8d}kUA78EbynyyTX@o- zCtLhHlRS1B<{}OX_~kYd_#kFqr?8d7eXXzM@g=)VrFJ{YQA=mgZMY?^;bq=*nMNGQ z;IDa%uf(dVx_E+kRb^$kT#3W(UFQ_JMbM#-Wg0SV21CMp-U6=i`$~r&3-%$~ah>-l zFR!BEeaZ_gTVQo@1YyW05)yu_aWwY#2BhTnrvBccJ~Tm50lk)H4^?h7mXTgAPpxPt zc5v1whlxiG#@$;D{$8jZ|3cA>aM>r-}R)@ zfR!jUJ^SxyyyGQ&qTd;t(+&maQtex0-BXb6T)-{rw!XGj+qP}nwvE-cZQHi>wr$(C zZS8e#&c=V2RHbr}RAtU&jy&V^Vlt5BbHk|%6$QJ_>U4wbc4gIBv)N~y=F^+Ahl)8! z$oUt~mA5!8%G5OwF6U=J9%d)ns>an7L*jKne{GQlMH>}3D?kD2wW3apC5%0O*Gc+o z{Fsin*r&}jscuKD>*B~O78bXTEE!)`xRh5KPzh7eev+M^Ee>Tw=|_Nfph6TnLU3^$ zxRq@^QlcwL^krOd%CC=Y_k(c4Ej?}M+(N(Cx`fti$~|NX36Ddo6CQ-aR!h7Ou|Bh- z-5C6GJo`#pSn;9|m7pv2T@Fac@U~;kF^$3;rl!ljIOEsnTAuxFb?2b;?~Js7p^vZ5 zBUht)xZNakT`gMov55Hv`M>kWzX&3P7}!8S1ZF@$82=-GZ0hW6X=ncb1(1hz*BviK z5Pixb{SdWD1J(ip$tx*RCwu;w(dOT+VQmVVj9V0wn0bWZ?^(Ma2EBpHxy=%3Cf3yN zP~FHL?Ua_4ttMp1kkOZj)jSTUnPn7@REn17$zSj+QzubRoA`kLUXn^KdvceaERc#}VRwW~pfOyr2iJIayp@c%kaL*Ng- zo@}s7s!Q^y=&h2iI87Tb1(5a|AW=$&;n$!4XKG39Vvs1#Y5sD02*ZK-x8?&hpcJVRx42YlDq#mJ_U1xEtRfXqN(Q8IQ=eVs^;d-`+fw( zE$~M+H~(iPGR>jt0p^l)C)P=6DTTGdECJ+RI&_Bhmg`Jq9A}dqE>E5r6r29l36atk z975j@x3#e|@pzC}0H zOufGn$VtG}a|LN8@wuwn*c?A-rLh%_P4Y|Hu}DgIU_-?4RJvP@^g63Cg4SRncdn34 zla;YOjC?yoh$~-rh603^!ZL0e=#wNhT3ji={aZPhRMHw zAxAYg!#iWSf{*yHT&jjD^^^wsBmypD_H=iHC@shha3!8}nuL$%8?N?UPAnFO=K}VZ z#?J_*`%~-GOtbjIr^U8?HLWR{68LxNt+~gTc2+y+` z;g~UFj^&+Uabn@;@W|W4x^{Z?G^=uB{j{$3?}Gq(kB2gSX(^ykzAm`5d+!iJJ9Lsp zig)bm*wI#dN?%S{c%_t*u1jYD395=_&^vcy5= z+>nQ3rc5S@e$OkF>Xnh7bF@;L*6=s*?;71xP6Jx=!5zV;qh@k*A7Vu+nrrDSOKCDI zPsWs>^0FqYAD;)c{4}!CI1;h5JUienoydKB0e*H6YE%adNk+xB>V#ns!X?xB6h09e$RW7HW`{sS>y)5`bNcJg&vAdB`H&W~|lgCPkcO&Z3#O|Qy0&PiR ze}=#R-Eh}`dI$9gs$lQ9rS@tV$kd^~RaCRFH`a|$ZlAb&#ciMADBjvXdXhmZ5TC%3 zRfK)H$M)oQ-=>Cx(7JYgu(7`zqNnW+dHf40&omxg3g36tRPolIh;pK9Jc&P()9BH) z%XUC~W_X+6yMW&e-(7HGS$s>pLJ0dU*zp58?Pq5sTC#uN`wV zr~1tbXobK1pz>6&yzxbZvK@f`)^LJd_ z{9z?2y0FR_gBe%qyv+6&DVy4Mw5br;0xYVZEOT8U)3&rjM9xgw=aF|*4XYX`b<3Zz zw4cHmeh}VO)-&NUhP-4jr=Ou=77tZ=X_K&m`YuJy8cNfOv~UUpzArFE@bh0%$DGJ2 z=3mUdcAz;E)9*y3R&+dt%vKn#vMF_VG2PTTs@Q5dI4@P8kKjO-n4*@-CK(MyO(7ta z&8lUXbr5_C^zA%<-|x4^TNkc#y3C$&aQ8c~18{E#FXJVJV~)T<6(+FqH^&|7;^^!jRWLZ5)r6DBW~=ljX$8UG&k<|6767%6Wb#vs zg8O7uVG08J*vKb}?#qE!#A(LC|=hv8Yxl08|pNw4o& zIv3ekKDX%7Dc!E4rk=M-Cm`(OP=E1UNlaRlVDcq^=r>Q~muVxPcwi7`D>swWW!Gi; zcC9k;-xJM*#S*_b(FOx~#J|)wYYOG|O%i3wdJ2#t^x++Im!oVGR))wO zo^_0>x-i*hc0G;*+vb=p+Yf8WZC`12grrWnAe9nB&*si<0=hKqGC#@4SzE!|WycFf zzwNd#Z;5D~iy%X`Nv(zK+Fs#mRjl|DRsgN(Pcv!)Rnm=E+Vt$f@Pf;!Q^+yrut?dO z^$qr%6=;O96u9U;T|e%|6HmgbY*ayM*3D0-^2p95X~p=d!X;Mfl)G%zP!5g8Qxt!r z>uO7aTR!53$$9Y?Pve?vUY;g{j5OCyOXU}5Z-0I+%j(|o`3mu`p7~bMzMonfS58xP zmFW((HdOgPgy-tp0}i}~b~;a7bssh~47bJ_p_vRd`exdi)Jy_JJ5e5wfgEi-+RauQ z*Yx@aySa<-)`r?R$rnz#0yWR7Y8ugeOCg4qn@m0DPtCK{a=2~l9)(*A+58Zo{N6I^!m zI>{&Eaw(N77wb`0$~qk_iigDYcTpZf4d7cofu!*=wNlESb|=?9<7MS>8Sz#c1KGWw zq;y!H-LSCM^~CDH+wkEMCMxSJX$`r3SV^WOAbn zuRYz=Gvj9r(fCck4k5+0wvY>HDg=~zBR-Nu5M3cB6uj94AZKvcnN6Ai^hT2DW<>B2 zBC*((F)8h&Y$xITv7BOFL`` zI=7~v=`_?JexxJP^Q4FCn7+} z@Lh(6^w2c$T7?nAWO}{vc0SC&)Dxlc_(_K_v(}feY<6b+!?;v+DeeDV+A2OVixB?# z^z4#~!;}|^5>`uIq~+|r$#cJeq9QEUTRNZ0slr>jLkfC?jluEu3YFg`^gfF_%`)pA zzr$zu-g35{(F0IfPxGs?SS@dnaM3MTb4EK*4q8cWz6W1$o9wJ?!Jb{iQ3`&l-0&lxg}htXlfvoOOWf6mc1q`hlt zFEc@uRa(y)b41cpwvgj_?-VI%bpkN~tjD6p{t3Gxkwu(ep{mn+X?f4<^?KEI@8yud+NdsTW8;Rj->t%N!f z({vmrYytriF^o}rVpVC6xb}Iv%1H69D_uzw`!1n9znPrZi07?2UnBD;Y~@L1UJO8X zyQEZuT;vaS`vB_zyZPENPWy+7;PQShhmDYM?<3|&K5F4Jf%!*AGZhtq*Av3<#tP_W z8{7gJl&zjS+G*)mMk%h2?g^lA*I!24g+dCZDNaAs@e{h|fqu}te)BXX_bsf8XLVW$ zLRVLYsNyIG(cZYokmo9p5?$W}K(kgnU3ZOA--{YbsPJNwu-==SqVmZj;Rc(o-tEJ5 zcCaT`GbG*{RL*Sjc>!}3?SUtZCP5aw^I7z%=lTVtLVv{gF07@0?!-@d;F3;?kvhDlQfaDFQ6ENB@4^;xHO@5E-AsX}@Tq+V@dHpS^U=nQ2 zyEeeS^ynqIVxXiHm#PBy!2MWmI38KeqN}^VO&h-X10BC&FpECsD~G$;ap`ooD?pLU z9(4D7JH@}U9L^xyts#5J#EX4_WI>Ss21x20n4Wy-4{J?WgD7F-A$bZ}_&2RIi#8QD z>+Z>*u#tRcCi6NT_)2*U z-{>9=2b)0agqBcq~yT z5#e)?M<>WCK1_#$2<;J?S17!cbu`3QE;j^^)ZH3O*i zn1l4Ssz==#*QhPb;d<`RqouL&vL%BaGP3A7E1o1-0MkF;_OWL?dwj<50k}QwJ`4)g z3N8fJ6Pfc9_Qc#Ex8s(tMLyY<=M3e(>h_*Y_?S7|6@Pk=dQ;?_E4`+`k%qsvQAt`T z56ry`-pw@1*F=7@|B$H}0qsCb(q}rHgQ6da9!WCns8M%hW`oD}|*D+1r|!9~lpYh1-KD2<)kHS>0660)PWxxfj-wKIM@>J0Y?ojC3! zsBc(E=aEtXqt?Ko1IJ@19TKl-Yz2=*=mY`DEV31?AUE&N>py@iDo8QK%UmSrfr}XC zZXsfFQH^@+h{hd&;Lly)o{47N-b}MxTx-!=23?0b#^kPlqquJZ@#`)5WAWyL21>-%??;AlNs#(DZ@g!huV#lF<0DG05sk7h8znI2dTn?7Y}VN1-GN>w};W z3C-?bdR|xW>wX%BC~)?ufDq*8oUlwA>RA#V2`|3roIef!NLq_d|A>gh5@aQqG`m$x z-4KHsG(h@?b>NP6gHHg5(nGabRgQhP(1z|>eAP2yc*wG35yZN<2*wIg#g1-zWnb&X zJG1k`eb+<|bMUqWqIYVlOXw6Eq?QL{IMsglhrzBIit7=nSoZNABV?YWKK(?$fQ~6#wtnnNsQHrArv{s8s0lDVPiaE!FpKcqQ*@K;*e3Glmi zkdCl%bwr0LxHD9B#w;=8Qo>^5~;1YnGKc_`g@hYdw zR(Mu#MP2l#{axl1Smn|d>diGmFS*<>oVk~OZI%-qeG9mI`Khf}?iwO0$Rr{0neNQR zQ~FT%$U4#3ZPk_FJX+tgEcvo`S+T3==UDUc;eCCzJ0#nGj*XprCSihdqyN#5S7I|L zx@hAE9x47>$+m~kQ@#Qmy!{jm$u00THbk%(AA~{VwkPmo)SkcS{%7MeZ{~2CBjUsF z-?ssbA7Ak$p}aLDh;~Rxs0i)Le9nK!#mHQ>RF@5WQr2HmxI*1bJQBiq#SS<6Nb#U6 zWETRzaRMhF>GRir8N*5!g2W=0c*=|qnD+ltkL-!tP572{=*GEDW5mZwwN0=NIr*1!+PgkL zLj2=rzFE;W{!RGl>@)s)x#KXqT&VNs@TBlC+rL?_D#4{WRNQ*r1ki(R9J$vn5YD%c zhA1f@c=19mxJcQt-`pDPf02b#YkC5ZfQ#R|VFPv}oDR2&G=v8wsT!5}?GofYcK*%! z-MZTCiHasASs5v_iW#P%EtPu;o=czU4!!13@Iaq9bAS$l&H5NSmNs##ZGqKYcugE& ziMEwOv4z=k(Q=7iBXn#tPeb}`%KwD9QlR2@GxtvJ5g0)qQY@<3#0!tVodAvK2DESh zCp6=+xV(D{MO=VgQ_k4V^zeNY>LsU2$=|o#UqIKymJ@O>C=oGD4=yl4p~Kop2;ns< zgbE19=YJU^H}0b9OL1VQn<$R9$=KMaJp1sFK(>UEC^feJI}c^>amA|OnT;AFTKB3N zT;(LL*UwkF%Jnuj<(dWMT1Lec0JT&{X@f^lif4b}vKW=6!$A~FLjc1UH%lAC8+fW) z+2AY+_OGtcK-THtZnLX%QzOVuR?nAM?BMz;c?`rclm}!F{qWh|DSHepM6YVP59H82g$!-R|EDy_&cP)cEK?BG1>G~jv zt zXXbAIZQRVlS{?yX+S#0NCPtBmuXofop0|*+;Tzf7@!@5^a2@p=o6FlkL>>~WVXpKY z#jyX38HqmPpST%U_eb^_1n&aL?v4=)r>e5Wx#zPFA>L=*D0UVc&A1Hk=i?)UsO z1&V%n8+xxhwoDbSkGOq-316)Y;e0SXodMeuAH`jbfTlX}HDm65SuXPaj53RVmqlQT zYb4^Js?fO5St9H<24bw zW0J79n4aaSUNhG&8X76~l00(we{TElYU_jd2Kg5^CJ5|6jXpnOEb)$lsq!f0t%NQ(=S) zN^z1nde2}96`6@$szcu&@40A_MsRay3=x9f?h5UAy2+z=|lo{g2iKa_I!2iP2cjSoeSC(V08vE6w3d-4y@Yqw$Zyw}c1R>F;? z7XLJ!((J6JtH79O@X*MY;(NMsU?4ZtAo<-jFr^@W#An%%o z>D>&U&s5q=Wy`!HR7IRUjnRM#LYh;cxBmxv&Ow8}uPwz1~FHM&kY@gi`EVt1wy<%XoHr^7TPx_+le z3h~qtI6R^OYHU&N{5u#qnV9!NvsmwQ6X{d6gh$;ziSP1({f!`NkGe@0OAjV@q>*~F}YhLfZb&+m~eY5w_C)*^-)u;#c8Fu;(174zUVc8qr93EK@1J`+^ailOrq+1?h>E-DLIl^okcA^3JH%2S;=t# zxrghH%qNLUzD6bteBZWBTd`~? zL0witdn_*Jn}3#K-SBpLlx5#7zKAORT|H#qb$(LunXhqKSCdUVFJALiwi5NzQngk! zdvh(aO6gjtII2O{FE6BeJ_sjdi>cj23KuOBP$|6Zs7xZ0cTUhL(3dsHs+CL@ugE&m zL6dEfF#8x3Pi&rwVp;c1EB>x2ediRf{^3t%>|%4vFAjZ4tW_GcXduLiB6+E&$^eaOzoU zF`wY6V7n$3+0V(}QSh+-fU1Y;f~T2OpE`Oj1#$~mO6)@o6S-6HuTub;>>ZI&`mcYn zc{wzGFHI-S(@3S&r3Sc_P373MXQJ%gV01oZX(tjCsd?qHaz>I#OO>QUh6`!{B1h8G z{O#-E0ZWJ5mE=M;4gq`l3eP8DYooGd!&m#CYyaPQK6b)vr9uWl@i3b)(t!Qtb(*ZB zqVR}C?n4w4|ENjY7cZzqEO3-5h_swAm{efaz>dArnx!G3^l!v2 zCd;^z=-z~!zG`5~P}XTghd}fpbgr(Th2PhOvxDPo1M!q{wMEO3OvlqJ>KspP=Yjg1 z|Lt7CG&}fxTEGLqk6RW6NbqQVJ=~GwTc0y{qClVy;kh!2uF{&i8g32H6E6ZN#LuiG z0H-q`_}ZlJR)b`&tBm88{SV~DHl-~xZIGv3g&_T17ga+#gJHcQzoWeLdC{Kmms2837R(>u+@U}l`R>=kJ>8Y;bK%Fq8OL0C9@)k;*T2*`2u+SAaX_NQ7x=-OMJW zYSKVQr2~#&2B>1xx7I8@kwu*cUorMyvO<^iNn{DluLvepYtC0e<2za*$gQzx`A14k z7nXKDdn>+om+)+?a!N`Rf3>hN>1=;;W!1zAO=Mv(iqx2zqRlKW_;t@^C-vir^wsJs zFSCzM={MSF63y3Gv`#@pW)E8o5ErMox1=@7y;Vt>7v$7El7!oZ(0T-&Y-+Sqh56G3 z1~GJua|I!#(X36?oZ!yW8>jd6^Q$rh4$*mO?dDC}rV4WBaEKKda+<+t)PLLb`~sdo zsAE>k3wv+z>&|w+s8PS0euYGTPw>nB?YU8Ww3?Xy+IX(TasYn&{S?R(l}VQ7R7L!0d7B$991 z%Q6}r_MzA}kBu6*IjqfnLmcKen5!~8?F0IRzuY2`FmCF@I!640kn(;qk$S6AoQ+*Z zxn1)ISuSv|7! z;b@3L+rI@hrJeaI7&i&lC{)Yc7Q0Kn z0}cH6cbv)~D#1FcYO*^kLH4-#AL=SrSkC^Ja`#4{aR??*5OZYQY3B+O2Nb(`!RS7= z6*NSiDFL{BKN_IQuJXj!n~c0IVZR*k3LNUhiT*Uh*7JYsihIr zJnR>uw1FcR!YrkD#?zt`_D|dnUN@XEhY%fNIXZyj6dyU;IZCJm9`^mS7cKU8^USQ< zxyL#V?CS^J=NW>CJaM)CkXwDV;yHsY_X{s%q?MerOk^JF1-cRmwPlUKH3nkEA~i%B zCCGlRInvI6q1#kka%80Pz&Sc@7FP_+wrWpdq$=pd@p)A48XZTAPf&O3PJp}0jNzMK zBXhRuY56*4g{IaD51ncqone=r;3iDaw3~;YFb6`srR#TImoxk!W;0a0vk<)qewkX z<$pv2Uxh@>VLNi}edIP&hH*Kh)3y{d- z)*NOxA@$pi2XdB?X>6|R-DCBGwl-nSCjPky+SAf{C}u^Elo+t95Uh^DdAe-GA-O2v zAA8z;uYh4u%XG%gI#S%>_qWziMmM3C{{O};Dz>>X#?U;*rT<0nPDq;)i^t-=(*rs) zDYf1)V(oofzOh_PymPpFZ5aR!X9u@!ScQJ739WY#FY-z(xF(-D}|v^BZVxVWXcy#%qfed z+pFlY7gbG*PdBe(G=<-CF7cg94foXMOKzej#_uHI8LzWWSb@O>+^QKsU2qR@#W}%} z<>?z9lL$>#^M=ZU_p)`4h?s7DoMd4nwSX!aN_k}o>7HW`BsjY=+3#|5a_5paDSw?O z|1@jRD0Mol%)GDr3i~$7?GeXYw2Nw}PzA{?M48gm+8cJ-sSv+ta$ajuCnD|^{ktZ~lJ(a0US+$_b*PW+_ zbQyb#neJ>VlyYiIP>Z*yYs@&+Or(I&i24;`-kY+-I6(q^k0t(q1saDs(;M+#tg8v< zE-ss@`zDKJI^Im9^pHC&sD+Vz)A`;xHAWMl>6eL!UqqvvZCk)lDPto0#=QlprSeOj z+`VX;#{U?01&VV*981--?y5McpV^?*RZ9}A`BuRo+dt^>v^QvI|1nFuG6`T#Dg>p_ z8#I#tz}RWVWEN`ul1hSq+{F8DKB@uMnxC>XXH`{$V>_MrMW&{rj#8UBM!Gu3WGluU zJUEdY7`o7xP7mm$$y&)vUedW?of->{y(eZN#$NCzuZEtvmm?=B0vm|pR->$hNRh~M zQDFA--0o7HY(Tc)Q>=JrE$FD=H5nrEf_~;wr3tGckci)JNVYrPu@|V1j44fz} zdc#eOKej-9I_EAwLHIH7924qJD9B#!5Jh!~wNO9_V|9sL1LwbcwrR6Sk-1TsAo67S zup^d1&WoRp%w|*qEFlXgifDERi49+mnBr`dK_Gt70|a-X_Yz8os1<1$%Ki;sV{-9U z@Tnp$jQ~6uX3iQmDlLRh60zoNITpKF1>SIAE9KMJ21s!DL^+8C1irmoN^Ty#7wrQ} zf_z_WA!CLO5I=ur|3$0kVd3TwP30!#I(bZ`aJuHQ+2z{+Lw>R*?n2zD(%hcs=$fVLNe_cT+nuhCsaWv(sFhFIAUHtTX{#pei)dFJ4Z#oQ2*Y^C6QtsZ0Rnd4(Q6aw70hToUqwlB&^t@@imY|*dx?9V)mLA?ssNWw5{Y9BJ2;YA}E?if}{w1E#%!h?42_;isD>Fy#d0Jv+m z8v7{<&6Y9+p1n&|(n-8mQqn2Vz*hNYg#WCXQ!35Q5Y{6oH9HwpZ&{A@oiPPY8;J(0 za8Xurk|mqPf*6(H{1RFo2TQFYZJw|Wh{1oVNC&caf_l`y?B!a+@&(E_W2rHQ0bpW! z=kWsULvZ{Zl;Pnb8NytLK63r(x$}oZ7YB3gkLOYK!KHL&F$D<>MRTb~(~n+k*IJqR zIUdW_gfUh9i(7~!3{&zxI$t+3Y&M-)F4tvkuIw(B zOeJ7px!x4+MrRbUgiy~3dS_&My~HCARP;VLi%Om+a6GvEln)`r$~0w{y!i?#XEOxv3{crlyr#D#$g+wa~!z{|q@TzQzL*f&7D#$UKNaM0OUj{*?kC z1jhi~87Qv*6-+{cJaQNHz;T-5Ft5pZUZW3W-xax-g;0fLQKj_?e~0)rZKyxVB;j$s zDY-=!b>+lCa?OYiWzE>e@AdSL#pkLB+rL?n){Ue2-4ToZ;}%&BBL+25wF=Oe`lOb+ zX-p_gnj*1C@OdDTn~L`9R_hiOEfpDB0tSmBqA=VWNxU^l?*`g@P;5}`vWV_P!tx0R zZrDSU_A&+?G19?W=hDyzIc$_%BD)vw%H*s|R4udK2u*xO``c<#vF7`23BM(V56<}N z)edvRi9KWBOtvevDJX+^j{33&WFs75~zb`a&Isw|? z+qclJu7%M|&-OkceFGyKjavG8lR&YR@Df_MvN<2iAsJ1lLu*M5A4FX+H$ct>)&ld+ zX;h8~%HG-6E!jbA156C+D2Fo?&MT3U5F68@4FeO-eCdRh2n0!(Qj^UFjyYxmNz=qu z_EV6_vQz!YERwC1_wj-E5a&apL-#z2A^olFox+hBxCZ8sN8#Lrl&coo@MU3j-H;sD z5-N0<`*FgFwFSI=2uLV!<~tA_y%O_nVP4#+1-bR-O7ag4?eT1By(nKjd7;m zKAkm3_0y@fH;C~CY?D`2+Z%q@=T??|_tS@UFK@N%tRROj^Tt7!9-BMKXB~3ODPJ2_}5y@(Wt)3 zd(D-Q7Q*;O3Yb*|&V<+1s|VF-l5kAnuMbV_?}NJJZ-;Tai@PUP2(y4Zv=h^v9WO2- zS@DyykjkvdudZu2qqFytywa{3I#es%JEWdhGFhO(E9HjcGFl>f&&|19N+&)W;fd!& zDXC)RA53jblrg4dDO)hN?9AB$tskM)F}xGauSriXf>&v8@ zOSjoI^T#sHoYH?=|N9n`g+uG)Igne(bx}@uZSM2)E~apF4kGT7wf6L~Q28g9#)2ui zB2>8VoD&f-*w;$N#VhkBbLPp`m+8X9m7MZ!O4Y$*E+Xqd>oSjBGjgNU~yIx{5HwogNxr58~|xWp#-H$)S-$rX;Xg|`AnwgKD8 z3+FPP4Yx^U8nU1czx_?V*R@0ux`Z#(9X6S-wXX@&PM59aS57<>@2qtjgBlBE8TFq| z2zB^l9OjHTGG=-g=3sPd2nm}(jP0h#s|muqQJVojhV6>WFd`q{C7rknFvI6HnGW4; zpWydAF5I_SvyrC5)lL~U-X+O_z}Z=il(^7C`hig zUe~&(0Nfk?f;?{A-<3J{S~mWL3lmYM@+T_0`HK?&h_PkZTzk%;X>d8J>pQPr0X~iF z4gNm=U)UDfJ)X)4c4>J&6fr}Z>hnAa#vfH)aj}wCUoj~kC1R^IPt7VQqGbzt;U`V< zKx{PUPpcq{cagp*n0aV*XHJ|J?ky+WZ68&z08$9xqn;n?<2nnGpu{5~S7wXC`(BoE z8N7H?BQif)%~NHPe`tAbu_0z7=|qSfk;0hSVdsbEzcQ7*8cVF#TefV<^`b_4v7)M2N%M0;P0(L`b=P_72W^+loJ7p zv30=G{Wz0l@7UfG+q$u5}^gCPO_A+s`Ra z19Bh6AO;Vhw@SLd{*Ere`=HEx(0#Kp>Xq)DWR0}sk{cs;5+g*3_dLM6^u|$}MWJJX zKR+d+e+H{!nuX3CGqbuhkC_JrsRZ+HRt+PFW{`xUmxRu50l&(y9weD}j!jlP%@sde zWj$pfSwr$rJp2cUA3ce7&|mWglwM6{96!akB2;zZ0LG~~ABR!AjLciZrf(QwmgfcK zsr}C1p`+0}fKI({;}|2$deJ8;D&mM{?~b3+Dy1P1TkOd<7Qc?bOSTJ7a-N+& zL2ub)x8}TZ2SZh6XHRdj@xbGC_mzE+1Ud5ZqlYN0G~`)_Kq#<9o=wHB%F1u4QG7hC zizBpSbo%98p;eRdY1IyS^%|aGY`)aG9Wj^r!`9LRn~Q)PeHcuDTFLP1;RAHPsMa=a z&}{+zygPeQF+6xD2>3V~E#fI;x466m{nX@t2H#YFofSLod}bZs4;-s+|C^J{P`~Za zT;}|#bL~4Ak1^!Lb_)7^NZ4{}%vJf4^C>xnHHWBx$VF+O ziw&VthQYPp)hJVeat?IIQ=t`^hQwIP_NFKuP_A0O^AUi`tCeq`!V#wv{h zQX3=}1aUAh+pJW#h1X6+i4uveyywKNZ9T}+t>x0y8Be&cue_%4FDu=XQ(Mz+V z3>S*32CaD9lkW@biTpJL_`>M`RN12OKs|3Q0s?SyaG}P~S3{D=((&mO zov%s5(QrfdQ9LnTu>#~p72!Z1x|~K8Lg6#pZ3C;WVq6UM#n2V0zK(2?AvI*oqjH(l zy%Cd{fJ`37+1~!^aWVOC$SEZeiW+aqid*FnFM!g^28inMy(glAZ1x!;j!uU>IG3EO z8ysuovoHVZ>acb0d&V&G_^))zTrn)GCjGB5Lp?1@dhc-VbwF+!_F&z34uCLIMI+BH z_la`O<_B!8jybpWb_x$Gm)t9c;==$~(*v_tmy`wH!pcU*JyNO1ZL=bI$l|% zm%7Y#x_?BOFZe6bCvq%@I+lI$WQcLXXgn_X;O?(=n&R56>X+dT*j?)-+`S>rEkQ9_ zF5jevKl__aoTomLL&Cm2YYv-gi0BEmO4!)Wu?~|t*g}Vzk47P|0di1S%>u+E@$kVJ#weZx4s<`#&cHe>ZT-dIM* z&PNbKo2Vid&u)yG!aqEjVLGjtE%WT}_W%i`Pjt^7Tn*%LtB`alobZM;*RMHi&^q{L zK?l{RBhLlv+mi-4?Z(6mUip$3cPIgp3MtiR$6)1=E(2TeRAS=c{K8GX@aRt8A^!v9 zOu`~b=U%kJx$BTSuF-XjdVkl)M>ig@kliXB~(>nZFF+Hk}+G~O%^GMYtJpYL-#I;gq z=+VKPeVK6@@9nt1kKT!*==gKR#-IlNO?DZHDb0SSNZcnLPuw_dcNM*Q2Fe z;es1{5Sn0V+{Z^K69t-Ic9xFIr6t>YAk&EsD^kTQX$^v5)p9(0+jRD!&uY6j&orgJ zB!_}g6s(@)Gi7gi2A^w@X_G3V=!HcI*TaD~c zp&RJ+!Hm-9X z#g@dj}Nb~dsz>w z@C5XJ&p`erqd=8c-m^e3US530FG6Aomp{WFH{xLiN#se|2L{yMr}BBb=btKhSNl{7 z2E#g#guqyx1?gvq?c6b+WHbO%^6lrsk~}#)x?zEVyb0ES@=kLi~(CXJSxP z+@v_xSvn>wv7vqls7U^(!OwkQMH349RIQguoGbw4HH^w@CvZ0#Y^F@&0+E*?Z09?< zQn~~RRvcMIvX$8;lgVimg0&K6-)P~BOLOFX0zkQdut_iR$}jF`mR`XFW@jLMA_irz zNq@c~)bRJ!NMU4Jyg^f+g63HFpI9KzlXs6=fuDfwHgDZFGUF~?d(|qIU$SP$lFgcf zZm46`u1!G=G{`^Ilh!J`tD*YBt`vIl)L9ia_zaI$(t$7Q{(EZE1Iy$FB>#c)+Q?=r z@M`5guL(`nuDDtF5W?fZs{c61J0|}fKbI+KJ66j3Mf zZ$SH@$jx@~<-d8m%CGX>D{8TZ)@85GyUM}5aV~<3Wb0EINNm}+Z|I{IoS6lG-qCH@KV$!89I@cGWrU-_sE%}V0^o_ zm)EJ?BA|Ap|5hB*eD|E5TK)CaHB4*dl^V*s7by#}4cK>QNRxt>havj_QoVRAlJT|QfOg4 zUi7feD=xF6mFCr4PfEpl3@xX0VFJbE@NQ9RSUL09S_%)0?l6Wh`mmr~_X{EO=c##O z+1Hj|D=POuUdcQ4dBVdMdEB7iaQni_>hQ@Kt&COD%!krj|ITV=Ulv&=$H*cDr;LO> zNKhMKscItB)hHiR3LuH@Mb@c>*O-H&mUc&<8xS{A%!3-8=fSZpY?frxS=QkCRBzG7 zfl$!cL(_>sB@3q79k@Ja3KB9DfAAFU;#5HjSTt6rW!Bu6 zeUIs$Fl8YXPnQIxt8KxGV+|trwmyEzio(I+aO7Q?^G-A7m9xvv{xHkvNX-kKzTv%} zrmM2U`Q>GoyM>E4;v&o3{;juPIa^j~f&?kfgK`)&!>FNsvdAwvL%kZ0fjk{=LW2Sr zIAQy@?|_y{oaJEnzr8=w-}vkS?=sr|#edNd_njE$c&3qUS^CwRuL1Q(#W~)SET)!O z8g3qPD$1-Ssqi^}eT&)as8_et27aEA`~4?7q7V(%j?3V{s&6jH!%F}cE3WkINIBOXqP0S0yAH)prd0%st zMFXN`c6QJ6cB8%-UN9epnmMo)oT3=g=O27`iFf;u?^1fEnRnVy=H7$(4vj!-Yj$ySQ%iF?-ysQbUz;y{62H}| zwtMNL+c;iBK=!=>;ISUd7Kz?dlec+j%y|6N#_2d!UHYMRAiLbgC)EKjmnDw!=@coiC`Tj)i|>~=Q@Djzi~SM%!#wUH;cO@;H~O8UuCQ`_LOIX7E0;m} z*7vj@9Xg*0~@sI!Z5z8o!%AI6lz7}T@6n6cd|E6!nEP|SwL7e z$chcW-(oT8s2r<4Y})qahsfBuW*0y3`X^_c#I@e(@ryTP0CrF50! z_B#9&D_eG&VAzIqoQK0OsuKkQK3`#36Ws7eKZ*l`+?~as1 zV%0}URdmcm&Xr78ct<1i+$=40?u}4`QFRM@X9Y?$I z8C|^5*=)`^%i5f5)gKq==0Y$3ZrjlVvB7CU+jnFpqB+9EB zFTLfTthMm1qh89zz!l9{2WwI%-cmGYzup~R?BS%Z=&&Dgnc1Jec{r<>t~+0zIRzqS zXFj=N|@F1E&35 z0|Ox@A*Jlz<;7;7!ou`itf!&gmI85K$uFM(oYD{aC%lWbR_JctUOzj z0=Nnb-mD~m1S%wnt_Sc*(Pdu8KYliv&^40yfi}LqL`UGR^~tG-6aS1ox=BKzq!1gj z^T)K{_mJkW{8PkjlIvwH=k#B`CsFpw8*!14zMCx|9u$6O@`>zV=rB@&(t@|a#QgMbTzpb<)@=DLI|bo$B1!&SY1Jj5v%MaD<_&7=t+<2% zcM`RS%RlI9dxM-MKCZTa8X~c?2qwRq5>jeQ&8ogZJ_p+j=b+VFa`E8yY*pT){weYf zkS*eOr3bSMUi(0hU~6i+9Cx|`c4dDD0B$^7!YDWPAkP&i3@Bos*{rnSSLOs$j+0uF z{(^=K8al33TQu<&;v2y~(I)mL;?N^1w|DESGQTZ+Y>*TaB*jxwiVFsgVEMt+%TRsj zAAD6GdR=kze_?rnB0R)Bu6o2%8Gn7-kP;PTIxth208!`9>s`y8nW^-^$&=sZZp%A+ z%WqI+isLRVw%oV$Ojo^~YefM(4UHFqDo5p?N3f{W>=AfI^SvRdODL(cEIKOsJ&mF^khsb|6nX{pyf~d&7HisN;?!?98yI#l<1rod8#pzaeCr$obNh*cWOLtmCTIU zkADn%$HgsgJB;Nt&fG_FjObwVf^rYjY~DXNo~3>vt+*hRB6xhT4EPx`b|^9yJsn*j&oQV4!x@ekcFT z$>_fm9f<~&?Yc)$c##qLHxGdywlR95493NGe;3Sbm@$r5%a-<=`!6#xd&B5{)$uTw z^`kr+zru#~8|-Q;>ms~rx~(M-SBJ`_2S&N&d=RMmA+_!`&x6PK1jtsS^mt6YdG+TP z(fh$xXTwe1^LZmysU_X!?OdMTuO0<(hP79I#AoOtjrbZNYF%9snB9`?ZS&j0r!}3_ zJ1v6Xv~yz!5ZTN)w(vbIZ%5JZ(3|wC;Ao2YK~iI3x1W|tu!C}`H)AI@iN!EP=!2bI zR;kMA*51{6qmuHIL?(FhJOCF+wfcM|GjhLtQIR0e6rC-SJvpn-7-Np**yQb6)6W+V55m_jZy<>e$%9pUN<#5L6DTYr&NrT*mM;~3^-TDoe?Ff$i zB?F`XC$#pa-FlJ+UB7kEEi@4-F(_``=v^xW?6(B2-KgmW(J;~k!hBF5^1XNGf?Z^L+U^-eL6V2I@O&f0_iRbVu}jv;MIOkTVCITLf;3Wuh7ojr+5)t zqp8OWR$Q@WFfn7mU_gRfgGkZL4X6&aFRz+kWFeelDhq6v7(*E_T_PgWQXrvUIp@IT z*nZ{~v;$89D&?zjTacw{0xz_6t}VbdTobV%M@BzFNQ$pqba_{R z-MPZTta)1es{7_gnQ5bBt%3+W%wS3)7uH#D@Y#Aw9--Jsi!AlFSSYr9Tn-6}=bc0C zxcO~fi6j!Xu#qaBgtm)sEHGe~IW~SfNB-Lkuim9?m-8|Bn)s0y(I(Qg&}f;u$kkc# z8Ig#Hcii}E>}}ug`85L*Ean!ypty5DBdPHyh``{;{)^WWK}4t#8g}$5<*>LAxu5B~ z0}Tu#Fv-oj(e!hy?d)$U;{W9h<#d!RnJ@qVte5<6-q3$1r2j{FI-)D-gd>f}R|N4L zCdMZLL_3Eabw6mn+zK9NI!yDzEL31I(_GBPyHn^T)|$&GXum%iq2He{#Eoz_8UpcG zen0Ns#FVzj(gT9PT}|Fi)l^MQ?LU1*uIk~je&@11Y)9^M$I!2C!5R1K?&5IJ@$>O& z{59JFhtmRQG&V2S#t(U8cM8gI>$lYiwfK z&U2}WLz%j^^5mZ$olU<*p~=4`cvcfr@dB~kHTlhmp7Vk1!7>2?_|DTFnLm^CFPn2| z+Mdj5K}c!3!}=wTtCo$B_DmuHSKpVDM&Z1Cjv`8M5th4*328SfVQ{!(_k|(=ln->x z@=S~k`sg{6#Xfp2qh4bYL&);Y|+|zPqW5s4@ftC z%5BHKUsX{_-EvMupB^nQ_fU^()dog;7_IX`TIb;jevu@@OU}d>4b15IWv5ox?Y^qI z+w1L#zA5A6>hk7Qhn?1r;V%M8t4-1epQmH$n;B$#n$8bqko6>MMQszheBxByfGWQO zk>9n^*ZexS`C~WVJTA!W$ z%D(W4{v0s>dn-q1PVAQR=eOA1j$zTBn-}ot0)P>SFM`F7yS6{*@{jmE%SoKYzWhUw z*mOspOgChvp6ObanAiD>>{vWpZU9RB*9NEhVJ4NOvOYvC4n3?K5j===0|S^6a92au zjwh!z>@Myu__}pjT#r2ue2OoJbRcEEEeGsM(-8+|-Usu%ml`SHDv9%6XOC&o9hIn3 zO~D46L2wK(k9^SiqaEdep3~36D+doeS=t^(0#*nk1vY0Vf2m%0nFG>v_nAOvJHTn1 zo-5ox%!QvpJXJI9>D0z{-rFD=z+W7e$8Lc+WQ63|+zAZhdIhqYQP(ZrYiIBU)qbC3oOTat-CY&r|#T##H@K5_ZLCRnX?p|Jx%r9`(q6R{3pm2 zwsNmA*84j4q^V|^Z-|reVr70jpN$pcghB?n(1~;4#^E3iI2>t zDu9taFj&ok6aB+6(-48lq)LZ0jAg^cgA?X(8K*{jN(eS9_i6*KR@PO<`0I`5J;KGQ z@XwU;dFcXPQp1rd30r8yFDPnYc3F)V*e3GWmsGXMJ2*U^XM*}1g>DN^l&`si&PYm~ zCbzIrUpT-?4C8YYh+s$C_Pz!(gonjNhMA5hh}L*Zt)d#F2ou^9OH=~Rlt=+KJ;9TC zJSul&Q^e}uNSHL=JPc2K1siac-W-#Jac5pTc8!pO5W0)vnW%Ep-5Dx2T>6N60mhUa zEe;>d{753o>+{haJ5ch)&3~0xP~rY!c!<16MihL3<4cHR9c>&4lma?f9uzL?kN$_w z3GwZ~xVck|CHGUmW(9F_elGEi2S7_=H-7o!U;F1PQ*ppLp)X`q)z`#jlp>^noIxHq?lqRDeE6eT&kv73YyiJ=Ja1u5Pycs ztKPU|{pWO*Vm1PaEb@=hnQU}}N&o>gaEXuCPBoVR5lZIo?1Y(eebu-Q^dsT5hKW+F zW!e-r@t-seWn|r~5yK0>k_kwAoG<-p&M!;zgJv`reyoT9Ur}gk`c;Asn6xw=hsnFjDY2w~2Bj4^rykhC-z4sk`Gp#RW1&s=44o_i>CFYN}wyb2tdqar)O z725-AgZaF2Fsh$R8Yk%c$|MGF8=ZE5ZqM}E*(I3T;JLhdn?$CTks7IbwGEHl@D9TP zLuI!ut$(lO&Nvc9*S>!$%VsMgO_-ObfdE7t~!N<*=n z{4f!SLac^TZ?_DgfiXo zjEHWTx|58c?GNc6ZzFnVC+tv}u6s!BvUv<*{Jy*Gk-I~BMNf-8R-Sgk#qtHZ@skL2 zG&3h1AtfJM_vwg%#^#!lXMv^!AE_*R;Sz>7zj5O{Ms;Xl2Pb|+-L6bFCMyrVynSC< z1gRf0`A%!U?2Hei7O8hRb+j>UxH>!?R zUZ+(WBATe00^xTo`U##!%KvhF2tnilc=6T1yh$8J6?@Gev_LIuRy_p_DmTYrTh1~~ zN^l%X95*=mtC3DtcF`NvnP{@t-ViAlc9XP}#CLGpWJHMU;&^jkN&8#*Zgl3YQNOXP z@6uYL@bKF-W{30V4d-h&WThyVVY-!lWv0xgep)qc^TwwV5)@&O!Je-T6o9 z0^SZRkxlU#wkc-th%+lCh?MYr{09>S_<+4=yPtXD+OuWgd9-#ENTuYNE2J`b>q_iY$-LSbuQP}cpz?mtD{dAd#?vGG*@IL;^^vb%wvl@@M zsqy)cO=X#`rNvQDa6c3EsE7DeXrH@46&*8?F^xtS5y2sKw)&@>a&+af=9#Qx?%>7vItjl>ncUYz(4Fw^NT^H zTRwrRYqPK!fS)nj>S~2pFs3Bh@b9FZ)=ETn1^cRGJH6UknHyX*lSx|iq?jUY?Z%?2 zr9cI3VR$OTyNV3{)4Aj?3sx5~b84;xff&LiW>#t6VnNHw8Wk|+QX~t#-wOWuv>8xZ z>PMiLjrNCsf-bdhgmuso&iH9qeX8m3Cude!3kMxgJ~&@8-hVhvZ zy~p+U$8OkC)H8u@Ue3prNL^la*?9;A!rM+5$>@>;&R})j>1Y0izwqV_-Yr~Koy=(f z!lWF_5^KR17;}3BZEJ`a7I|f+6s{r;O`C7t;as(=+$kcj?mo28{No3P!CA5VqV}V~ z)2_vrA#RNx{Av&-Eu}xYLPFE~2A7VxUt(<}ETG$XTXv$1#g=gRDB-H-zpp==i-6wK ziGI82J&bvTAk5$GjX5`>sd;@4l4JzCZf&-GwHyj6u!V5GRGF+Ev0v4N{I8?AV(#`h zjs5PZDZAdQ`RhQ~r{vCl=z`G)fE3_;Z46$lQr9Pa zwRPoJFIi#wrpTQ2N+NTqWZCg=eUSD<1qd#aW9Tg|v%9@l3^G|pNUMnubUQ>@u} zYwGG_?{9t_x~w5iHw6$)P(9R_LJ0+zIkdu=%~pJc=iKJgyNF>pr1$2GKG`4Q45a2H zb|ueJIMK1!CpXC*EgTzD&5cLvnKc91vrwp8L{9RRu|um|hCM|D#W*CRcC6iUVPWmYOt?WY1Mk>rQWv0Vs*@sHH!Rz^N zt#Wdcy0+To-~2b?3w1LNFjT3IxF%E4@c-mHU+X?PjNai zaz4|E&1CiI17&`s)t?ZCgnP<-09bLbgWSpZ7}Ze`RJb-Y@U`jFK`~4nAVlS&zy^yd z)LCJYHB}HgR(hdb4}l19PrP$-5LriR>o^Y3ds%an;UE+wvHl1(ph!%DfP`5}I(_<4?a1A%v9oM7e4v1tp=IG)Srb3LT{W4JFSk_LTU3N~pol|wh z)2tIjW*(P|wGyINRnUA|DcMRM`KQWRf?7lc9WYB=P4UE$*71u-8Dd!0!|W{&B@<|I z3yT9v(syGQLtUyH26b*RGq7yCg4$}ckVP%0y_Q!1dH=akqnLD3zA=Uu8&@MNPQ07t zcLBg`Rpzab<%K$=l2B>=RmDwEcQFif?BKy`BUa31X|$G2S7OuO7xNN_%=0U}y{-Q$ zyl=)Pog5s+d|F-4ZT|h-r`7`uv^<;U$>B(yu|~L+JWV0twU^j&O7;xKoJDK1N#bGV z>B{*UXFFh}Z(0cw!7V?BFRf_ zU1kr3#cWWt0J~YWm5u}M;y)Zf*I%zeTtsC1-R)qoaAQG9^v83#&S9Rzebd+{Mu!w`m;x_ggILSlS4@?5{A8fWfKf<-F z>D3~ba3Sz%ydp3!)N)MXF$i@; zjo%o_@IytBo9u3l9xxBA1#toubPcS9>~t)g z1<{2RLv|)jzk=|*aNX9c@^A^h9*)aL7?W9K^>+*^f}4*43ljm?V7k&QX>|}{y7FLE zS<>6(9CNPBY~J4KzzWxFvoC!p214^t+sOq@4O6YOBko^O ziD>AS!`hJB9HpfTU*)pyAMt8~z9W$qB91JIvfz==b68Lxb`*ixZcA?EIR2*R3V{Iw z(@Ba+xoD)aibTwbyQ^wMsTb@17z%^O4%f6Bo|q`Dezh6=s2Yn|+FMbJ250yG z`w!26w+pa1ge~al3@j063v$tr1emfq;OUL5!EXgyTUMERCZTB4;~CUqsP^b^fyS`-`Add9^MY{T2AFM(o$Wap>b|Qf{}E#xT>@}GTyomyZu`zc5DHZ3~eNEM!guYbm^xtTD2{^#T*e?$edCuRC2|@9H$ze+DL{5j#dLU_epW1Y21% zPyji6vPRqL@6Ym>u}%$u8M4Q8YIOwpsWj0+Gj){4;OH_9O9q=4OVey=TUK|iBQpmj zXg#WN?mQZM*4-iB51S~;h1OcVRLvq>@< zD6~RyyVnMZaM?X>oPrBmhbvNk3FA4nP^+k!%m+Hu;5*q?=s=Dg=M1kRJO>gjM;qZ- zWewmEb%${rGOp6mJ3@+3$6A9@8kzoL&voG2a4%jNK zs7!(h32Tq{vmyQ)TJ|iFkG=02xsoO*>wy=2HrEr=87@+4((WC!@>C``0J3Zry|^`S zxCKO13Hi-L=g%2+D+XX^b02SJ^Q2apF`9YcI=Q`Ec(92liI@y#YN$5?8(_uExU?;q zeK65V6Sg2SUYaNwr$ai-D`&%wp{48GDZy41toLTuQxoDG0U^cMFj+dFLCDrxB;Y0(8@ed0&o$BN z3kE0My`772D=Q|HEwzm)2aYGxyFrZ_*M>UvUB z+dN&)v;;`CwfFeYwIDKX!x@^lMAH%AL?GWlMEoLo@Yy0vXeV0QUL zLyOdswTtnsFg(!i6WkIS6I~cu!#DtwkWjEiF+TS5BBb;rPLC25mTomuHN)p_=c2?PKi}1ZyU{EYg4Y_x^7&HbXXb^`FM1bzD)< z7wGgv+!WlxaXp3bhK-J7%L-7UlS3d>)6)Grx}45nlAz=W#p#c@f88Dm$^EMj zgz-=OqNBsXQQ2d2OQ^tX)@o=r{`oZ=(`fJdPMc(X@37XB!}y^M9dn8*XlPsWEd&2! zF+`cy;56c&AelrOo)vPEI-B#R2o>tD>zrCL$tIlcNd(7`PuSNWL``F$rI4+Mk&!>AJQ(n+F?=}1|kx}Z}xKkf{ls-d%) zckvWD%a}aL?b;;nxm)^!(K;-ql_-PEYvUjDYS0zndW5Yj>U)~*eu2E$cjmiBpBUjK z3Cq7&jS6tH#*;k=7~HH52u@xg>5b-|@WEeX4xlLC%j2A%^0K?FP7Ao^ZIbJ5&{?-5 ztCGMa3`_$rkxPyvyn43_>CbOVpd~P3#)P?evUw?A&FVVwP)#iRnM_=+8E&mu9i*<9 z*KA8dtJ%q{a?2<4UxAj_eqOYIA!9d}z!{LM&!Qip@jk^(RZLmTB5xXIv%>6^ zC)K@@pB{WW?gxWH2Ebr(`#^F|4UUGSrQ-gi*H^c~OVchG4K2-D(7!Z8GH*tF@fb~y z0Nf+}yt+qsWX&{rN@G=d{Xk{a-)_=Bu%$mj*h|-|V*7od_>F&^J6Ca6^^R>MHnnu# z@LIQ&CZ=2M%pi#aab#o{7yr>EHnJ_JTgSx*&4mOJoh(r-)nxra(-@Q3z?`9zGL|={ zVR!34@H2BpLge#CtmvM&$Q}0**W4rt4O+tJwLMM5;bWL$>Q2R%(}>)qmS+dwB@s+m z@i@KH_5|!6CJC3Rvq1lr50h8~T3!aMo%pOFy`={b_T~#gGRK9I$TK9o|lBjvfqz0RQ2A(p>AJV%LV`yL` zg~VwQd=rb`y2Wm*nL~k`_0jTf0N>LZ|7%nQAVk!flg9d>sa?x&tt2D$XyyDb1BbcZ z$h^#|B=?ui=9 zT212Nt`3^{(w?}c82Pbof9(h2TL;emwBrZB3$4o3fFNip9j3~>)bKG1jp34Ksi{qT zFVCBECqfY;RM-}L4WgDFDd>CkAGY#|gq4G9`+D2St;%f+$>BIm{~Jj100SsM z(%$S))jw}bcviQK1cInYU2PG)q2<@LI_~h|7H2uM!PuodqiOcA;3dOJRetV_N|>4y zG3OQht!3OTA1klgXnZP2%y!)C?A2z6Lm;fX#voT_wu@J-k)c(;wL^!7!`&9>|(aH`?YQ}`2%5;9Ypuo{Aqny6SY&lzbqA|~-L|ljj+A}evU&-@~W>8Ex1;yUz za?KrLKpAzwR>?CKHUiqhYCLvRHFP?G#Y^fWGBuh=aF`UcV5V0=OlXAoH4@_Wn%$dO zPDi(11e8PGc>OuOvFDg;piPDMy7qSo(B=Wh;lvQDXcvOtdMAxf5n|6q{uIM%wu;kK zkfOYoL*8)1hBbaWiMePw-#bb(^L`=nn`VPcf z$RPLTcXXo+{8DVc{@WcM-d5x^o2B8BKpFGq7dGiP%c7qhgN9C`d)+54MP!;LuQ0rp zv>ywS23aHKE$uyt0~FF|ak*SL0y}r4#M5ZZ}7gnLm62~`6P=aI1NMYxr0NhZ2FPCV5G{G{W;He|-qiJIbd85hR4qXVIw%Fr&_JJDRjrd zSc>jgGAkPq=H?E0_4 zDYy>_--*nNF-_}8(H}_NpRtga!*LV><^0}^Mt8A!vB}o+cWPjUIV4fl2#&Fo*L^rN zamQ}G9F+U zqHYg@&cViPEJ0$Uv9zDnZk!VYTMC|{%ev^N$UCUt^V@2cCB0RIOD4Fhw*E}BIIS2a zkF${{p2;Kq&b{cP?=x`IFSF6}ndn^qOmb79rI)uf-Li>P>?4F~MuOrwXj73NKBvr1 z|0hd^^`c^#YElnP3=|fKV(@<`zzY}(=`gHW{F~%?<8utiQnG0^f&I)9lbPj8taVu2 zb!i(Mq%iX$ zNJk<1207U_vbVHJMJfWHl~;~&t-VB=8La)?#GDpL0wCgo%5^Y0%h4h(Z8B`@!ox7L z-Qb#Yt(i1zEGbyu_y^f!MSPA^F8w*3&!nWQfRAh6VW{S@saLZ8xjaYZ3Wx5&JGBun zbd1jQ1REi$ft6(qhH04gkHo%aEh>}2G-|HqV5Wphhudz~;IY%)F;XA$~`GW$%pw*IBdV_RUBap)j2yENW0x- z#RWp}RYtYVSa?DQ4a`BD7a2(2K5`wCUXQ9+g?zC6c;EtkI~RX}d;~n$4}B@0t-)jq z%^;P^ycz0YlO_(dw)gfv^s;@Ja0vNcUn#4=-=9 zJD0Tvd?dq(Vr7h=9ieBlKWPJBc7H+^Jr2-QZ!acgX`;pKwu&vr6W*p%YfDx(=cEl` z1KLgNW70nQq&yF*bZfirE0e6=@0&SdD_7fk^l%V(n%^YGwEBf@uHjF5KBu@hWnpkjioAi{GJTNJ z*5SFi!G{NflG|8OCFqgjFY;y>OF>&B>*4g%b?kit@EE>D!ik!C6tqtVwIHDeDpBDa z3Pp|CWChS>W;`o;_j1Ar_Pg?)*taIuE=uK}3}myBnAP(+;P)qmAD%*f4n^zX=a19d z$;z*tgdMw>kfqqWC6Oyp0PWo~$fa^I{mM`d`DNhdJfGfo%MvhP%O=1~if(so@;)hT zL_Xs{VW`9&DrUF$?h{+kQ1bmnEkIcgK>RL&R>v_e6~datnBJ>X^dHI%)>-)(k`#42 znIi?c*`vDK#O1L{M%aBbH_|=sEou#tQ@zvEC}-C5W=E$ zIwZEye;OKa3lk7r2Aai55&Lc;{4vnUax*%248P) z;&DCr(Q)1MzF$XU{2vQsp9xK}d?(dzoa7&u#CucJW;p7ACj3t+^Y1~VW{S*-perf4_gPA5{InD_ zsRHhcn1Z{oSI`to^yhalTUXXspMVJ(w!}k5R@rQqG0HJMBN!6XO4i_3z=}?&%68E7 z(SE&+VnyejHJxPtDOYrD*~;OhmX!&JAZkhYy|g=-2!i$^H&b{5SGtZWS@Hvm9J!WU zVowu!Q!Og!rU-h%N8L)0F*Q(IaIF;wSiN|;ITa~MnK)actf(sU@8BsmeCUzVLZQc3 zSaLg+LfK1~fbX41PcRH2LR~m_DmE884E+r<{u$LHKIaLmnPn^z|yMS8ns?HBGpL{a7)QEm!sGhM^ zM;8~K%H~zq<_Ry1MJ=z>fMl;yXz~-?Fnq{$P#=xy=;^NxC4C2Cwy3o-&WQe9evJ

hSNsv&sG+S`q~cv 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�@Jj!mKQzFH#!Ms~W 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

ZENd?Iy(i64z+g?V)633ZXd}dh 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

_mb~K zIk+@_FQ+6Extfltr58cBA*3@G!zHW0ml37V2iijE?~_b9MPK&AbB|&$|7PUYJ9nL3 z6kGTi7FkfHJ><<-D`T~_-zN<2w(HTv9r1(vr}IXILw|F^It`;Cj*FJ+zJK_sAl#Xb zvo{%rUq5dzSWrK62R`uUp6erjZNYeTvyo{@;M`wz5O;l%z|imc#2H1yl~roXuTEZ2 zwJ>=D|9pWs-pIOYsvgVclw7&ywjnH(RHuB5 zMuG+pc<*C=>J7H4y}y>uv2lrhg8$EJT{W$ElsY&N5Z^z*KFNQGnf`N|nOWNWw-Q%f z+kSxo)lYn%Ut_;mLib}3hMm!%7c|%sgzQeKZA{Wy;&Rk&8Ew%2gnL9X$!)6@a(H?8 z`EA<0nvau%gX5{1fz;F0!>iIMjTLRJtkCiK8rP=B%4Qfr5N-M|*pS7g&=S$$juUPZ zliJ&`nDU%Rh+H;#it-}RG(aEhz?n;vmaG$%PKG>_x-7LVwr<$j@!@0nJR8Jd zrzQDO{n6-=ACDTkKCFU$2znR$HJ- z0^?XWdzh*ox{Ch)rV#dy<}M#^7v7LUDk(*&M6L?&lR0yP7q9Oc3Ni4f_28$?r~9j_ zp^mgdi?z#@#G%l560k4&0CWTi3HYesmgAN|@gkndbiRwdK znpFs$S!;o*@l?6W&{9bK&EPZOlOxwv{U!aX5aBqIqeX!VSJv3eQCjL@DcUTVjhF@5 zTZhd7!6a4fot3PORP|odPt4(zMOE#k1@^1;ZswKHMfEg?WVhp6+@jjm*hWb%Zp-P4 z(eC*BZ(H02XRM+gVl-2`AkUN03-Sy?^b%7m^`#f>EE$UnnD9Vn>u(aCEkAoabz%Iw zA#lJxEp+fyh}P#*BT4QE^LOfy9u8Z}V*G^{hYlF4_*!=k#0z*`?UZXH2&?{eFe%9qN9LhiVS zACu>KW&qZt3!9B0p3Xcit^}7~c3U#&iCx}`M)isBR^EQOR%_`~P`Y-50O2ZeHuF8Z z>2*avW-LTEWRmMA-}A8Z0Enf!#B$5ccC0#7gnn^lVO{`|S zKV6!!Nv*-=G#vZ<{=;wcvlYa8zpSYqf%c@;o0=o`uS8IKdm2p7uqo`PY=Xv(SC&~z zWM%B((hO}IvZ9HG@QpD(zSUyf*aln4ojZTYrzuI#!wfTZOig5GTvAwRB?o;<=pfCfw9LbLN>aojl_lqqvX;=8Dl$8%(|bthdJ$u$V{zn zToMeCmZMhK`nJ)4TO(!a+z8V>$1>u6qC;imnF#6^@~e8M~`n-vSn zb}mZDIp{nj(WanAUn~D+gcDo+AI_teBmt6d@q2qw5SBcro(`rc9nRAe7nd|j8d zN2Nowhd>>pSj-ATT~fskDg$72!q zt$J#xQH+DDH-%JFTWvKmlQ}dgM}DR|Y)-6}V;!%Ai|cZCOh4Xm<@9}@mNKM>Q%26l zv3(tnMKv|-RJ1@vvx{f=lrQvCEhDDZU)ZEB42l~uiV`q{l#z-;@w^_I?*GhK4nF8% z0j;t@reIhLp@k5}MAx7knOfGrqZOkS<$y!R^wb@e z1eWL|+VEPN@7Szx@w%3+?qmps8u>d`rIVep-wp)?q>q>7j9^r*Xzq^bn1&2{5Y+W!=53+Pm1Mqg&oa7HNg= z$A;S^?x6^uW*gri69i^qF95rVL9}6B{v{ON1`T~=yG#5#IOM5k!q{Tr0tgc<`ywxI zukF1p#`%cWP$DCkY##QuSXNgz4J>A?5pbLs65yuk2T~MJZ5qk>P9g)C(h@o|J?DG$ z`xxMX9XUygE{!Hn!%%;i8}eb~`q^JV5-4(X0s`&M)}Q7Q{G$gI1k&YeOixc1zK)Tb ztLx+H3i})V71NHE!NCn@o|_c0_3v6z;Vtl{p%1*Y|INM?%a0XXrhCN=Jo1jbS=v-w zjhs9=Gv33ykq_I=ng2oDH~Y=0|3%#Qz?M9@{vYKI}xz=;>5|&;e{VEM%n`%QE4H0(vZjF zVMF!v!rIZ$r@@Gk%Uz@M=^AH52M2#gdW_kY?<#YfRepE2FJI=vqMLh;KiG$v%biFn zS4Qg$2!}2zpBE!8CSGO_5Uu0860rH0Th>u%RA#H0eW&+3rp30`gW{|Veq>JhQRx<| zA1dHrWZz|TZHcREdb*jOEImCMI(hk;0FYI$6J3X}FFKKui+dP?XOrcfj#o3b z_kD)ZH86tHGhP62dMh40f0m4w*bJF|Hn(UqaC@B4q50jR&*K|L^xKh<4`(pc6<7vO zj$AtsAAi;qoq1B}C>RbnEHp3e3No0qz-~z~g)?rLU@c?og zk09VzAQ{5apa4kA2;%f+kNgb+1U5IFz-({&+aJ%x*mdhY@88uQ@Hmf6*zt^TE`NT} z1O4r9mfo1f-U4?F()dN_@bujBf$DQ5EDWbG}|^15rSt!U_zqw-7p!Vqc1Xc!se0$Rezq1NCGE>7{*(x8c&FXE62i&c7~JbogBW` zHKSBVbSp{?1!Mk~oUh2SMN`|bvW3M~Vf{cYqEwL2<95Y1FP3}myw0RL8z** zk+!){_6lZ45PN?*zyjqYkPA_Uex6n^=$kwYHgqEByuS?mi@1U1-bCJQ%%WqQ%2;w@ zinV$I>$-3?1sDWJ;Q-^gm~10ex3Ha)V#E@Z8ntyz7_X2+1k9^&(eCB=IG$I!%n)FI z5J3ZcHHd>};YZvA+q>Fs0=ss`;tUrAx02Tf0AGbAx%8@mX*$Ca3WMQ}B9JrOQ!xO< za_lFo856VSTZ-LR>Qr%RCc@R71^?~@p2U?ALJI!U`3|ar5scg-Pe*Bsb(LISwP`?& zRd>D4zNXsIbJ(#27~(l3sDwo(9xc9NifL4JJb*kksP<;fy9VD>Ru>;&$85puRzW5^ z>sISTNv7>#xuymTv(%+C&7ItR0J3sxPF9*Py226)e!s2+#C#pVG!e+{M1coYTMo~| zqHA4O&d~|{>bn#}(?-X5CO{Y`0@>vlM47xSiI~mT2$-}5i(aa3!bAtj`^KOtSo%xa z5MfA(kq-8WD>Jd~o!?JqCyLZlrDo^e+!$0_u_a0MEZZ!S0qQx`t7MkagY|@!65K|$ zKUnc1q3n~s$0zJl46U2fa_sn#=*DZr9gtq9%Tg7H&OPzBJ}TCP(R_EbV)a$hP~ahT z|Gt+V96><<1F2I+iehJ=x1qM=7wwSn78uE-UdezqMwM9S*)Y-mS2LHgnD?p=V#n@f z_V67h? z#yY^2rq$j-0OiV5_Lk|ckC-#3$uo?vmg79ttX=FW{b)d=j8z+20mV`^Ob$*hus$wt zX5V$9wn~HCNp$K(KdK69bx5)9yYxw31Yi0q2Diu$$0D0$qVijA6KelP!8M)ZNwMSk`ic)=(6fL2d6& zAvFKgso3F0^JW9RImu&S8pQ?s%Ul{uTA8x10tTw-<$6OkIwmi+NEc2p*t~0coWy8Z z(h_t`#UYOo`7q7At@X^r>#y{X;UQ?Uw_Od&1}l)#Q!?IBx``&sB%_X99?7~?vhdmu zNos(2rGi8qwzRFQ^lzf_*t!qrbnsWLjLx*Iaa^hdl`4Zw!(v$gH)368-38Dzq2%+N zpXmqIML*4sjphJz>AP5>2{(`fFWJ8UtxWf$FP0pBE^yy~zdo_1UYHW+*|)K73yk~x z4EF6JR3N0y(uri0i`tBG&?{HfhtcCuDIC@ zE!h$5ulRr}om+ed2Z?~Z?SX-8VQK1Ig&_k%%MUQ#F&sjSY|cht?Tzfv%-W&ZlyGyQ zH6cwS#!>bl**47a>;O%CG`^=+lRS@LRCm;7iEt1_0W+w=r%nZniiat6?_kc@sW6i` zrhTzOf)ik?=E0Y|S=l@}4mdkm7fkbS;s&t^R7R@RDYScNZwg4g&->5qyTj}9@9hAk zuwG!V2k#QSp7J|d-KNzlG|12S7J5&{4njE=&&V%Emf?5OIrXdTybFGN=1_-Dy^zWDQE@WbsI1{LYqhz9EOaYH>I z3V6!muy>iGd#tk1E<3Y?-+C~Y9 zhgyxGiwL`5#q8{cfA{OK?dZR&ffE%tFZE5@YiH042z|Q0ra>VslSWn9Az1v|0IY{G z7|&}4C12&wBkTB)RO0x_E=Gn$)bHlzl z9>wzoEm^701+H8XmYMbCeR-dsMq#V}UdzGGP5v(NV|gxAR3_3iF-e?*QKvTDs8+2D z)=JbE?wgwI$#`cs{xNgek8Wy*%0K-+CVSL-+9sfQ#ky#3iP7WLsT};|?|2jxY;<&n z<81dpFepL--9WeQ8ON1X4$flV@eC(TsAx*rIVPR7)l~@DHft2Like4jxoYHF{QIM; zy2Pz9{du&gANO^18Ul_Te0>e7_5)t?@mK?XL1(*cxO01^57z99lJMhD+ylp}0`AW_!e|73=x^*HGbmbs_R!d>1cM|-*WQUb~iwo2J2cTsB$!~NXF*cS)v zCR2OBbvfD}=VLEYOB{fUR9T66LdrpII$Lhg>$u{^nNaAXN!A<&8izK6JpLtXlrrFE7EUX*rxc3ArkPSyREeAVDu;Qa(xEGvl^c){xE8qmus5h$ zOY|yEk9Yegte3ch!C$jMu1;=z*wZY)Tz(cU#opWYz1Vyb6}g)1Yj`?Ae+ho)iBy91 z%5f||Y7PM_tlRvXn&i!jVcp-oPn5|>P!n-Z1QB=KcB7K~Q(|U_R9EK^upC=2o86YY zsF0|_>?uz_bG%2az8|<>j6v zl&01nDCSLOjeL_2;aWGjHD_U8RfWC#@qwz+7`nUOq$jA$C<)Tkh)z5&l;LY}I(lr| z;J&-;aSQ1vo0d`z1QEUbVVGC0jxb_@v^mlqXucSs%{!!R=T&V@nuZqT09?6!wsvSF znlY{n5DHdGradTQtIHu_u3nZ<53}_Us-;OV*&D})NwgxYlBUX<@TBUc{H(my~H1I{r8`m|k zjD{m@fAYa76A5(~w48Qn<1#Xf!1YxOP<0ron_j>25jBYyVr4$LD1Sek7JS?u3&=kj z?_97FO{1XH;?71_%LPBMuO`43hR~O5<1eNme<2Gj_y5PCVm;BQrH7-|im>-)ZbZujC;2h30hsyi6eB)~DB!_PA+dWX)m~rd}P7uk)inA(*V=X)i-UF@i3J6 zJjQY((_6S1%or)^7igIeT+Fjah#_p9a*t$IPO{a7(biFkSAftVkD~`bThw9I(UT3~{MFpfLepR-)!UUsa+s^s&GQs2p z0uj_6Q&fOq8JnYGyAI6YD;KkXGQ>;?IB~gTJcC&HR`;fzbbU{C)$ z_d4t-K|p*Z_m)3P=Ig5WJMUoeYp4eq>TJjyu9~$=21-j%%v;pBSL6VOF)&(u*NI%wm9w9fH>%?h&QiNi) z@uFfV)Szq%yJo~Y!Y$rAHa}DS=4d{9?Nc8SlTwF+8Yw2wDpCxHn!8Gv&cM8;6Abkz z+Pn~{H!53ZPGxtB!SQC)k(q*&)e5v4ah9ohgLO6bZcPy9lKQ@2`_>#&yDA8I^x&4m z+OnGsH~I;y3*;X!1RPXAo55({;5JXeg3Np|j#vX!UjH+U4Cu8v6YjK%$`F#k+s?)| zj4jF5BxfyfFe|5(?)O9WxOKG`y2-Fk$fX{m@exYgxGb)ueEq>gw6{}fu%IwbB*gSq24Afh{vcHYBD$agl_j7t{wl`dX;n7d9a?I z5+aeg&a$bMuFG+I3>EDbwj&{(8N@&iA#9k#vV3H+Q<%i{sL(0=VdTbO25g7JTO*1M zV9GkBZm|KXkih3qfde|rv^UA4qM#>Qw8aac>Kg$+XubcBvUh;eq*>O5+qP{@+xE0= z+qP{^W7@XOY1_7K+y49e&fVvpz4yKQuD@30`>v{$kyVuuk%)|Zq7Rt1=m>2w_>xx8 zRYZ(Q6>q5^q^_wO!{EyWM&?0g^JN6*Rz=!GO1o3ljznAT21ef(|h7dEJBgn}ha24k2DVxqL zcpUDRQI(#;!KD^(**&h`60f=?b zA7a^_5Q~>2g1X0aBzSo5s#9}?Jaf^Eh>1NUIk?iY`wo1cMGr=OF8Ec9)1)n%L59-20tyW4j*3G+-Alj!V)Cw^Ww^0h2Wdv!DC=nO>$l?+3$d1#? zJC;RDQi5$Ew6{A1p7;nnLT9rDdQjHLQwSHN#REK%Jz#i#?mh&PKP43Do6SKyI|wL2*N7d^nU_+f zok{&^7zu_E+SkfJTe22TLy_L09ndz&0MEl!95MTx9NQKtt*rVa8||sEe^b=~L%D2l zcM30D^1Nxzj^_YE#q8r>y4-l6PRHxLG<5=tl`qy(gtyKhea?Nq^x9$>5E$l&w6Iu1 zqtJQ{Mo_heNF|~a4}~g+luD3*5pw7*(Du&NPCVQ?MR@Zc*#maT^U)5e;gXdB$w`H@ zQ9A>dGO3KKwcaj`M$Fh~UT(7@==)L#V%Ct)YN0`Yxy*?Rrorr zc~l|C;3V&oHlTP^dVMjr|M$go(q0!6lgoL5^cbNVzaW*f<1fCcn~9x_tSp&e`9v8I z>`u&jB~oQtsIf|=feGyES9fI+H$x0Mg{1D_gJ70%%E5RcjJ^hNdSH!fk`cGPlL_nx zRL|i~FXG>KH)}Hw>85?-gm-zJrJYTMpm*BAhp0XCGAd3t)7T(zMF~bH} zOjGh&B`Ri%Q{N#xUtvrv%~i*%P^qZ2DT&9uH4uE4tzD|zM$aYa6(fXb3&hlib#2r} z8jUS_7!l$JX2r=glKuoUqUJdEuxr`_Yf{F|Dcf5Z(=LBFP|8P}>faRs zP_$PsBTKXX76#}x7Z~g0sFAUS*F2b8w9t*8cy>2%~kR@Iy&~2h=5F-XolNmvooiEb`=p<%L$2P{pUtRhPePptP zt4`bPA6}XnxC)KNwc39ggX;D-falgugM779QxAzhfx@GuUt z@XU=YwvgM_f3oDDP5>a$E5grwe$o>G*j6#BU{0k#kMfuY6T|DmFQ(%vtiBIB%GfAk zHvCK-Yz(dyu{Pcw#d9r@&3d_{!G_B{n2Re&!WUj9)q)D+!#<|0>=(d1J;X0at17}> z6rA#&aOda`ujr%{vDj-wnxf_R8mv~&Sq8&>t)7&_p=P8~HmabNTIM`6P~W0}DZ;M` zS6)i+9lGRF4IbrbZWeM7_gct4$ZB?+5_mIRxB?SvjR;3YWo}&j2qA)?ddwP0=TfzL zYur9Lw=&Kkhs{s7CrBx+V2r5Y!PoS~l}mDxP?u!t(ZKD;IbH0vU#6~n3qI2CB=^xq zjp!}`E(sbW8vd1p`(q|W@iOV$nvvds$KTWs`bJwO#9B-jp6^8~gXy?UpNce%<_C0a zD#%!80u$A>8SHFk1*jF&Sd+(+>-JTuvB5-+!rhl-%rnvo#@bfj>mHK6|k#dxZ{&>GWEam(GGC{DPg<) z>?%-%05_Bxgn`jdZ(=Kv6F~sHN)g&;R zeTp|1+DJ0i`J>RsuY=JIZ1hYBgnoI|ueW&vF>FU!2IYif@12rxnYR!s+LROHu3W}S zo3|tY2!(|3VkawNr{3)opDr>HX|9`EdF?-i|YocMHCmVp9i`Z zA!H1r13d%+*f%EI{`h^v_*i}@24OVY&S30P%V^?e}wQKFDg`90f zL=*$fDLR}%z|D#T!E*c~Dzecp99_#5NRL*QsgQT^V!;quZ(5HQ?V4W7;0Bqi?-ek{ z1$gl0UQbXRfJQi^9=RY;mT1)y(&@AhkRTB{Y*7SjE#QiY`rbTZIS6?ZKnB1My0Yvb zA`^H>%h8I=M9$*RT8BY$UW8;%;DqEd=$Qr;gfE@4@^9vV1EfSvs@vIF@gdNH!trgr zvVr)E=mmz0w3U#~D8(4pGRKf9bpsZ;L<&;<^HrF%{BfUL^7U3L6U}c708wgjdz-bb zL;mjG9zGxF=2dh25eX9fv%^^-!e@lDq)CR=9VfN9&fprPbR}B-eAZvf-P?e*xi`JV z(jZrTsA9l7bNu5%Jpuu}pp6FgxcjryJM@P$va?iXPFv+D7^1~$J(0-8`@B1+wxr2`DZE^XMC#+5x(I6 z+}nnOF@a=%J1eoH|7Z8w@4nW?=r1I%3$>N1@2=KcbQhocMjn@W;}JTcEfNen&+{jd|@HfRq3LFITM-}EfwVJ!aAIJnxK`12WA+7rj zn*zc9wTT#_0t>1g!(vw6croNu7cEB(?c5p|!>4IKtzl=FNO^O?e#?acO>5bIiL(?+ zpQDcN03mjE(NMRr_NU5wd;cF*rY}Mr`?Z zB|VI;B&0vTSmzLa*?_g{)21)2g#_MMZ~TfB=XxjIN=`JOout7ZwGu|>@VyL;-PEKG zfRCC(;|Oq};SR5IA21|GN1v=AFeOJjid2K23I$CCkO@AbEsr1CJBu|bhCAXNLiRX# z3p%Mknv{0g=^|02zn7#8{-6tIZn#;)>gdcpMSWe@sC0UWnCLcM6IHag=PchMerw4S zt{-+_k@a8`6XD@kQ!9U{bBocZfI;x^=iG#{U^JG6oG~K;e=D7C9gHW zF0uF{gX4U6SpBjx|A|A(GZ3}C*yuWXMX3`ZHQQ7Zh7htq`bbp31>sU|Qg9G=^1LQ~ z4L$_TykMX$WbJe1cbxOUAzfWXmF81>E?y8M&zZeTuv-X@c9!1~E3PhO;gUBRXvr&` zZ3*dDgIsY~VG)IG;d1VvaSW;<#ebg3<&ea5>g76!`qR7RuHtH8>P@3q_Jh~dKfu{O zno8aT(C&UQ)V#pr4fu>aj{UkuO@?RDO{M4P?z$<;W4}1^u9@rn3isvf|9!x6D@u-?xBFJ@q+0Y2;!sg_Xk|=JV0;d+FE*2NxQ{6jfBcyr zLkTsAh+=!NVp7QPxGmT#^=e2^d@tV%QA||0zy5ysgwD zX{1f=9#2q<(amPC@F6o_R}c7gfrlEV)k!?6(NkQ#aQ$W3a>e7pzODOVL3??(u>RTa z>NZIbpt}}6jZhqEsWDx(BN=qvO*fA$h3YeIkA4Cqe2)yq>2gSo<%|qr_I`~d5)&Qx z;{4FYl}GYh(l5N)7Ltq0um-=s&mR7jqn0k&4uck2mnlrqnBZ(`!|AzV6*3TBO!s4P;We|fy*P9O6;hpE%f^0fzNckP~eMxpZ)CtDaG4hK*7L9I0`Lf|V+vgRxU zQ%P@!8$M)qugL{-8n6gQ05wk5vI{Jv5>VHOF%}BF{t!`nW_fr#MhWoT$3ShThel*R1Qc0L!)1oYpq{!_HX{h zT;FSt7h3z3xL(P9Vgb(jB?4;tvk6@JlIX6v4tP*Y5iLY6Zq5HBEo0r|LuVaiP=^%^ z+0dVyC>5R@i$@HBhC^jPK6W~KjigfSUaK!?jRrl?hHt>ysI0-l(NdNQ(}8Sn)P`&7 zb6zXZsZpySUZBp<@@yX7Qmr3YmujStQ1-1B-TR`L%=`3gEY@THzgXs%U@T0*X&mJ_vuXa19boP}#uGhex4dQ&&|`iocNnPI3Hbr> zS=URPkFP_R-aL9+kHJKpv3r(WNRldKzJ*`ska#ChjWKS9FRa=xemJLc$#Jl*Y%Q5T zvj!wBrl=b4bQQ6Eq6=C8zp(##BsE-X)0ObO`(pQ7(Eg*WxjQ-;TmLnbs?@NJS!2fV zjp=u-iAKLK(9y?kLyt$0TH{A9#yw|6sHSAI*K`!eu{vrEc)onk8gj`fXt9?oSTqo z_Oni8%A`rqjOb63|A41s9>xFFL3$fS*-k02o@Ud84yJXkz+8kFTvk>U=Vm~UmU&X4)8Tfv_HdTH zI8~+F;c;_55qXreetZgCU|BztcsjEA)8gZNU}0gcytq1)IZDi^o}xx`DZ!9(N_TU7 zM2WJvA}R3``f$@}t+Gy#Z4=^0nG6&iTOt&gWnrQ-ko{(yewWx3KZYEVrsb)hapIK~ z@-aYr@ejDwt5Ei3!jpreZ0me-2qd4HPKb=jV4{hXXKZ834Y6t*u5Ot{iQzw$PCd~B zYc|T374QI6%E6l!HI!1N1Wa8Wo$9bCFp|=$wh6)Qr=0T%H`xQ~Nx103fr%tj&bP$u`69d;&tCLs59>)Qg{9 zPzPqlu#lu|WmZ>#g1Iifr-fRS8!?Y$6B@jd3EX9)7Ni81) zK3hE-pbOygm$9Nk*5+tcgvVzWm_BECPuh(~gkh%;R|?%KX}d{$4y9=NyDC!*dp4Gr z;713TZge>81)aep{5+TCjyiepn~Y~&(S4>N2|Z+#Kz66WYKu*Y!=}faLTiw+XReWR ztZ4E$^P2FlIDi{4QHZ+%&;Ha2nV&TS;A5J{lOd_sftbuWUKY17%NcA(g_eTuNG8}R zAtdw$pca$PZtr{ps@yJM8R0$d5 ztNap|ftL)FgghutG{uCT)lsgD%mD#r0OIc-;e>sey=xT+IaR+chxR~Kl%@xKJpX8< ziRWWss;o4(W>|Dwx%;wvLmTJ4xvB^=cW*t}FhtP|Q`ySi5w}U0i4Cpj)j2%Eq#OhRa23#9TciwWVKU zOsXv8SJiekqkp332~rgkQW2lpWs*OKyt)qI7EUr#D)zD8MXTi>z9k-v*-xS`E7RQP z;6bRP*H%`T1b?EJkY*+eM+4z>j-sM&ocmBps!-?@1RaNc)oB8mZo;JakCWjjy zEe$6Op}JYqVVS`i)6u|77mLX$qZB=$u>ml=fm67`ij5aRoU!klQPD1u=N1?e;C3|` zOlrB2fyBB!DJp4IkbZC(31-c#k~rPFhC3JU5IMk`Fg}}yJfNP|cxsp|!I?WnoZ7Wo zZp!F+;W6f8Gb3SGlG9v9E;bCJ#7-l`Wj9LWIDUn3tZshj zp$l-xXZ}3zD?SutDKz1nyv)dzb*|QLanVm_d&^;)Xpa`?mzS>tYQ6bwS&usEIq=I} z1r~`fCx&);1jsEKxqJ%puE;vmNmV}+=A;x2ba#K;wHDmhIdcYh%{pt3^2c)!%hV{G zf$Tx64Uo(doLn%6x6>EjniF3F?xZ* z14`BDeA;kx(BHJPBBXFSZM>CTY{AEw2N)AFdusGv;O>_OpO&H(Nq-d+`Qo?a)Opd% zAmerS+|#!vP4Eg9bWFoB_D4Y&A__TUy2<_yqxcpmN(do;w(*gHyBAS`j>P=f7!}^- zN0uC{;OdT)QJPV|#vupI3<;Qs7O&6yaa<|gy+mcsQJ`e40C{BhTIt<%HbY`;?g*AK zH=77%Uq~n-!@Vv;;!hN^@J%uT{aE0kVF&0Jj!id1Jf89MB!;ihRCt|3C0TD9Vya`49rSMdjWi8 zef32u3^TjPP-}^P6?5{TGq1B5;Dej!RX#Hhek%pJAkRuCB5o`G4Y{G38oX=v&ZGp{e)z6)S>_h!g8Rks&<*Es^M6F_Z4x~Lu@NH! z5q_xG>}>|G#Hv${bDzi0f8rQnPp%VKoWk*lIqZog)9(PGnn%KkV@It-K!M+$XNkds z&g?KZTILDu>4fYqStH?JkR`KePBzpFB+zzvVUO-X7O#b85}Fp z>^%0J0Nux3acHNr3cW`;{SI)%2!jdhZ!yX#Z`FT(Fv~2h1WXn%H&;XEMr3bb@7mKf zxuRPqpeH!ZH4WGQCN6m-+In~hY`v_ml{jWvfh@Oupf6Clf^r|*57*7|=34cSl`iAMh3Oig?PPufh9ha6|8hj`{ME$BzkjmWVf zv%38UdrcZC$@j?pgcP~ggWo`e>C$G&lU9`{*^)7pI(Q$o{ABZPNa?t}wAo=CvT`!J z?>tcC;Bx>;5mb3yj?mimT&D1?*i4uP-gn zG|lTf3r0m@332kBAoJXq$yU-9f&DOdcQr!V8uIKhU4Yk(8{*CR)gO!Z{*Vj zDGqD0XS|Te+!-c;0N0P_+EIh4fKRs_M+SmOzQ3fCO3Ks5~OYHPSI8a9*COgWitnYa>2qod~4#4;RhyM09Nz9xoy@&jydVJ0@S=vfuNkSqYwLpLT;uS~;s~8eN-t=l2UXsS;?>wH0JWvmPKO(xqZ#)l8py9@4i z42Ia_j*ev4g6zAxp(c{WLB{}^+HG<_{7wGX-5$G;qm?N)lkY2N7=P18uFr$!t1oHB15oS`{#Q7%Y&ode?}%8G z?u}2zGs%@CN*nBvyGZBm{vwn#c{5ygi#q42qNGo~j2Dm@(kG%1<+g)98vV!MpjPH7 zb<^g;R6CR=Tb`^Y2!d+i8CHtHeR(z7fo{7EAxWf5P|6w{>$IVnnj)bS6U(0Vm}+uv zMbjiaK93Ei5I(=6(@L^RY|mb8y~|mnvE8?^X~>$a;J?l^pp5heYMF4{aXq!LoTb;E zyQsE$xZClQ?R0fC-Q8QH%|ldR;aOw%wMK#CRFG}s$&mJNcHtR<}R^)ydK zUZGMIw#zSLF5x{-Kf}T&qqQ-0sOi>Vy-?Wm1)-Yo2Mf>|F(NE{y#udoXoBN*G4}jY0JMLAh6%@ z!5nJ!FAi}a=9&Gm;^ZVWjz`Q?>(vW2%*$igB~N^>jx9TEAn!GRYAa{j-I?yPSkou+ zk7v3s=kS_syuPuy$Qv|hCB}i`74Y@v@iM?7;V|qHtU!v`y=^IU>JL4`7BPH@LJdQq zv_iKH{6(Gug+g7@V}BClvVo;SL-sl+5Ll7)!35wxa|eJ3PD|$`$NfZX70qSHQ&8|< z>+Ot606(M&VEuL%l}Yg>s%%F+{c-OMkpq5arxs|Zq%sOZRSCBECjlWI6;JVFe(X(z z(QplSsH_oJX5MfP!#3aN*0!}R9K5Herfhh8*Y8*) zO(6L~yVp?~Co5ue%CHi8nE5QNHG{vLX8Ld#SW5ix$%%g^*? z)<`~Tdd+(3ku5|1n2V;P_xfDT?AA>g*iM@iqm@J4IVJH6ocaay^BR&y5dcD5ee8?| zLR9WOP#RbqS)sCCrZ`*Dts1l%)h4scMUv(HR`ikN6lvb!iDdPEBvNf zA~Ih?SwOMYo8YX~eS~uQkh-j{W3FNxqdde5d(!)zJm*a2 z8`sy6+X7z~8R04>B2M*&&Hif`Qs29 z;6_;W=un`376|H@&{2n>5fQeSLAjnLZq^ZaZdl7~@Vi%aX-Ac|_Cph+d)KqA$HxyE zFtqLhOt7*vQJZeVE_&RKA{q@u#5Lh9lO|CuF+CT!fk@Jk23HJFfe$16lk;3L&fzh(X5?cAc=rR zX0M;28u-X304Gs2gL1n%{5rH>yt*xjzN0mhg8}GFY=ME3{C1O3$hk!O&w(;IT+wGk zS%rP~`ZloT1jx1e$RE=d4O=(j#392zfF&6jhE32#3%a>mdLwNjKK_lcxMVb~7q%6FaO33Xhlh`U}gjPye+Okr` zhb4upPJwaOblm|5~rov9vYa&kLN3tf-G&kUPo<8~N^J17sSUt9g+O|w=7P*+|R z1$N*KTY$L2EeVjoV(XFgn}q2P;GJJIzMD5)#FKeilmAY3_Tjn38+14bzt;p_^3A9( z6?Y1USeF?JxgjNyJdq`-6I_o3cEm*<3-QXH!=RA18mjM)CLqD7c!R_WP}{OB%yer2 zAeA)u(5<{`Z?3-x{hnFv9nX^#Xki-iD;7q93rk9x3|Rk89J#aqOR z18IF@_GvRV6?O2xSURhE8c>0HNzu-WVsdO$ZPm;-wt{obQ0%z#NkiOMAltJX zCi>!L%{_OSJV|BL5qvN7{9du9cWaO<#`y^9#vy-JHYdxIm=k=mcFnMQSvLi6xtYFI;rO!A0uVz>b zhQPpbmsVVQNo2s2(+>;lmcwI4_VuF2T#E72l{%~Y;Gn5(6H=K#nroI6HIBmKT$ux! zIAQxxK42lTXbsC&e>+#9@&k@P1A~BFlde9XpIh=X!-3`Ip3@8XlQ7usN34$sAx2)- zK}hL30OrtU>RCYZX|()_P2$+QYf>k#$~F%E%+2;44Rj=iwE z)xcGbWfn)nU}OogfJ)@i40=fdiHqC_;7!`IE{!iXTP09urZftUU#k;Qmg8p24#w!B zJNFgzP&|bbKj`cAL^A4s0W4(kc1p=Lx~77sG{_A;_D}7-Spx6L(~=fa8XraOe<0XQ-w~5HGmcgi@5k;|xuIPj%dY z+ms_iue&68+yITwGAR7Wsl7JL$sv>!cPXmD?4k$h#$mzFh+fUlY%x`CBfo|8%|c&0 zKZ=LgHNHq4o3nYxucs+kCG6kFZM6Y|e z6^Bi%u#g+Mf+GS&?Z${p4gl_?VwyswO$)_CoA%Vt%T(kYiSKY)vav;E24PAsplC!~ zeoK^YRk>k109=eh_mWMsDK_Y`h+ph({YuqeWAbc)hv@!`;K-QG)SViKXEB8vb4nf=>Ig-Q7yX= zfI9d?mQo!susj{?X)cpPAH+anq;4)4GVA7WiAi_*rK}Qz;_E*{TmduB+H|Xpv?Ni#2j_NiL@^+T8N z{zn#2AzY?(G|(^+X?drnXH%Fycx=-GsKxOxI2$y+f8o?s##G@x3%9FYl{9VYLG|Q)bsd!i!+5 zfcD*^U1|r~Fy@&kjbFQL7z2h3lJvd2L}SxF6MMOYcWtY4GVbYXqi5^Gfxj& zBS>4jxi|EUiC4{Ixk2o+0HijwD^C1fn32if6~+|)z@fSBR`xPF*yWK?UNtUk*dhv0A;YrAMXb*jg-69oJ-Ut=r#u#@u@wIKex%zJ=$EJ+8z^3)Td z@k{QFFAyKYH0l&Hp-rL-&I*z-V|NcA>v+fEWr-Xm5Q%eTLgcy4Mhi({f1s<{BH{EI z#PIoFA!EG(R%HFSL1T*{_KiL6DjQ|z(iL+UvYN`{1QGLAGv2O!`V7%7i}K40bw}6G zHyoub3AkY-Qp8fz2F2ojplZ8JF%(gy(2nmU;}FFN0VXYs{+z0y8!YzR=sRp7OXiuj zR13|;Pp@p2Y4ASo6jDp_ZI2?TweDW-ULt`OfxYnTBO6@W=q4l zj{LUJK3YO(s#FT$5c+{}+eir;U8zi`Ear3N^;ox__to*iEvn#?>T?3jIlE^@{XO?r z9~hkJp$ma^#q6ARQZTh7`&5r}^BH|v$xZ}H@r`-=8>5h&Yk~{@jL<}q_(Uw3)oec1 z$dxgRBKTsUc!1)XY<}+%cPNF-D$3}>glU_J@0%vqs0_2`>5-G?>D?O7!;OzD&&Ksjpffpppz6LX|8_01s^v4#a6%X>KY$e3 z2AhCW%b+z4R*e!|`00Aq^HKmdz9o;a&JQT|&K}icwD8$j+nZhrlJVj^=@G{_{Z!U+ zQR)EbAkVjXW-+o$PVEf34U{Xf9f+@?mQPVE>=@U~Q`3gb)B0DLhm%1?o?~uYys^r! zBJD1X%hFN`NYT1R-2ej6CzeXcMtj&kt%8(ll|Y)~mEPqk(i#UbNH6st(V9lhHuf|s zx|nmjfiHD)81|@yQ~K9fU10!d(u2~WLHs>i@!PSPbzcKj9UrI@3 ztLt6r-u+S8BE2hQoH{VJPJ%O+FSt>J8*ni}O9f9AEy{gBd|4rZ&d84O|< z4P;aQ-~?f>9~A+~R@SdC*-KYY(x|V_s*bt1->Chj#lI0j6CnSy zKZ>iljghVEUvu6Gt}s@Yuz0Lj1C`m~Rg*?47gYwE zlP*^i=Wt`H`TJ539CO#h@zgO)ZC%~!0+|Uk8+>9hX$91hj_cXuJEqnQWzHRRaKYl( z=|J>Vu4^!%xSafA9DQs8kqO^!wq5|zOwp)CPy!d%aN+sb(Y#m>Cb*+)WKxL2M{Yh# z1m2$Nt)14|;NAiVvN4Uw8xjwiTBWk#~n&bVc_-8)pMP_;u}uSgq?0XOn%jZqPhQj&=|^g#C99-vp-{%^TaQBmm1)^xj?iV*b{t(>ubn}oULZ97mYW`{<_=dbU7mg(YYqcW_fiJf6+eOf5@ z!7?3A^HkLcZ90M1KW@R2;((DU7KRnAB8r5Bo6h@)83@tsco9Pt_>+izuj%2Ow6ov{ zNHK&nALV$${h3YsIr_?uHgfiDM=#!cl5usO1f>G0IW&|>lAC*0P?HbZ|5V4e(ZznR z-#VQ(XL$cOl@|+A$oOIEaw2EUrnifqFjw-}YW^}KK-u05NM|5iOS}EY@$i(KV}wB9 zB}D7>7jH3xbJI|F)Xwj&r~(dZiLSFU%tJBCSj=;&0cT|q+v&Kbv6H!VB3Hl-w`M%+ zh~&y00qJfwiQ)*b+E9h2w2R6J4YU|nZA0)P0)7q?-IHs#2D>n?4pfM&+aIv79`z|2 zn>7|9O?SBvzd}wZf?(YCPmRLV6Mx*e2%sbYe+?EeK=Jozbd1EkU5RNW%5{X8N?3uZ zYa`{FYiDIP!4Ra7i~!vC`c%2}oux%=Dl)c^m8mF;0=Zt%BTSPTPn?_Xi( z1;6_IBjGOi5YCC3Iob**gn_ITF5`r6x;&*<^8#d$AVxf6t~QmGolmTxGx0?PP0nzc zkC4r_1^~6?1QP0Eml;}ZUgs&&*Go`8Jv!EgOcR2m;?R)?Lfl6Uo-yi6*aCc=3zDmqmrVS z9~$Pja>Fq8s!zbrWQwYo@H8`hEQZXYAmWyNCs~PFVkr|EYtL)<8^|=pb}6>t>clyJ zU3$DZf9Yhb?uBagUCSg>h-bKwW2VJ%7JAAQ^Km-8%I-dC8O#s{lfI{$z0n6#Lvuny zAJ_#w{r9Gjf9DzI|A`6TlIo!E;Qlx7p#Em>U##Xh2=!3-zWOWu6IA;@Sp5$&D_fVp zoo#7oX!!q<2UsXrC@Wh-eJcWM0v-ZS@4v21oNWx9%x!H5tZALh%pJuY1#E=>OJbz{ z>){kXV4=Q&3jfOMVC>}V@SPJD>Yp|5amfGA+4swYeG3%!_y51io}HDmsrlal>Xl_D zEWTx_6Z{q~05`6NEO$w8ORuKS1v}6qJR__{qQ*!C!~3a~HCG8e@=7*)4Q)7Jl0q_|0s6JPD**T!kDkQZg-pD3Upb?3yNTWxw7PRJ)XKAak_ ze6NMPk%iQwy|m7)?dg1ksvcdwL|6pwZX9QGbHg1_DcNS|hbn zjlg#Ixui_<`(TteDni=lr9tV%9{tEv_>x6NQOv{!vH&&TG{FSw|)&<}?n*CRX2e@qgiSq3hNX z(|6Xt(m#pE|0JO`HFx?xjm#Z53215Q{@3|^hwdAx-`UF8k?y~_@juA^X5jypC>ipJ z=fAH0N(A5O|3pIfKUxG&SSW(;0~X5r|NfD<|F?4fA)Wsqh4{PuQb^oUGW%|f+`r#} z;{QeZzv}C+R(wEZqbmJdpsMFx!#ozGPu=|_<{t6pf)wa8#0X2{x@DT`U9)k;o+0Vy zBQwjf-tShjwbREAZY#ltVnX-)jc7reDyRn{J=XaZ}-m0vg-U|#|z^QH4+)J95V)fd_QpmP<|)wE&EE9m~0pc zqTH^GOjHn^oKkoysb|qnwi4MPlEPY2O4`{LWHJ780H%Ci)Cf{V7K_FRtn4Bhxk{@} zz(PYIJM@E&AekJeRaL*1fh1|YRi~lqTEPsvuz7(M-*>bA*m>X=c3Q&ppGpYL&$rdX zFYl>GSW({TPS@p+ewv#Ni;>LOngYiVs>sUTSOMH&yj$6oXwZofy!I*C zZz)$zTOnr{rd)wrIRmU-x}9K?kD;RRYVZvR3H>zPG)@y{5?+kxZtg(^q^PVp?}ZxLS(UQ#dO$Djkl>T_>0 zdqn?-wEnv`e=mCdZ-tT2cXa$0HJ%A8hxjX0z+VaJ-}3(d(BHqx{+E_l+RSP|`@2lr z@AOYi#NY4nKQxvmQUJ=207d92z%>^BV%Ih=%Jdj)Mo^-cAGB+csMQnSIc0$U?l4iX zc02rpV7p)eDwz<=E@pEGU~L((j-$6t{QVvOpt1Nz<)VBS`(Mq*%ZV@m(Io(YJR~>(>Hqa% ze-j$oT3g%x-3e7_uh;;ypm@U}eaYSQ68XoC%-#;hO0D^mAd^9^NusO*AX)>PkKPUv zxzvUW6R`TnA_x)?0wSF))qH|JN+G?yzP@gXao5Zr8BJo+E#Y~dx4ayt+j3=B{(mfe zV_+ps({`L}Y}>Xr+SsPxo|PWvlwd z|89?rksm3N2lg8dv8g3Jlec3*;tnIvHbG2fa2D`a=v{z zzjSKt;n9*K3b1-uzQnKi#r!L~KCda6u*2(C=;H<&YYNRFHaso5TH-2X+39;;WRgUl zM@u(nR^wqL6goSP*w7EL-l>f{(@v67f=HN#ip~K%dSv}_LSi755laKB+--1WJy-*a zYR~P|yn6j_N!F*Ys^031442$C2K{z(^V{QrNt+j7A#=*x<)^npTaF%gCojK-DVN^B z?}svh4!M!#P-y`zdj1K3@Z`ktGESB18PDR|`R4%iDOJ=5dR5zl%8Po$hAg?Y7=$O< z+{x*~@`2J4E%Sqm0KX33QEwG3M$Sw8tl1gkG(&fUcjUu)F;bo!ky8?3zQOEN+6hQ{ z^RkuS{$B-itn`fPs!OXM)thghzv~h@gZNB++xkadUJot-K4Dq6k#!)8(5KDKDmgW> zxNV)^69+bpE=dYzr}6@H&{L^aVWozCdigt~kttn(!_&d#Z7GP+ZS_!;Jv16OTtmnvtr< zPBrJzw$9t=8&;5;gQ^rcdA6kLVl4(Qvs@q@CFwoc?F~%b|-2gleXBNs4fK zx_YydgN}ujR&tUz08oQ_U0$fWBhXZuD##i`cmFqLKroSR72gPWU?>3d6bte!3L`R} z@dS&`08?Rk+h8x>Ca6A|o{=b%Uyc00F+e$^vaT}*9DAi02bRuj`y3LodOw0T8m!cH zE@i(tp@Y%^5mtUpTqw~av+C>?-MYe1N*6;kkYmW%yQcLgQ`whCU@Ih(dX-mU(^oA9 zID9Q$z$yR~>fTT|N@;9O8w*?<#W-Z;?Z9yfpgL9>l(dB*^}9CAA2)w@PNqTpedAl>JNUOcRYrc*De^_S`|!|y3Dz!e zt+3W|gfcq}Jf*${f3M75ux(?6Y-5@?5Ttph4!;vS?PCT$M!EfW<)n35qleKs z!U9->-UjUwLvx>Rwg99Mg|TJblVR%qOA0Y7WvgBy^xI#_036F44q zXo&9g4m~bFNCfc;Ypi19tUTS~D_ya{24POD^v((9ox3(=;R3@yNunit3!C#TyOr639>kO;8v>FiqAHieAxJ$C>dZXkka$J&6h>^osqj#!5>< z_zL5kdfP;T&HIjA*|;%&>j3+JS_H*XU>Y0~c`}?zadC0A z+=fa06mqP6CHBPb=r2i;URikV5>*Bk@l9KgmF$p`e_NuuI}TOH$RLj(9Yi>6YLoFd z^bjXtaM)@He3l3M#4B;2UX6}mRNNZSAg^rl=G)UOr03HLuMB7G^c~x?N59;HPWW{} z)*J?+dObQZ;#MQcQawbLsl0MrpaBBcxKtu4racvO@i<^etpVZt#1}ebV!tlC`q8D- zMFsGN4mIU6WPvCn42Ce{#+t->NRmj<08hV;)R&=gure4Mb}-Is`S41NgfHf%KpHT- znSfZg6{6!z%L0hFSi`t}DY`xK>#f>vbWPewVS5Tss^pI~6O_=6!&f)!Z&;Cjm>>$d zlYm<0WDySG#uJ)gdZ8yRHprdJ{nu@&I{%t$27Z7-(~#5$_pEI8{ZM~wzOq(*u^qvd z-nXyFGMQh7`3u$8#2NS8dzmKiDPnO_SmDcxmA3kvS-b2DM)kFJnt3?kLFM2zrU&aM zZb*MTkv+$IOL4JqMI#eO%{NebRtK|BY>J}`DPj!d*oclJE)HjLx}s16igL_yCwE?{ zIpTl7fM&s%vg7&5m0uA-P`cSE_C#C!%c)7XUOb#N1 zANRVQd@hA4-l9oTj9&l7tn8Va1{NP`dJpAR>r6lw%h= ze^p_*v4%U~&0G=VD9=M$dLv((hbg3pJy2suaQ+?yvOP#}z- z0GCFV=)*X~;*kp?6~);}50qI7m!MVf^_MWl;AaDV38pTFZ@ZZM+Ilw{11oC~VvVX8 zt;W0rN7>kmgG(oiURKI&Vv&4sVLt~ZB!`HzHAFNIhBqB^l-QnfNGW&EvJzqqz=#@A zkEi^JEc*nGjh|?Qp4AWUri;0ba+61{-mHEMdHr+t(cy1Qhc9u$3kvO~yJPG-zZfcR z%*L-9isFuL{SA8}b2ChOQ7|)M(NR?f6X~z+oQY8H7EN>+zRM8z^#-79jTRufENW;aBHHahbt6pS3|2(;W53EvXH zha|`hdrvY-aURARLFfnIq5*O|J87(1JDI7kfJUn0FP~>iRqJaLxDrW!VoEMKi721ZeOQsA%j8glPSTuYxn!m0CMbwNEqMqKqKJ zdJVs?a@d)2QY_Crkv?DZI=sz&ysOICV%Wv{F_|OVm5Xce-EN$7JGiYy9ZLjAC&#W1 zTQ(hY4WTYd4W+gdTz@B+__h-JwR^Ri<@P-d-v+RSO}$$ube0y=G=sOyD)0In&yC$`8e*#G)gP4#^XI-j}1VkLXQ5;`%|AGIn ztJ-XdES+dnd7gRqhDkH79xWt|9~C;({-No=1bNh1H5DtxsatDn73Ke91ZnQ+N&yH` z%Z9Ss_lAlnhkj~Z(~teD+Dndq8?y$$q!A=09{Y7jGGbid(Gx7aOrzQvViMpCX~4sV zwe=hI(~xBOUH&$v05w0pos^k~GL9at4U?1-L%(q74RJU+WUI;TnBH;t>zagyBI}A z25uAdp;O=K(^$KqqKtSKlpsLU{2IsFpT>hJOY&qch;!^q5>pKk(TVdRP8ov`cp#%K zIj`*~Ya@Z62FCqOQUmfKBpMjdCdSG3+Ht&z+cl#9To;%rP;M_t3UNl7l3r@8$<=r= z$P5v}GEJ9kbh(CG*#V-?Q9ztLf$gSH_9Bo~b_pKHNeSZ>bEe*;9t;RAQ0&E2tLMQP z^2*#eu=$1HsU$(f_FAQ0pZKNjb4D~#nh_}N{vEFkM&hv@l(MgDTH-x-?Kv+KU;{d zwPb|{HG+89b_$Nr$u2bo4#5gy9sN#9v?#nsx!c>&f5S+UWz5}D;AfekWDTL7o(Mx;Qx&UF_(hCn|Arw!_PZF6kUb% zlL<4ole1pKkP84sJ~q~B6J5(1a5@qz2X$DkM=Zfir?w4oY@A*#zf zr(-a|B}lCa@ca^I+0^7X2n0&%ku(ivjp~6+%X&r-a=nD*8i{WowI^Nv5ZB~q7I9t6A5M=j(s5kgA^?EMf7Cp*s#V0t-WV*vdiYOroY&6X~ zT#~psr@Nv$J~QU`L<1s%sN;bG&QY9Wp46+(UPNH@j8YVD7TT`;x&(j;Er zz&;QpfGrm01gmip)vsGsHV@whYM*F?ho9K!B><|h$qP_CIUb|sd33@iEK0)i%oa)I zKmqIwhNb(O>wN+q|I`U7$)vy`O%QunwG94&Q}O`~ZaBoyu?_$DYI?*ZWthMB-v&Jh zD)-7*PCzIRtsPsWP$o0{PMBF_Ov~0FXESaHl8B+LMbfw!15dz$$k(GJgMjO!+|k~` zGBlVcQDM`!Y7&7s;_@!n5?|B%pNZaJJ2QWzerTSi48cip!u1Ys1)tpp?zE|^EasRJ zmQYl8a90$ZxMdIV+ID!^03nzJQR>PQOdGduT#kxmiei&;QjFkv)3qXUReT5iw#Ok! zbQQ@b9@?qLof4Hif9vZ7$b=$LaQCQeDUGX``9qZD`HiZ!YAI6hreG5g&m=L8-LmB4 zvvM@w4c(&Vdg~%+35YswR?9lAXrIg$f$usWp<`+mF%i}Pf+!5?8mprg_D3CpVxE;3 z958%C%KqZ1nhgg!1)Y3fJJvyRP?ls_i4;IB!*1&W0_kx5@J`HoOKg3@Q+AI0H0Olm zq@Yl4wvY4$bpOQsibz3q6iiK_ee#+)|le`yrP7av8Ynm`bBjju#HBlX0jH)1DC!vY`<|GOqac zOD+moa+gflogfKr15sZSN^Ip-Xx-7tfzmyN(vgJa5@xR<$i&f#fp)Qfugp(+VX;7} z7^#t6;d+Y|dT_U)%V~8%BDxGme2Q1>9&=fLoYcKlJ_O+k2apTn%w!oX>IIA-D~>p5 zrcG`-eO#+!kO-m|0&#qnWs#5;pF67k>SlS_tFWD2So8ylc%kC!a^+YV4V^JwK9!gN zUH$Nd@witaPtTNn-pps9hr-Y(SHxFH#%uk||929pTs{T7_dt>B1KBSG#5Y8}ZFdN& zNhH@vBvqCC2uxe3FiT;))*LwM&}F8^dOO;)gU^U5fk#KLN*1mdheu60jDq){kv{Dc zI4NGsUc%GV$@zg_ftC~X@aDL9j&&}QDzJ3Ur5fz#67}Vwz$%;vFLPOi>2PdAa62@P zR2DH4z@__$caYr8_Vm}vDaHISP=LT;Y3h2#n9-P4GWcY0De9@#!&%WM(XC|BuA=EA zN|kLKArWF!n$)@)v#C^L(XL&J* zg@j_@yl9&3;#;C>tmJ5@9buN+vllU);V?N_iqVufkiR2OwHrFN)?d7t+uAS5Ez$Fq z#WMl57oxnV5rc|;v}?_9>IP5(qdi*yS<*-sF!6f|oIXJdUFM0P1bh68i=d~n|Jp9c zonb%tAmr1Dy0CXQbF_xr5c?jrtm({hRZe#U%?_M>ApH5^w^7+I4J3VgGMs+ciG!=P zLLUxar!HlK*$o|9i<^NFCwoqQPmj&7H`&y$jE!T5axWmbo!e+w2AH!b#O|ZY^GM9k z>Ev~~&Tbr=fQ7-g<;=-HW9FOq-CHUKv;5h)HD=}BNPMmBz^OV7eW#m8tIAnoI_25Z z^mk{|z%Bl$r^(<&Zknuu*p;k(pKX1blu9rS3P)%I6N?-3C+N$N9bx@z3JS@q(>W|QwPf?P6u@<1&SZs8uT|^hF*DeZb zc`!PcZw#D-{hHppvPkQfi*+dewZ>`}AN8O-1I|1FVke1tLHT>@=cfLo(V()0Dn<&*L8S4u$MSVMC7y)`5#fIN2myE*HD*4S+$@5JPYE^{*I{8n ziMAitv50pNE=JjHZB;>J_OgH}H30=6HI9scHijrD@X|1i{s>>u&a3MB{N-dm01mAI zOBPkLbJ^aMKko8;Qz@CAtXc-PDWH-#*;Tz7wkB1?Wkp8{Et9UYr(1hoj|(r(!#RuM zp)B*aHHy70dUi39Wz=v=(On#XL}G+KI@5{D;S$o>gDkcnkxz+D!Cl8Tz6|0LJFDPp zIikPU)5HmvXd=LmS!Ux*+lbd^gweC9O3%r?dg}ufy~ zFv^e47+S+s7FG2*iMsw;$)Say>Jkbmz9kfczbZ70nuH7r2}!<0Ji@}Z4A6)({R5Ac zuabt;5W1%UGi1^&ME>!>ve7J@a*hQe1x2?HoZDNM;UG{W0u|^4mzlC2)u_t9Ik_&u z35;Z6q*o(8VjooHHUW`Ed9G(<6Tr8uJ}(uLn}MNg13t7CTqp^@2~6mA4s4vS_azV{G<0-)r$q%D)?w4bUNAHJZY4O?Ldc$8jS}o zjTi_cwetL^-`eQ=KVk8ee`7i{-%J)K0TyIq@5x>68{y=hN~>UI5X<&YmGyrL*_6f_ zDpof~b->XAYHnVc{ASq%7lxU^@9ye!(L&5>r9G@4Cu)}o1iwoT>* z{vga~xfUp3k%1IQTi0-G-^dh1H38KSqO@lqt-(0e)491ef;U4Pg?v*kA9frA4zCE& zJied`4Z@0RdBOrX!#s~EOSc3@GwqOTtQCRdPnh-Jn)B)^2))3K#rTpc0Vr9cyiMTe zyY>E0r|rMK-*(#lKc6>#<@4iFEE7AD9Qicdt zw&QzI&(&8hmnzZGkO#ZMm}W;o|MfJ(`yUGm80ah4y)}>iV;Bkh$M9P7@k!D!k>NFnlI}UE%einBl5w4s z$)X92se%{Fy(4;3tsM3A%D8QqOH`@Qe!M%)TjeB`;T=Im{T=Ul7NdZod1@sP$RTiE z=2{DP)GHh0se=2sa$1jhS#!yPiw~)GPJu^G36-@$O7&tM>EUDjT3ddpMcpOyb?aL5 z7}%Ncyo=VW<*Gux0Q?&nUH*4tqVx6dpSd;@-cLA0i0iDO9D*XDVodgsQx29m1fyBR zu%d!OzD^(ncn==YUPvrX-j;4I7Z!dfE-o(&$CBPyL2THt>ALMLCr5m(3#9ugs6{ai zi?$nf&q5LvTbD7_63k2HkmH=dV-~5Qbq0C9fkg=KsC*tm6xU)~8(2;Q+fZ^g+)H?H zi|=Vht44z;6x>N2W+qjuQP8JR)NoGG)kzJ`^?DBY%qN7KzId`*MzSTVv%e#gI2>KZ zKo_kh?^=}xl83?bvuGBnW0{4MwZ{`lf`%;Rz}CQlx=`UaTMC*DCI}z3?$`z2N()yC z!dxaEvroBeecr>24;F|QBle2O3s%;P8C4G`A*MJ+WZnwpX)_9Lnka$3#Y$Fg-OgT+ zw^*;Xhq5*^Ua#5s5mL|nQ8Y8QI21F*W&d?rRLN8?6=7aALdNN0`7>c&m2c=`FZ8Lo zRixg{4E-~re!Jp7{p<57{nKWw_8Z*tw-X^aZE{Pa?Aj`>;+0=&-hq!sX)EPj7O)N? zi-UHGHxR4jg$Qn1XnRIR__i~H#nn@_y0{rCVu=bZOT>D{xA%i#iWca#^h!8|&heD&aDPrTcv$DvrJ1w-qFx6vaj7C-xQ1AVWcz)kMsTV*D_{L2olOk zAJorH&M!$)-b0Bg`vS0?L6x5CIedmcU`>f2jV7kM9VQ9pMN5N&noWM|aTg<66#W)X z%*^FVm(3uPUxSDm9kg_O^Wpw2ZBw{MpZm09)P<)cHv8F_l|epQaRJUYc>k@`;4h6` z{ND%N{Wr0U90(rNudfRu$XfhY5eDAvYN?_L{cvg=75pU+1(V@qxho#oh1Ub(1KY$x z1ceaRu;mkxl-GE zU`FWd=WohRMd(0feCiu1UWrKF^H37vsQpQ_hsAKSxNCkM+u|5w6ROzm^+d09fA+~G z?xt*QUNT9jTcIY}@`v;F0}_jJm6BR_D%BsnphPjCl}-L=sX71{&@LDR`!p-%P2(kj z?!Nc@?-LwX*6AATA=W^uv>A`BbgxVEmvMU9qOC$wHmJ%kb_<07sj+(~-=T+A(H*d5#x5~5!xJqjdua9 z9E1_FvCv>LN^8n>eWe5DX=W2nGHfI3YUv($NFL@sVU~H!W4J;ZBfX6{WsXXImT~Oe zSzyM8pw`iI^m56^YIGJ-dciZ5cY-Mjhk@+r&ss7Ae99HX;iKSM-wALvy|PGC4kw2A zngjS+ZA;ZN1!zwb5@u0HmWq??qmk##~sL;r_pT z_`545zX>&#NMB}rU%w1)J|9=76#hLeO#S2g;=8i!O?4}}&-4BItLX0Wz`9ZXy!iEY zFz4U*aJ9<>3`CoA%$by)+Y%3M-n&#A^-Ak658nO)9|HzAU(dj>^zUhM@gLs{o^8XY zm3ZP$-{)h;=lhur6*6K%qb6Q{}+~xdNj;`-+QaS41C+!Usk)BzMdu| zYDSK3nJuSeF_-jgI4g2|?v`x{zrTjE{e3@atREEbzkP+apL)kE{z!3TnG3vMWY4+N zI<%T<>7GP&8#lIBP(Dr~`S;$_ZFWK5@%u_$tn}#Vy!73Uhg{jip5)i}b|c8oa}x|B zjLJ4jY-;h4l@>kb@A?)EKIPl@AVG?u;5uT1yVcE;WW@LCfc+A|Ccp<-!213?5K|1b ze|&k2L310ua9yZqm&zm6%xdu!ru+J?z!(y*aB@;Y_#{XtVYx4(O!)pOJd{c+=! z-5>J5+44_6Or(mVF+S@3zdsIl&AMt@KEKN6wvGN${wC)K7gzA*a`W=JM#v^&7(JB| z78KB8pcJg1mJlLTTf*OdU7|c~(Fl;J|7jhk7D*fBs>N}oF{%Mq=-KM$;Oy)Dl<&;!NA^slli}L6;WXHh z?r%!=rDY*Dhrdhai|X21jE_pfkM0dn@+(@x0@Ukn$bD_i!8T{)Z23Ae6TRe!!YgiW z39&gQPj^#b(&Hd7KLd_X$ zoX>5&C(o&;CV5g623%3XZ&ApK$h}4c|5Y;Q%H}n$RnGdV1Ye72jf(j` zxpwgg#zM@~A#n|WPxr*0vqcrhG7@u#K3YP(7lHvSh3c9!bz^K`SlS~Z{J0=G`22a_(Yw=g$M54jTw!cj=kzjMZDi8dDZfQk^tJ>a(8&8tH*XrE>DD;qZBkE4iW4!EaP zQMfx~&^-(-XngC|HJRzLKQ9;jqygZ8n26Mq2Y`z2RS2H=RQ``~kqB}^N?2T{AeWVl z;# zK@=)2bjk}p#^TUYa}ZGoXw=diH<>ruk}r^LVsK)ok6#y%#1ZFel$RD!W<%~JMQq#QidWOsEKg`iu`bFdV zreJ+-_Y~XhxZY9}igPuPmB@fhoboI=KHaTm))9hotQs-!7TUZCcx>_M|N7_V>HqTS z;r}pM?!Hpd=I0cW)3xr6%Q_L?4z2sv)>3vr(RPU*4rV-XmVsv!jGwuaW9*^4ga{E0ILEg*;CD_=J=a!n{j!iGjo$Cam7sA}8Ins{z zX9r{7eP23;?-a4g>)fdgtYnA2F6lygi)^S==XjA`;c12pN`J7CO7@ zK{lJ~0=V4oA@qazv$R3#jdXFM<*5x0Q4qqB*k8^@o$^9M52hnx)6$PoG zM6QNe*H`c(yeo7q)p0;+32zW05sAbf`@&4`+3nl9Zr}b|!Y(bcR8IGvevyoUiwS-w z=Vq>+2RkCC>M^?muNyQwZVzAz4Sa`(_->b5+^#qNPKB@sPyC!p+Dp!`IEHn_DHn zNAEjm_+N5A_ei$(o_-UuPG7Yg-YU5P#qr#J8`leBYXesr9+Co2NEXHP46bP{JNDzC z5y*(D?tixD92!4pjN7h|A(xquiZBk`g0Vw9qMpubyDhsQ?= z{wWVaDF!h}K7I^>74!gLyPtPxR*Wt!UqMm8+@&~8Kjwx;3FMm?Tz?ZQYSH`!g0jlj%3CnJlY8B)T|Aw%2*7&VMsf`~hlEpu%d!DFgn!nK+RJpWnc0=Zp zCQ)N7s_5d0lUMj*;K*Y5;~EPc zyq)tuA)t}}P6$1~bm?eiwC~AHE1Wzu+`&bq<=(dY5N-YX>iCLfHdDyA_uowPb#Z~U zG374g8x4XVr5zRsUQ;T{`p{VsKh){&M+Oa6KbGD+7h9C%&O!_{fh8XywWDXl<&-wM z+J+A%Gh9;$V~|*s){KzY!vRsqNN`%hjIpl~z6AMwx?j~G*Jf0FSF2};eV_;XKstdt zgwBCR2tch67ku)}2n#9WM1i%&9E>OFk-DVQ*_I@hO&0vq3nb=ugm(TZ-ZX}p7=6^Qd6Coe~u|jbYLd{n;1?N znoVu%&DQ*Za0kPe;jlqf{FJev|861`h9gEnsUveji+XJmE?jih;JKi$wg=jB@zEV z)SgygM2;>OE*Nyqzv^i9vnEzqvwIl%_u@ZgvFg$Lbj=@dz^bFUOGQc2nbJY>g&_5S zQN>X?YR@+g<0ejU53`VG{AR1RO56HnO-{Z-vcn%LB}&morj16@U`E0hhb>XNCK1;! zv8@!&Ee)@&1RYlaPC|1UjEDl})r{hC z6D5FCVp$|=FCyeEA_S5%`7K3x+(mgXN-VAUZAE!JMR~AFEXDb)MR`Aq@_s0>gtlv7 z*DZ%OG+`q+5S91(A8xdx6#Zt3*ii9VJ<^Zh8HQh%kE`pU79G)_m+zb%kdBDzHC)km z>{8DbR=tFLP+#gK1L*!ITp&cz9STIo@D|!4WYQBU1yTd%SG{1X0)faJ!%wc>wpZF3 za7vC7NAIwWR; zrB*&SRYt`NKojWKttNoaGMXoZ&u|~&Yu}#DlJo)geG#y_U31Gr9XyH#w?NQEvo7tE z{UyeQh|~sT1+KX}lp!{Udw9*fz(j^Wpm# zh&-UC+kK2yUSmI-nMYhM-x&Q|W54tCZ4S4myk;I+;AzPIPuKgLCcbj8IhrBolcPcz zsRI-b=4B?0lXlxk0*Q)DW~FpNjNjKe@-)$n#DR^ljVupXv`8FZl?<&agaEWPQWG6H z>204ES`IWupb_ih1u6BE#52~WBBR9j7bj2&#FtP0WseCdJx7*wxXoO+>&Mom`)!2I z{d2Hih}U5c79S=M8rx$HF=k>1JG37Zim(;j*o{k^k_;2_7|ZlBI}H;GT_&=%Euoah0bzXk-A2>ii=2i9!q&!S z*Oc8|C@lXHSx2+A&66p_<2Ndha6V3K&<+!F{}!po7i_Po6}FLRLo6_WnrE^GTK-uC zf56)R$fJl@@M3Qh_>eW@|4Iw<)6xlD8;e^bi$M5lYJ+XeW%F=ikJsF0vwkz&!D)LU zWxeU7P#q4mSvePqARtzma;+*_dD+7kkdF2X{OQ0tC!phxi4{GK8XSFF^ikU~)lgBV z&k?b(UL+nMC~!1BWmDQb_v0rw%}+4$dlZR06NAu@Ob-|a56D@Tu}UrZ?TJcL`DySU z{PSDvJQ=9*WHTggs#l~7_>s>fIEGStd+aRT(ub}tJn#*CcC<4pmcOb<(qQ8(@sgYE zhJ!cuVPt~#TX}oZhT`uU+h-YJOWl7-HL&lIx}0HJ#A|J6l`#qPQ%vtcItjvjQqliW zXRC$1-@@wcM}i6bmvYRM^-D|w%SgOk(0g>TN>QR@Y0pN9OpqAqjR$Ft?cuO4=)RbU zf>>OUWnXn(rR40OlV3hH3`L-9Dk;?y8kZkOl0PNIYXmK5KV`pUjB{Yf$qWAg9%D#K zzEhcZiYm_&!7;Z@b&*@Q`~#xImNVdw-Xf7K2&|b=hgsDLyi!YIk7_?xA|6E2m&74RGKsf56*qbohzFaCEpT- zqMWYkla4n7R;vo@e|AE($to{35s}+~lCRlT`N2s`U~a-Hfge&2j54Xo%nlBa@UctJ zX7XW$!A9fEFy4F%iOEJshS)6dgYt7r+ef2_VJt(;nAlr0mumwK)6DpA@YiLo2Zr26 z*zyoi?m9fK%sH&^Kp)9CzWyRT|2wM~P<8H9ODcFa}Zuee^Byhe!AvwsB z9X&r2gb{$bUnB%gVnWJ*#wi|`|JNjub~-<;;+WXPwp@_gEfvFx7UpTPKT zn(FdOwbYWF4;Y~i2rF7?VUQZpXb;fVXLD@wYtz~wmD%=-7z3j+i9*~Eg=<10JRtIZ z454v*f~83SdVs#j^s`>k*v}CyW@G8DEiCeVP>eFh)Z;m+<-ta zpdOLFU&EfZ-#!l#rkGU#Nrpqu|6Ch&CNx60%At~wSd3jI&S^9B_0 zEL8b1A8Al9S^UHG>^zXexIf$G(zo~o970|h5HM->*u4byjYcE<1VNb! z+$p$uJ`Y^b@TYG4Cjb6j`L~IfR12NjG|@icqo>p4XoX1g=twywehYV9<(h(yYqimn zaKobMjO_3HzqFIrTaOtS>7`ETOMY-9l*Q-1~gYM7nS1JS7=XeBuH(3=%Z{TL~KO)AC^)t_2ObIvy0+6aUQ6H9n^+eXi$P;8S{} zkf?>^D{U-#&6cR^b9_}7w0hg&N(an32 z!-5>6-)(J*O5U(bTRx@k*RG#@6H#>GZ%5YWeVCk7dDBv0e78sreMc%Qa>&J5a8iJLi%_6NI zCw^kuYmD@J1t5HF8tyZ7d3;VN6Wb#^bhv+FUit=$heV!Tj#>CxB$s7nTO2|) zibAX3DYRW(PnDc&FZ<@L9M-6n_4ZY`d#W_{G2=Hu^HZzGI=7I8zeKqW-;oHTr)DA& zwfwVvTWw|zYfO;n6K?`1we}qs*taRY`^* zH%0F6O;T0^YdaQQ{$!~Bo*9a;5o<;+$_js4z_TTURz~HhkDPmnM=1krQ7RHOWbo-= zJxb>+Ud;`~{cY*AVM+)nK?m#5K&p^tzP*{4`~yt6<<$gOPsVsO(M`7G(7VEfDuJPw z);;Vc{ea20Z3CZMR^q^U&?ZphzFAfZy>i_(=facki>y`ajTbX5CORT5Tg7cjT3=U^ z3%0QkrNW2^(ASB3$hL>pOFnXm)52$Q!mW3_NgAV@7>e(u8e+1}f74hDJay^tjLcZf zO@Fdleb{}a%?vXOcGfeyP^Qb_B@H<mmQSl@KQ>scKc7+k5 zZ;6jPApm-Z5linVUw`1$x0*_yCSuDgLOvFXElqSqq6fj&9%q=36yLz?y$ zD4%{iO?e8d^KDW2l`M1hIS4Kzy$9^7=)IkU_{u5wqz{bJq5Kup7=7kSU4)t~)KWAa z*ysVl&%B|{U7u#t&sXFVj4N1hsdeVntb4|Ftqh>ypLMPrLR;z23%hzpl3IU#}Hrd8J%J0<;PUdQKDTtMJEmqIq*e^P;<9 zJ^K&pgkNyk9=}G5+coH^3J6IEd$;<%0Q~!p0D3lse~hXb<}?DXLNE(cgI@fW3okF9 z{R!UG`p0=$8gJcIh@#6MZIY{Bq{=IQBwltvD_~iELkCl9GiXS4=tyIl9@5F@QX|g+ z`zI487vY$76Wr$ls<4l|zIuaxtr-8dXPsy?--DKz2J^0(3*=R66eHoa#C`A1F=M_n z9HD#nOJveP-mVGby~m`@25QV)S?xgYVwvq-zrc;BZ-zzR}Co#&D2M2MGZAne07QeP~bt6;w#GO0~w|q2Vlb=OV$KtqI8fM zreRW_YVdjWM8P`>FfCi{lpY$^6qZZ(f0ID z9O>J28cIoV*Hxquc>Q+O_l|+fEa(73im!CT!mN5$cg5^%f_FqJjz9C<;f^z9S6AOf zo;@6pgmOr>zPBTCe|1v#U^B`mph2S)ZHEk-pif1AcynzZ0&EuwXyjR=p5VXP`F8ws zhQn-snhWlx|Iu6UUASYi_if-mKJwLlAAUV<1&m05)xy0a@TbS?+?~H&r>fPO=0T+7 zr`+`4G+cInz2U`2W~eWF>7Q@k*xqlayA{>kF~$Vf-Dl?gtiMbT?eq6A!P33+QL1xo z{Tbp-48%YGk$BSxe(wUD{bFKsx9Ivy^0S?Bufl_H^X1aZ$Mebd6y8&9+|~-|(OTU5 z_Mo{$=klV z-^RArsVKTUl25ys>j>VCElTK@pAUxZ>*;}7UX7;mLki8})HeFFDJ<~|t&dn}|zc0ydngbAW8E~#U$k={7O5Gc7-6^uf zml=4LHiE%P!Qz=u=BIV#aoJT&Y3Jo$&1d17_&f*2TDA`w|L_%|nG z+kg=1rk2;*Pu6!4BZCO?W|5}3q21~O=}UcG_ntfMk$*rUQ5zugTk^*L#S`29sk`#N z^42Iuj*oD3oW5dUhyRyssdsu4Px_S}m|~y%kG+Dnz3<~df?RSfl}tXaNW&Z_lTflW zGNPUB&fOZw8SR~An{Q)7(ewB~I5@#Rf1j*`q?sqVY=&3{>cGgMmP@OWY_LWTTtwK| zUV}eT{0&t8?czrw@lm~Nz&MC;E7IUUB&XHEeka;AU}!`9MoL;-fHZpO#=n2>biFI| zsBReY{{W;wTffi3X|b@KDZA%ewnajE9Ymxz`tjrRUJ!b1>xQGVjl05ISJbBwd)%3jp zn>4kmhZac4JFW{eV#ie;H(i!62nIvCDzgJ#16 zI#w&MvoDG&`Yb;C!opr>UldhXZkpnmes#L)vW^mij*KG_M>&OseKWFO9t8Qy-_I^3 zrSB|OQfg+gk}_yeRBY&t$a51lZF4G62vd?Mp`QGp5TRm6_htJLqq}dKxbBF>Oz;-vWz}ZRu5^42$s1n}+=C9%X0jmuBAU+xLHrgI2Jr(LG!iaWbidOc`t;URrOnq^ zIA$ExG#8YNr?}gFElo;Xw9A<&DX|5`Nr?dtyXmh~QtROiKR2x`NjRD@^#Q46i#5IW z&{XiBhmSN;Okh|xg?@nc2l__$LAv(kN6JYE>&D=Rs3t3TUBZ2-v*HqoCK#+4a~~l2 zuk}RIj9kT2wiy9N)QnsO9-Z(P9hOzqW?|}^v~1ceH_c5Ob*O7jf>=Ba2X)5V)t?i_ zgGHU0BFVG9wBg?KsN)5X2l^q%>;t9XrW_-J%szkxHQ%6DFy&fxdBe`RT1YhMYQeBs zS5SQ+8~fOed%zz3cU^!HXcjO()ELg0nPgbn~2G)2?h|1NwCWwVex z0l=g;AJCxtUhcjK@B98Sn?=zH95}KVNNqBE$K~_N0*&}PI5imzhUBrB^^Il zI>d?S`QgvA5d=;Jn78@xA>>iV4IU5iWB&SZb{!Z$gm;AC<^%OHH$A?iC%NfKBjSpDE&Wu zKCp2ab>a`Kg}pwoaT(U6te;kY@-@f&m|`C=BB(Qf1?hzlVQCAVUMHd!95`_c4s4M8 zyT9q4LEhD5Z)QLweHp+$s3!wKoPz3+RZDcIF(RoRfCb&(`{zee?;?uZvi_+r%}G{3 zGLB-B3rk2)?EWPsH&t|9ycKd&EPg__nZS^65)HcD#TQz8V*0&;**rJS?WP$=HN}PA z?!VT5GT}7t`-cHGalD1X^TlVsoE|>c`=gAT{fD5imA-6O546l0u8uXX z)~g+%aoA&A*lou-mWdgpl;D(NH-EmcVpCI>NGc+Dp_Wq0yxY*vy)5&jye>ux@x^!I zFrd`6-uzDKifR+xly74Pqz)sFMjBHpUA=72y*Yj2D@P^1j1(e7`_8|4mN|93oDKW20?B!|I!Wb%YCewG$W2T^=IqY&k;+D33ZW@VMH8 z&x8lV7NeoO>u5A06|jyE0$%OJ*Q67D0#ly7Du^Fvypv2yapoLaYkgJbY=ZAVQSaX&Qnx*W}{l-dUz~6>NvsU zY7dBq;U@mJMa&%WB!zU7q+0TfuRrE0N{lT9eUM2|P-~8`@>2}jxleIoqP(?DM{G04 zmdk9YGa}mYLS&(I=tGm4@gcs@&d7Rm0#}TjZ+ilCh1Foe|O1f8?+2}T#%XQyy-S;vYOd!mWO4r zwm&D;c7>0g@TlVjk83@6_VB>|BJ{xi;^6`OqO4Ki!BqRIcTqP{z3SFb{i=hpw!W?Y zJo~hqffg$G=&7HXu(y~*qTKnwG z)RS|!kZuei%@nBC`$*5r%*(t*-Plu?k;X9+(s>1S)3fSqTjq3KNdjp^l)l>vGU?t? z-ezqFjZ>6-*EOyEz~J*7qy~-?QX{QTThgaIDw5+w8y-5)n4_OW0|pSF`t)cAMH>&v zvfmvGA~$iok(;SK`+TmyG(I%uCMy=@O%)X;zbT7+czu109PfM#b^aCW7t+6eyQ{Z{ zyqV*ppQ+l*ujM^K_}6$=SlAJKXXVikbS;%%l+|B!MQz${ltH^|P~19&Aty*w*#YcO z93ZL;hdx`=mbocV=Ui&wcp^1Y`m|y@wO!n}j{sk1mo0$N-t_fua;~#96fngiG2;lO zIc2XD#L^R(S<^;Ey#MoP(h?JnP>NDcPJ&GGyS>PYDBs5k*a9xFP|P?|X-+x64Pr02 z8k!Yu4aL{_8k!Z_8hZabRYTAA;`kn0SnmvUk(Du9R#A*P?gZfILr_rX9W>4aW9mcx zn=;PXwbTJ+AGw2TKMLiV{3xIm&QrP4g}md7&_?YL`AGV(p+gV6G(R{`gQk#piqt-X z?H?0CEjmm(wB<1truj;?GCwx?B&b!`OxdFc&&YSUPsGsl+mcXMg8V{tj9?@*o zM;6LjZ&r8b=fe9{9#=fRj^rXnJtOu?H#qk1;z{851V8<2snChv*FSth4Nd#QOd4uv zS)Wit;FXe@jF=j)*MOt`LpPa7H+uCdZAtr=8=Tr>)M> zZnK$qRJ<-prqYUMS)Ymrymm0R*-&p!pFj}THiYn1Y>x%jtIj=C8!J6bPjw6DG#eU1 zY6(z#XTPkbvRL=SmqifrejtUB??HhM-4}Ym*Hk99X?71?@Z;!mQ4Dup$UCkGZPX4; zMG<@HBAW0KdqA;Wo+GL3?WA8;vfhqq78Aag0~9OyNGc_p-4{mk@pErWLG^_K+3>tE ztgIoR-K!_jEaW|jX5rV9XcpR@#O}*XRLu|HKE9^+AUinU!(m@kvpUneHw#lV$9F11 zVG|UFbW^A{WFn=>!d5W462vV7#YUSRNo9=&$urMDekkn1Cy?Lr zzJdH;qa22VLl=B}&^&5VVa{Wn%yuW#?T>7}%tyX`i<&UR6N(YDmDbc|0_ z8q^PWFSDKR(ggLm)7Q0ck2`H+uO2t>-aT%x(Y|}HYiVTb(5xOh5VqKvB((Lkr8Ktn zq_y_FeO=E)fg2|az2GA^PTPGFg>Ia*)xPJi>kG+9JdKhGI}*2$Xe17x_O)MaCVnyd zX*&0b*$3P=WT&FPCEd-^XGO7PiT1DzxOnHv z(L_731KvzU@A**DjDNXDuCl7IweR*$e_};viEjP|6o7Amw_&VEj1V&qb zc6SqDA_XX9DoLVXIcWlgveAxzKsX<)RW@ksg9$;fR@rFBJRnoFjNYXDGJ2EBmeCvS zIH%mvwYhW*~3> zxLb|!b$0L$jIs)Yz|&P2B`ZG^6)i_0ry|-BFS5|N5*@$Ea=s@7Yn%WCE^$WBY?$3>@j9yVsW3hVPijELFB4ga|FLfxeLtTFBK#fxlPti0 zWTPDtN59>k-}{-DO>+|^OXLGaT-hY1Rl0ec_6W^5xwn=0S%`NNZRuIp5(qFJv~hT{3JQ^wi~`S3I) zTeCRIZGGvdsgPF~arD!eTIq~kqi@E2pg1aqIw!;VmHT%l+RZre>i2WA5u@^u2N-cw zlbABxAYQRSSED7^TDHBW)|8x_lqk+HNgnx%m zm}w^j;=2vg4Ln)e@PwoWj#pA6wNF#8{uLB8llQMI?bpAGQ|){LxFVgN$BTP$or&h> zPg)A9;TdafZG5?(hG6 zmqw?=bt4H*0Zba35^Fcx#4q%W)}qVv;~na|yGb%yIu)>vegUs@BH64&PV}QBThNqs zV#JD^IP%)nQ*eT;{#8`BS>)cZp$f62;{Z#m<l-h(n#$yPBX_Fj z{ao7HX!}&#FW-{$+F6BzmGD(8b|69mlg#Rs4z`S1Bn@B1(gq?Zs|-k+3Z^tK_nV$= zVMCkGqmrr20av#5-~rv%XLUc1Vsmty*n})#9Ula|(uv=96V{2;WS41+#bbsSz2}rI zB8a8?3MMz^?JI~+x1upeGKGemb_J?u@|8OyU%4}WD|be{a%W)WPLytFkw;TL-H@eZ z>4p}$cAUO=pvUR`QXqaQF~h%%Js0>AUOsFDE2EcnbY+^hEX?pRWJ$rw=s+t!fS3PD zNv^g@e;o?r+{XMFxwD4}(vQj8$CtL5}!g#o|tvn1dbewGIO z!q3Xekl(+`1AgI(FyI%icm({y73BvgzxO$TE^kt4va(#TQ(%m%Hx1-xHw_fgp$&6o zU&akdK@6f}MZSe@+x zw3AKXb<~;~4I2o+(Tbp;0Rw2HW47WpyBcl%v0b_09b`#IHA^eypUGOA6<1l4^*@LX z02>>KPXikpeaz8d;L}v_NbuqrO-UX_$f8-X{gc^%D-EIc2$~KKla5{9J|MDm^!CSEY8- zcJ(CQv^|t{;q@v+7v8Tzq+BHfZ@7#x(Xz^IRuXrni35=b1ROBuR6Xqkr@S?7xvWsG zH32JF9NY6@8P~2?!hFitQ7u^izK;0gm)}V3$;%*lDv5&XJ1n-K85;#PVntCPwGcTcACIZNWnMJgS#psOQm_P(@v1h#7Ch z@w46o8#wa~!pUcln!1z-x13bCWj{*zXZhSiZN8IEAOq?%feg5^Q&ew%Jv+UF3mRHb z0qgi6;MGo?UFKPK%YF_OoiWLhjsq;Ml>dA?W8@2t$UKn3GcphKM;wv~^2xWiHkDoT zjmxIJ*}rIxbdo}{Nm40!`#fPJ+qn&1vZZ8_Eg2}84mq|V0Q;!a{hh&rG2_UkIc1Lw z#Lfg_(ZUG9NW|(FMnEiCe~aiU%KIfEocxxiuwYDvB)|p9pM978>N4_M_Nz-iIXE^_ z56|nTmB+E#f;F`s6)&yzc*qJ{?F?)2x3n+EQH?Jnr3g{>Rcd~i`t~#>)kIn|bYhEJ zdPvtq`IRl<)JFwllCR1E4gRb&tA{f)^*4*$u3_9X_Mh*kwt3W1&*M4|%#L1bNXsi@ zH_r18ypb~fZ}i8=pR)4Nf)vT{l0%lIK($k}og;?6<(ws1sR$A0DwLO;t*l`T%7+f)1{J63^na zBX4)Bk|i5C;_?(DM-%n)cz*I)t$~u{t2F@ot=52na#|7mmKA&tzxDH*Itw zI5Xa2!ZYKWR=bP`s%4p-_>+gmxbXa;vB^iALe$-{dqYP}c9$-si``wy?+SHr?UqpR zfUNj=x15{WmP4H1i8%fg&w&j*%k%o~+!=pu|ESZYDbSW0mUP6kv|2v-_O>QBRav)v z^5N?&X;UPg;E;5hRi5*6{qj7K3GZ)@KzR=er3c;gm*?r($*-m@^M2F#p{Y2k=TS#L zkLx_h{#reX&M3;@|M)YCEcHorMv*0zk~gbIKKLQc+Wx3*VF1J%&$s#5Ca}@Zo^A!v z9JVmK0_x+C<$WEpHsKBl^7Pok`lWOqmwF3dr+TY!x5%!>Var=tA5Jjpx55n$30TJ! z0k3povwaXn-5hR}oqQ_FdKu+>2o5s&B#Os*XQustXZH^qHn~-7vMZB}&UZU{CBr|l zX|CRzD6>X_H-Gc15{K1~Lz@~kH;ei(RfHd#`Y#C9HUxh~c^e*Io`rJ@$3?BIsWQpz zf@2_^UvP|+KJA|G<(>R2sTyG?-=d%7oqWKRL&a?Kyz|WB9Y?WO7H{C$1iB||l(P-- zYV9%ZipyF$2?wapBpl#c51!b>>Zk($=#$wPaQ1;<6QwuV?jP=XT-S{&A75wh{B^C( z{dIjNsb6dAI?DD5Z*0qVI6tC->s>M|(uyq{C&X52x46mZxPA8`a43pp5-bpo~3Fo{SYIPX15ZnRO>` z17Y~OzogeJ>2hhX2yTr{ZIkr7>LFw){m9Zly8Qc&EU>K%;~7cxoSxIPeuUqVWUZso z)cdAMFlfwv3X}d%L2#q&)cZ!+Y0r(a`jjYabepNev2$rh5iDtmW@$h9tNZxGp7DWnyl9&X+hM%auWOfW#VIU<#HqZ^qRQs;K~hw?1gvF> zfcG;Z`D@?rBOMpUgSj*Q$`+lGoiu@Ejx>>XjJwtWr&hPAO^9 zvl`4FW%064+dZsmb`Plo2W}#P_Mzl#Rh>QTsj8Y1ou>-RZqaeDQ^v5W+3eQv#j=|Z zDcueR=d-enaw=f?P|_Cf8Qm0&xDwv)3NQIia=)wQr1!f5>lu?7gn!q62uT&~sV7S} zjUm|->f6g?&wFmj7EQ{$n5YA zKZ4YhZ0xAX3yc~;@=&xtvPu>seoF)>_G*lV^qhKw{42xs#TE@*OXD9U<*paL06W6_OVQRH7`^-&(l~S zzhQ+IoOsUzj;kHrubMYBW9!dFz@wH4Jnm`1f$plzMx)RIjXGGM@rzl|;|4iXS$XmY zSyd%!P6-StCsE%9^{^j_oMN&`G~k_LvI&18??n2#%Vu|L>E*7C&!uVI^h-sN5zeF& z$4J0weS^?|p(A$C*}Q$8RD!{07Z(mfyGa5DqtoZ7KG&b(TGf6Z(^XNZtg1b~8dC(U zWru+GHbN4QH!g6GNyC{Uh@g;2dgt!ny%)F3rs?L}nmJO6@R6atg z@e2)&z=GZYyk;GEri#K^H*L%i@|G>aG~Nb{`|6U5L7I0pNT<29LDbmEbX6t~@t^}! z?0BOg!-g6l`8$E+SWT^4GiXR67(m}UG(hk7{d#q&@>#4YSr%(DG>d-_NXA)=AyF1< zFffaMX2G4p9nkQ-(5A z+ME+uBI#qh34%LVu!BBqw}{dd=UBUJCxIn#^GmJMwP#QIV!NRx_FQ8WC zav)nk)uem@6=>hjd;iAno6nOiPb zu0B+G6{Upd2muOeM-2ygk%0Cgr`-&-qWGs(Sy|UzNMP26ZUX;nFTf6ZD5vKc?e)-D zK4u8jEf<#Q``;bIYN&GV5>^9n*RUFp#B<;V);NXLfH%p*Y5?pORs#}vu0MkvquwfH zq8r-M@pGgWF}~9k5J=W>XotJExkE0XZj<7WV4C&pFhMxmVW!Efb)jgavn1QRbZFmY z+4bF?ZQu2RhD^RDIR(46m?ls}8YLv<5~14MNa`F6Q?`>&2?qTpSEAW>ah z7$&Nl#Ipsx(@v+7EAS=pAZt<_6|$xSV?%=c-bMe$9UsX?ge8}vJckJPe?1S_{Y6ry zCU}{e3YR%#b91tq&5%q)@VTieZ<+jVEh$qIyi84n%XGUU@ci}>l$iS%uzAJ<=n%admGre7slo@{C9@??|3w~Yobnur@4JC4+1p*Cm2L5>Leu1b}slAdtkq0Zq2|8>!>Ash04n zp?vD8X}75-r0^ULfhm&Pp-t?FWRVYL5vMgNk2swyd;@=PpI>_-*A~L_M?gB9I|BMr z=Z!$V?9f6|7J`X?Qu2YTPNZ)%gYBNZ0kj>}!fVKv{Ozv+6R=iA>G2wKOEO6z$pq;;d<4lurWY+M9VY=zN*K@*PQpRclJ)-3 z+oOuKYf!9R!xz)uKe?To7Pr+*07xr_d>wqB-q$?`<5mu4qi5Nsdbun zt#y#bbJzn04TUq7hI_h)xshmw6wGhxv$8nOGD9aglj z+3?<*v%9atdSzZEs8R+L)~1lz9B7xF7cnp4>yY7O)hAH+mGc(n>1KoZBojHxolPnB zm^+u+H?Zma?nUN0clM+pQR$W-Qp)#-o-wJnm<~5OZU@+%P*?z;r>yrY*OCMqf` zn3$$%Ql7bylt(QKc-+r|j9!fXG_20b${MoM7#o+dMLh@VpqlRqtn8);_FA97%pJ2K zFY$^l2EJtjT?VY(9_U-_p^D|VI$U7Bx}MuBHVkJerrD77n$527T2bbD_(HHU78Swk zVVm99dv23O6VJH~qzstbWRdU18QJ>IcWwhO^_ts2I`6p+r1k8%z)-T)To%b9D!!nh z8;RKRF%~p%1EpjQG~FMe)rJIW4R`^)M0129o9psJLAyy1>!xAPu-%}YT>ZYz>s9Kq z!W+^wgft^CXd^m1JP-PBlx7thOr+VM7g61Np3=HAJX4*ZK`d!$XK7FQ4^IP;ZwtI) z$osYc#SYd_q;F^-kSrY|PRoI0j5y`T=MCyRHqSO}IQsURpO!;eOEN9l?C!w6JAt6R zcdf>}Nxxu>Wn;!tOmn`QM378=qB=DH+(Z!4rD=VaB!mPLpzjyB|MyB-sb|7UJ#(nkGw(|M`0qfJ z(X%f@KBEDWW%TTeZ%6a^ui%FKSS|82Dd(1A8WRNYJfWVd?^#!k_LlIbe`ptjguG>k zFpalCL%Bh^IglEoSrimG`tT3V&ZEnNazW=Ilv+c9*oqfn953P4?K0NmSxk;nplx?Nln8g?oPoglO% z#twFfNT67yZKHy`z~|Q?7QUs5gXLo7jgeO;P>{D zJZ=RO1beAbO?jSl1errtW)`Itsty=ocWDgfTMhQFBmb?0G9PFz zo_3*TqN-b^pc!7JWoI%eU@iRu-p`0?{c$$yC+V!|I?S|hj`qJv3`wWalj^(I*WJVV zg%&mrI(`P(YW+Ir8DmVA~DF=DlTp=!GE%AV#K)Y00DFv1?w zGTbspmL$lg`!~`iJ?wI@N#l+-=_LP)O=Hp~1p~9wEeTPY+@Mc{z>p0j8uX!nc3~g4 zidG{*AEz;49|vgQ_whm0rFJ*JDd6V*-o^$QZrLJB5@M5D|2`zYd6g=KCOT)IW7U`m zlle}`G`m_c(un{p6hjwLN>-9t8lj0JevDPx$VD`c1w)$oWX=w0fDsL8fD0PZ%L`PeuP92?)0m3JEHSQ^LhS-7pnh^3jtg4*c${eD1yY)RQfV~FagSvRXx zhXt9Wt$c9`%NlX2AmiR2hD=4$&1@c7VXi2KtwKjGsQ%yTo3=v-5 z@5vccl-@>P;2T<1`82A%X%(v3B#7nHa8Mnet?AFQjZg`hm45jRy1>k;G!oddM3NxH zn#J9L?5)Z<9B3(3s-~53)taoTs^hUHU@cn&e26L8!^f!46!V@Wi<4=D76fSyn?SRH z@`<5NbNhaNo9T6;CG2@9q@M(_0W=(BLG-f!PS9aR#e(gyfDv_Azy*EG(fc#`F&`(A zNy(2K8dNr9Xz+`T6_&625pRcy?364PtE{zyM+J6t@K8I*kKpGdO?4lnTX9toT^j{j zHqdZ*2e;bXksm>ppR%k_zpRp?-g5n^-6s;TmK_2<#FXOU53(?#=~OMNvOclX>L&m! z8bd*A1I6KGz$rE7bdXkzuxd3H)>49AdT3v$nfCO{%PL7>)K%mt0v`=x?KB)T%Pn5l zSBwR-B2ihKCgyGJi8da!tl;rLJIK$q$a5W$p;{HXgGBlG-)!^O0!$ ztU>Yk8Q`F`$#O?qFi&Ddjxz1%q+ZQjU^JQhzP)$dCQPd3&}o}cCve^-ghWAOp5*XG zHa?~Y*PiT)yjaf7QJ&6JUBFuQ2>1|F)Zurs-H&rsLa$iCf8^7j&v?sAV9OXuf)&4oj`i)g>v=wOsdRM$*P5pj1${|i*^sV& z4wcWb>Rr0xfgK}yPuT33>s<#NxQQh#D_AI%G!iYl{)u_R;ZCb_VI?B;ddyJ0XONJExr8VuV?-2A(tTcqnOFVty> z3IA_3o3)=UOIrF_I>ZRLx04*X#znrYeO!n|V8jWQfgAQR3&Go$zj|xVs#NA}NH`)a z$rKfo*C2M(Cl{|B?ZhrbZ{lB2_YFv zG0BBBAaLy=nZ;%y$*j2j^R zXnbQJOIjwdbchlAH`)ofOqE(fQBUox$B&U*gal>uez&GZDW(mpt7G=%xN`$<&D)Je z32fLG4UpgRY7TEQPm+$`yMVQ95%3|VWE=Yf##uLkFAg28!+<54f`XJD z&L0&j^?-D$uae1&1v*`Wo@1SuImz4~-nTDLw92x6-W9oCzaJ=(rt53 zW=*Ox{aC9CJ+f5c#{sGiw5oEcrioRU=$WMpJr63xJuS>Ex3s#@BTE)~9FkoRv?_hx z8cV~^u|As#7YQmUk+q|c-ZLOpVhIWfCdmNVyX_MtTRT!FsotJ%^Oksyq+%u{Z=ZX< z;yl-}D74#nfd(m!=abdV}bF9orRPhf!Nj{~dO_25DJNQP%qhi1%=sYA zIp*06{$)JI)Izl(Em+brgQfjVP|pvf2|AP*zR`pvuw+by^gh`={pBA2*4bimWm+gZ z)}DyAOc13AFz0V~9V!pd0hMR5-O(kIR;tLNO4)B~xA-KmWr!p}kS#;X zmPu5?Y_f=9HkrgQLq-ulDGceSQGey&gLy?MH=Cd4pu%;LuQJq{5*SiWq5JI0o=lQ_Rr0zUR3`s~2Q;K$#aLp+ZB!{f<25DA`r9aI zdJeLwdTttk>dO*7D(vTq2}>?X`AaR<+Yv9dy3LVPL3g#)1J8sHI^I^IL-gFJ)Y4@=`DP1=wl9Z=r-yg@{rcAu z^Wfx%0xGQ+AAcw__c7(C^Q|Qkfe1?wNjZu8*gu>R*Z8i~t0hZI8GejpVZ=$(W_yn{ zHGxTgt0R-zxrHAiO$c$zr{526=QPoJ7%kp9-ZtlSEQ=&Bl8!6K=Lbkb_o0)5xA*Ni z1yQlc3ww-)A6Y8!V<#Q!_vdpusw9JduJ!e-@T)~}RV3vkZnJym#a$OlWmq0& z1OjW$QQ{LXang0{qY;5Xz}(7rv%BN|;Kxon-X7kuj`l21q`hRb zIA1`opC?nKiUhGn8g^9t{&G(7s#Nufy+u?dP_ff5rqY=6d!6DH@|J#K8aFdu|L&=j zWuC_M0XdU^`Zld5|v;M_x72nO6TWBYPe zO<5HxyY8In`}_c@=st8(us>{iibHq8izw^HAtnh+6G=IVTR%N>g+(Z&F}46bwQgUY z`--whCq{aU*HhpA@Z49>w@Ees6cCn1EPXWQq;LIn$CfoElIHl*_LRGQx$7%#LMp}d z7Pzm({o$-c9gFFB^yIhbHY#EjchoWTNmRS>+lkl{>|gH&&xcuU7uOfQp(a!qF>+7HW3Pnd2#kixMn0P;WXz~+^`bPOSD$PH6mCECo#7M1y;g& zeg6@6rMrz3LHIXFyo1Fbj1-Q9QwWf}j*}RYII_LKf)JY6lf>YQu^kc+68F6<_kCZ> zec$KHtexGrpn7UNGv%6|uC}wVKQ_r!b$wq|_w?O8bS7NsNM^!Q^z0})O->PS@S$@Y zOv34)bc&gl)^4AZ7@uW@Dm@o_Rk@51;c~lIvhO68dOU@(nyXZbOT|2^@N_zi8rQS0 z58jmzdWZtGPUW5_O|oxCwr$J_(zR(Wo)TT2;Hb znl3L4!RqT;uB@&{ua=8Pj`H~|uE7~{Ez5bVuE#rIWjab{T^F4Sp{G~#`Kcu>PEIXp zMdQ9MXGW%CI5Dolc~LEETF!O?EjIPSxp6fuL9S}eve8apseS+GbgD#|FqR|`^4{rs zoHu^TjM!vknFe8~)e_QbCDX!hj8}_mQSi8k5Mg3zVCwx=5`!gJpIIr8Z#QreVZg;g z23z|(Nerq-%e?$h3CBmNRmo`WCS?KdK$mli#n^0>L61|@>k5gwUOh3VO3P|w55r3h zQ?4kW8Yxf3bt{=GY?Lal9bLO)qgc(az)8Plu)A1LJ?n_BK$kEU=nF}=_PS}L%ca#- zA!ns(L0PF!$(WU0{YDWk<>LyjA$^T-qX=(R*NfvJ{?T>(%z8vfufu3*^n~QRK|6^Y zet!iF`W{D-(#RPpt|N|Cua-_IUo7WW3z{ler)MCDx^|UwuX%4G(UsgH+|UI1vCK$n zbT~n-XG?Bp$4Ktx;v!in)Tx-M`D$Wj_ZXSw3+w7y!&?YBt(KYJSW`@KPfGEah~hCZ z#baWM`{{Mc&AHVZjg^X064fe7(W+Xx$7ynY;g*hw5`E5CL^5ghQQu0gKGeIzn}053 z6hZ~NX1>=*YJd2y;Yk6<`zCpAv^m+EJ1aua$_0JMSvR@tQ&G7IUozVWQKLzIaaU zZcYm?+w(tCen;iz_@`1da!!fs2np3TdpbfmWDdD-5uw4v(lS`<_7h7+aoz9R;(f6! zv-C=g6<4&&vKH_A9l_6*l5Mw>0?s26B6hHCk;Bt%iv!PTBr#YlUu#9Lo1|SHLDV;W_2sx%}y_g z_j=)IwVYcGW8r@uv4RCRx8dIu8aiN+hInF;&dR0sW-H01l|s3MpA%BQ;kxHiE?=O| zh_s0tq7+sR?Cfj`92m!Ev8Zklk9sFEb%_fTNi2PkWCG6btraSj_$NFh$`bzZ1a{TS z&Q3j%J(xDf9h79z2F2N8+)0Wtj@+UDS-L@ulvl~bjz)v<(`s3f>(!D9F(1FfZ}c)E zqb4D1)V3q--jkT`xe6K!#(yDKodTh#Q?g^W!^b8Ss5^6HQayUe8K3~)13VhQLCMj8 zLEC91VM2-6D3p~kQna{mf&*8u;L`OvNnG%nvOB8K5*{tnNN_RZ!&Gdd16$-cqlp;; z^^lQb8ibct%Ys^OXF#ZdLgr@I>2}(ae^YWd7jheFOVHA|XNq4zGH%tArSl!Q$A{G} zyCSQ}&BF7nHr7I_t#vY|K-0n%(4NJCO|b*<9d$xa;z=xAiYJ@Jx1QOzU}+#K5bSGr zmgxjuYST{bYQHvbb`^injUYx%fjg1*EP2&8I}kjmkQ*hQnnr>q#;}-Q->x z-#9NUY&4NYNuvp8E@sYr*X$vJ@J}g;v;{uV6w_yyGrz5KrW}GDf&ctzqKQc!kv4Hg zlp^MgnsCv15}$V2?9H3qzXbOMoO+khrQUC(O*u~<}HJL{wiQFfWYznV->egOW z)}Vs1a>`F(?USEs3YYG-aH+CUTwPTI`D$)GUywOP)5zVT>85b3XYCj+rP;WJDQum> zRMWWR30#V%GbYy7Watg=d4 zr)H)ds!q+@aoa}T@yc_hv;G~+AOMYSo(P|i866Yk|5>@&V%Y4 zp|hdRJekH`>+HIj>VDUye}&Y;Q&lkQdgJ=!_=ZW(X@P}47zlYNlgeWD(im!#ZmCp? z;zS=aq)3zkGoK8z8ZAwcry3BDq+l#0Vyu+PvDwy%=Nu=Jr666dLAoinL^SbSiv+S1 zq^mV?E9H3p;B##Tfh;wLu1tbT`jkkLPy-q%q#$3GoN-6j{l#{&T_aJ-u$e{*_?7Xz ztUBJd+s`aDo$blLLkc+Q1mVmr-?2VoW5^i3k-zNXjIuGZ$&KW&Gzpcz_6FXA)SO(DrArW_Mw6q?J8*z-E<)m%9ic`hQzTx&raxUR`z zlo4buH|Oz{`e<|HNRk$50qRvT)D_q3WO98Nj%*J4Zo;FGg$ibLHeEHqga#L%vjc{l zz)r+OnGda#*K5K=e2t2W2sjsuz!&u3x#egkf{O?^7mL8-Z(7c4bvzvM(LX~D(Pg1< zC2mQL>uAH4AV0@ZW=JXU4YMjWmUd~iP+4K1V}S+{g{g4!$#83hYOGF~6lma3mw8+u$IR}emsaTgKV->0^sg0B`BBJ+A<>!e6f3ote>q&yXJW~ldBwcGK&b5+i}a1)Qc8hq$leQ>ThN!w+|hD@uwX(; zf-6WkEL?hdyfkb${T*1A@uz&*gOJQduDSxNS2&GwbX}cdXA{vHopZWqkj%FPAZ&7W z!p71nJ-o=pj0IN_k+@t>f=|k86c`bvB%*S)o{Fk|S90Z>3b8M9>Qx9Gy_%8G{FORJ z*iDNyu8C5{gJ~EkT$Wl$O1Ub_AEsa|D4-|k>%{o!2VXjP^WB5*{usXVv>C!_ zHXBa6rsj|IP`N;<3Q80*#%05Ex6F9Tr7mc?p4&D!rwk^d6_=fsTj@i+ZpLeDgKiIX zITkgS?AwwB+Ljq@DIIO2>Fm3n5U%ShYw(CcBVeuL$pJyx2naf9fGP@Qw>N0^rKl>j z9;RT>8q*Aa+$RvmcL1uo=tjo$vCS118(UkA8c^9cqdARwq|E`j$wW-$ePP#a3*xFG z>Y^$~qsCHlQV52b$l-YYnE+MHtw2>aN`RGNJ^0Oy`nD?tzDFq=K+&KcaIxVuJKI9Q zy05GOBnI_>7J)T~G(DKBjaH*y>Y9O?O0m=BFw~INA84|KFS@1$q^7j5T&3%}bu*CP zKA&ksQX5H|DpQ41 zP-!Z&f@)J%RsfUrmKd70tgJa*)lD?Rw4Cl1C~_2PNC$FLqt{Sh)s{pNpmt;G9FQB; z!B*TpTw*PAuZOxEkeSn=Ey60N)WbUH8r)k{Dth1Gx4zeDiqLAP%h8y*l!h+fX?8p_ z95!+_rOffT!L(jrvm@;q1wBDXAnJaCp1zxOQ>Qs-xyxQ>AZQSFedTSX%t5)qM8Lf2 zN;+youAs`U`N~^LnFDfziGW9%@Mx`57X)@wskW3V2cyPxLopA^u(+&xzPh%!GNZZ@ zTXpw>8mVUn?YnzH_15E%++gystg|gFs#~3HO&N_$=?iCJYs;+(yAiI^)pjJPInAp8 z?-V35L+zp>$DxK8$oQ+PGKU(Vsd0yx(hPt4eW!Mp49W3zwOElkE!v{fa<+wSc-`04 zqDAJkXt=XqhK6SZv}lnzEn1~BXxC+6J*BF{ii~k6I+rB_>!Pv-ju_PUh&pi3(UC#F zFAZl)CD?=nx|njq`XbtH2ww#UG}DVGDCjeAuqlV?4K|HvXiyJW@*3NX_L3*=)^_{^ zTb{Oe%MEM6ed$K0(H7R5K5AF#YoWPWT{8r;m5ps-QR;)bqttb{+^F7R80}g)4C7~s z!v&?L&*$Ea?!FAP)4R*v*WpFR^zRCG{flT?*n4s?Q6SRvqVxc1MAV@}I~E?K5K$eHl zR9TTTQXn!qL8eZ@C@4B|QUR2V7v}O5w6G+}Ss{>&R6L_|p6Be_QHvKWM-dT<<<+2=eC`Na8; zFrrd`s+MH|>Bve10+`DM>e-hL24ww=y2gUE|$$*a3wk-X*|e1z|6 z248Ig7?9v#fw3&Hkbt&;k_6C12ay7Yqt?c#aXb}h>YU1-seD6I*?4+}#2rIGOTUOM zL?m9Vclw#y!1JJ3H}^C5biBJj4-&(Z8a%o9;)`Ph#=ZNgoX(BYWD<-J47!>Aj+;5Z4fA~GXK?fBR>yb_1BBT=Z+to{5Er2{`MGkOl+HV%Wl8qr&|X)*|7<-!}Qr-h9_Pbz4gHGqmu`3 zJaX{tXTz_59=-gnEJMKlksH>Wy$xJD&c-eKG8C-4gTCi9Z)!l|mWAbn)CP#c9{fKo zf}fZHME+IO+PH;rl8^<5KyNs`USro48&67{3Xt30_S_jTFg=4=gNi)2QH*U?&J2J5 zBr|;C+syFKlkjW22-jV(;r24BUrJc02b{v9yS-3$>e(O}-xsYQLNp5HId$0IEQSJ@ z1%S(9G6FUF>ciompJWm0!pv>u+h@S3G}=iRr~Z2V@G$b7p3aXa9zP_Es*~tPVXvzy zxLv0?fNb7$VIbzVGZ)Q6?N`stLqp&j1(-|yIL6LhPfVu zdOswGw$tOhC$?RK5bsUc#`w-|yYIBA?Q$5i#unI7q1=a#xtrPS^mj6sPT(KA=9UX3 z!JC5CLUw;HjoGzhGQa&WdgZs#d%sPERJnTq&XqfzJ`Dqip_I5iu+;CUHWu9JcJ2up z!u?F<(u*(6#Q$BNnfFC|N`hfi6j6jsN8dd({Out|Gae$ukdoi%+>_m#^OH>0l4Z3< zA2*CfWwmi=AWQ59U8tjdzYme274hihAE6x|o_Oud<0nr2`up(fci>NR_dVIM;zBv; zWC|Ju>j*Zjd*y{9b!__mW1pye|ob~2>t8<|Vp0mIXr~$#m z%#zwL`q$PdgbLcXM z>?dnk*skN%+>m`Jzzx+&ISHoku*yW(DiVxD5NysjJ*Vu%iH3Q2=H-8&JupUB8;bF& z3hWEofk@Nx9ioIq9EK9ZZ%+&#dmTihZ;p$CGw61qnhoX+WkK+t=bfHAj)HH4*N-bs zZ)aBDl@03o=&dh@Z+&Z13e01*RdvR&aj#n^xyw-x9{%dgOJB?2h+{gul};aak|f|& zT(z-TjUMA@YH+LdBTAB0dfeKg+pBqvu1Z5j2jOFVjF^FJEY$>3)pc5A=V~7w)SwaV z>tixbmJM}@(eapwn8kh5X2at#GU_wqFvZwtyW{f|&SZ4%*=f{v#?lZcwdb<08&`3p zEHOW~H@9z~20yLX`3jgAh%|#=MBL!#1ijE0&vkMjC9h&^MY9X3)L=bt%uR+f!I4-> z;W!n&V!Q6{B`I|JFoiz0fLaQXD7=<=d70HnJ`hx3T?Nw|6jchKG-bpgm2(%MEUHz7(QKT#z^0eiW{CZt3Y1{ zR^Hq?3&U6=I<*#Q;LJb&{)@WeyVOJ|gVQyt?2 zZgzymr{3b0IE#RJc)pQw2qnskw3CvPma;7Qr2E6K-x&S+>*$FSXC8PLy3q{UKmEzh zfpSPZ0~#gaQ4V0<_#0qUhmt`>CnJpqB^4+=BuOl=l2>-I_ZJ+Qfmcy5A8p|Xpw@mu{x3Jh%78#6Z-CQclU z6TWgry?B32z>2^Sdc;zk;#LRVq+WonmMwOiUDsc`fV!gAfZYLgq@l9OU!rI^-d#P^ zh@ST{omy?sZ3Gpw4-JJ(?K$hgHUc<%)M)`-c&+N=D|`W29Xji|cMot|hN|}fts9%a z$YvTByBBBnI|Dco4O@kJidv(mc*06crt5aPO&0=_abO?A9wZ)<1bP@}mBfQ503X(? z;ckaPn__0%el2t1Oz93YUzb$gOr5i%mwtnlmEcwQ;H}e7`V)Y1lK$EL^mG0dH-5&S z(DGC8H#4{=?5Uqe4?LJ1J@YtpT+h7!+rgV(Uzj{QN!YQ`Qu?brzCbLv&tZJ)*c2lY z#2MSm#;M`JDXauItZuk+@aeM$&pv+mUXNQxdQVrRBRRugMJ z|4y~=>NR=k^QAPg@ftS`D6gl9T+bVOjLv4$g159V5&MK&Xe#FpcT~ zr`{2g076*B?C2U?*cAqg4RUIxIeJXE4qAkXN=7QW*Zw~E==V#`yz$)WS5KV&`u*V( zj}5;&fluwKJk`q=bY(l?vB?;(cQ zHcC7M;6JuO76ek8o@LVXn1f*TDx1c531-vXA3b|=_{7hrA9&OPJ?&*(*1W7*0yruh ze)rDkfs+;-j2G?z5qjB+JH-n!fijJSH2zo@jKMfqgQ_(zW%8y2lV8K(&kA1 zxZL$k(HV~?-aGU9N5mZS3khfpFS_7dXCEy`>ZF1D=eg7GKNG{q8!#f7de9m4`F<@I zX4dPCT9mVq47Y!HOF$GzCSAy+z_99#F`f&s=EkD`GOAbC%yU1TZROGVTavE(Ys7CB3-X5NO`mi0ZV*EAWqcc+KYkv*czpQ#OPPx@A=c=vcSnD` zFL{q4PO$&B;kkAGF8dd!O;i++NyFnWpZe?g!5@#Xx?)=;(A5>bwS>BYm}3D#4ro|c zSD@ucon*o8OD6Egn`G6VQeR{8s;a`n1O7Nav4+9Eao$v?pP|BzVOpZXDT z8~yqyaI?z`Uzi7ckLN^GnhNbfOQH2jTWZ)Mby~R^8=8;-LZjIq?*ZHECY10b+;{}W zw&&1N8f9!trKEWqJ`-=W6lWd-5Rg}X`)lZKUFv~N*dvkJq=fhJ23 zcKG&lqxT-aQ0k<9KN>xCGQdM8v*nx9-X=8xY+##17#UbW#tfJ zu%P{INwspqE(ez_a4Pf z8?p+0Ih@=&G>=qX$-Sz=-U)zfHsRoNCfvTIc2o3l6CMcRBwx4FhusbhSTElPt=^qb zGT<_Zn%it%wCTX?p1L3gIN=rz$KT&^PiN3nr=;Pc{9P9i2kL72@v6Jpjo~L(+eVze zIvEW9z$GhSYI7g@ByK;H+{?$&_`IaG@gh!E8B1L? z_O2%l$KAxlX*7b-#nf!Jv9%%B1iFcdS`rIXdno{A-Df@HEp8Ah;hk-J5f7AK$NeCno zJ{NLXg8iouGet@9NN9K7{cQNx2go6@GFDbJ09eoZE{Cdok5n8%Fy0LD&Q1;{Y;K|s z%q8TW$SKHEJC6i;tYI7EDk07C7n)gkaStQqJgkOK5MhyOebHDBhI3`S2+O0agmjJX(uAYzdQeC*JH zkEH>_t#fcs#G$&o)@a`%fILh`0n+H@M<);0OJ~pMtABNUMR9(lo$R_!;VadZp1>pv>cxHC+n)}g2^3|)5uI@h_fJE3_-GukR5YgZSJf_|d6JCxF)V;c zXCtvIr0oQ03C$@}>Oa!`88=8$R)$t0I$^1g#<8;md5l7`S=lgYL(N+5w`)6Irw!kd zyEs$baq(1%KhcVKJ%0|h4YwL^4}fC3ua5UesiKQ5U8lAajG}R7v$*A-rgQpmwQtv- z`h|^!VAwxIM@+Pwb{odYAcJ4`VGIk3pi+005*mX-1AVevPyhAfnJ-?0gTgi?NE*0X z^??f(!9RRp^zO%&^@Zi0wqg%In8Mp?zNZcQIFAmW`vOanoSCR5N#W=(;c${z^>TWU zdvb1qtW04xPBH?m`+*b!MK&aL}e5tzO zyIBYLjt5%Mi|d^gdzxv7s0`n%k{$6uNDp!yT-|lU<%@Zl z_~;L#XP=w_X0g$e;DiY1ml;R)!Uf6D*SZ!xcyzPV=$G1+rt5ZlG6s_KatX!>5q4Ux z*qfSf@RHxCZqJ^`2U z)9-|+w{(C9(o#4s#?%tH&V-Av2LV^w_<6gOFl_h=34yS-7cE33Tp|$)VW=jj2I0`p8o0S;RAmj{P8XvNwKOf$WomS*lGF;b>`%-I!k2s+?s)m&tdrZU%+9qrB`;>(~ev#^KgH;Ix?0WE60roU&6}386N*gUnZ-T zx>V|Jr`J%sJ;siyQ|I-DvfWe5RenVmEZzAuda%)gte$n?+!`q6qJ=#!JQ4~?-1JL< zIk=2`YBZVP4U>G4p z*`~xCCO;PY#UqXs^bbP?vifN4o=8nZH83AqRSSKKGYn<=cXo5xcrW7Vh zkeiZ!6UnmVwZr@Ip@N4>PFACgucGi`uRASeDteiw+F{U%?^41?Q03vclU35%PM#Xd z^&lEIIbK6G`vs*RTxL|L%-abDJG4_$)IYv`^&uhWN_P35HnL)*~T8B$3jgvO>0fRC6I z2IhB^(!a3|_5@-&8@9gOPl}h~so(ya*CXQ0eGOUhS41C#McAd;*`6)}m^M@Qe@x*F zrq_9bQc{n7^V{if-X6XG*yx!j&%E&U=?~Nl)bQ~?WHS;I@*{(OADC^bAJe>eNDr;( zTtI2ug~CmR_39nVxwXO_m1?e9xMQ`rR;(ICV9!7T$0rEqRD_~ZA%-EZJf#8zV+ z_z@fq+3IZseN@A``x_n8M2?8@-VyFo5iy$`e)#Nf0?q$0!Nv|ZIXgXFm?^%vccEIH zoq2I`syz8Ln~?dla9}UZv`gSy^i0g!TE~I0OV2zBE&P=0Hmlz{fd->BBL&vV@m4q zgnZ<`HH+xEslpPh@`|N>r9xHtU0O%upk#L+fS>}fW|gyL$nL2ioiF6`QNDjRrTV?YG#7z`~GkouhGvTPE~Q0PYp` z2NZY75U{x$iwXUPg%tjJ9HBxOi!EBG#RBKudNS1BZ$Iu#32vRL18DiB!u;fZw1TM+ zD!@=m)aKT;^IKp4x^?p$jP5oKiTR8brwnew& z);c7{~_>z%)DIn-9V>@TIIVLwEQ_T)$sOwAUGrK0(xktZ0d<+Ds5 z3RCWK?bO{meZpYnN$@MBaHV-{y?6e$m6F`#NeOO`Mj+O1s&Ltv_RqIA?|pCC8uoUH z6Bv{J#d5VYjqFZ;2*54<))??Id^F8d`wKHqm0p~EZl*LZyaBVheiWnHApyOmkdrG; zYdJ|wa1z7ZBN1ilMpGm?2b=2I*IVW_(){dPtU~qs9GrM9q?TByl<;%Bp}Et(*6vt{@Yi-Uq-`X#v2Si~3#wu7Xd0&?a&5MnU~pwe9$ zo$iuE7xUYJ;z8>W4^IsGk_bZR15H=3zIdt>D9f^B2nlmd=>cJCsRRjk0>` zkW$MSi6{V-BI(Oi6)qmx*chU+3KM^D9i>i!IqgUH_zkR`4-1f0S3{1{X8|cEYRDg9jgg`_JIeyS?jQZ~pOF|InT6 zj8$84I@7N2JIijhjr;oq=VkW|hvoX{)K+F&&9xo)-Xe}kU}`W=0bd8`PGR?2C_iRIAa#ptFi(SVYbBRFvifg|(Hbz-QE@Lf#4 zI?AnX(RDg2x`uXgLsG9W~jfF^-v%G^%D1uhn>oD^g{& z)P5Sg_gj=-ALn1iT!sNOl0lx)@7&nhIEr+kdyMGDt2Y;8jh{yKQ(&~sYUd?1YAzP0 z3s04b;Q`&|{p-EkKe4sZ`Kz%1hVT{IqLQ;HItQI)S%pZi|LK?g^|Q1-Bv7jGXZzF* zoqYDJ`<;5Y#Tnuh0YjJBnS#X-?ZlbFvOQ$wI03Nj8jRLi0xx$bpIIo+N9Pv9pM%p3 zxR;n`=bQYq{c@Y*z~we&ObuS4$i^ZbBSm{P!^#cp=Z#8mlOHH3}899F?Nb zzGN|i8c`{&L@d8mSV$Hns+(Xi%yAS|v;oe)hczvLB1;WcB$@&k(@%v32r*U)ibOgR ziWDnj23s@N_`Aco3(rxi#)TpV%NA;?s$#-gyB2CA8I@O~qKh~w03%v@Ll$ZoSP_Zn zO$c62y$45h@rYX5JjF#IS5QHd`D0((gUJ!T2rT>wfB2{Nfdjs)WvY_P`FX687%Yz? zP5=1Wt#417^+!qZAq4DqVew@Mk&l2(BD1QYEReh)1~-voF2u z*5anJ&#Cc8M7-rL^F+tIcmAqdYaD3cF-qNC_FUH=p>#N|agL3;{To5}3rpOk{OH%5 zruyq^EIOX)CFEss{Ead0(y@1loWC8%VB|U5e8fi0feQyGTi1TZgA;c7nWZA${O73V zd097a8nqLWaOxtNEVVOcT{!hDn@SE3+1Q&0|G8G<)OXZ!FumS{dZ~p7>jo6K{*-K0 zmu&IrTcG=q$upl`J@JZsk5+EI)@`<24@v2m&=bIE$Rmz~>~EuD@r=pebd+Uv4CgKj zo~a%AUEHC)lL}13Fo&;`Xg5jd=?k3^{aK0X(O-%K<*ize1fyT*D6SSwFlNPTYtk1{86aG3ef9#S7^hD%Cg2jL6LdcHZdmW)nM zfvW(;$lgYBV4XfTKyrO3W9*92;~g}KfhuwyezXIh2N;Ls06`HRLs{sfZlbZ{A75&C zofZA?B%+yzzuTVJ67syZ2=1A#+m&XFLaT9*&r39nc(4)F(cj1E*#I(`#!$Q2eQdzQ z9vS*kh~o*%dwzbS|NgE1`3Ku?U4;zRlo18Lz_!Az!-fOQMQiI3rV6VGNCgTK%#R*y zU0;7>`;)VSi)ZL~3{&w+`}GivX8zs2c&qo>6-?y4i~Vi3#&RvY-hQ{SywXV;a77?{ zNV2bRS~N2Z^Uq^t-R&~WvJkrr*Vub#I=~id)B?+dhO(>sYO$QfdR8Hz`bIHNrufCM zTD`zAe6;=JQ!G4j4x}G}q zdXH7WOTAQ{xH3Ebt)yJeh`b_Wl!KL6Bawr=08=^9dM0DDsNt}b8HXjA17?0fKH$5K zJaTXl+&lf#L+U#vDrZ{LR0jgIU)#rtJ;JP6AW zR))Df6Bzoa}SaTSK zf41Q_WVu;2Rc@AH=jI^_bDGo&UzMfpykX$T;+*O-Kh?A+AFz1gi@y$zeFH;eMU9Y<;<4{!%(RFtZ_b#t*e{!aOc^xC|vID__`dD)_qv*f;OaI;b*>T2ENyiz> zl2P$5}y4C$q?WSYp5C8MWd8D`xd%Xu1OL_9~shK5;0 zh|SBiWW&57iH$2>)EOraVL{!2;;9Qnftk9KI(8b4P`19j0zSCh=a8SMpbH`%9g+re z=FJp0i`0cixhRa}SWneBO9n;LfOa>99N8|)wD`a9JtWU2vNKtCa)r5%`DrRg#>n*r z9KZ2J0OJ6LUuww0sB8sFKB%c`0p=1|P;cHl!5lENQN)4|yG*C!m^BeG2Nm>B-`+z~ zLLEpOHK1b1vw9*BaDW^2DjDy&Eemv43$eg%34{<2sX$%H&c009}`3=O;q{G)IV}nV2RMW}z zP&Fi}1hb7zEQE)`Ap(PVXgW+K#O!6)GRN7?CfnYsFEvV~$0>KW*d+CS!pWDm>~k(E zsGgVEQ^oT#nXcU~FCuQS%Y&~nOWfZnvjxh7;eT}I(HA9HMe^!;)@ka`gre#KMwxCN zNvNQM>;!bYKxi=?$)bRQl~$Q9jlgs%o#~RyG~o$)G!N~JjwHSfyy(PER!u6@36Ayn z#zQn@)JJuP5J3$Alte_=#J4~Fym$88;O6^qyFu670ls)Cw3eH0x~_1QBY+ZWra`)M z4F5=S)`n|4GHPfq{O&Cs8GED{ib=S_nj)4^kmed* zC6O^;aYb(+t=_gWD;XL7mS^=7@Kw7W-Z+x+u^I$DMa3jEac%YL73~JEX-6F(*Smic z{s)mKcB9A~Y&GE}h^3 zarBKs2?w`s^pC#}i(R@3Yo6<_KGk)+ddk#|ASa`u0>rq!`j|uS`**g!IysTUmjsRD zuj&3suPBixVVE0Ld-Sxw-y;IsUXvW!QQmqyK@&7*l=2R8qUl}gNWcFjq7XW=cVMIpEqoa zSQ!C6a>ygaJW|jJqWV^iBoqr><1h@15iBO54XP&2?0cK=6I3Ej>n{bxwJ2n&B8sT0 zs;FoN#}=5Ie`@cOk3RhP6Hi#^$8!^pKiENLOZ~tk>AFe3JI&P7Fo&21&$^g(HT%BA7e{#2gIg{Ho&;pOi_Wxc7`cf<*lFTo%s#$ zAw+t^keL`Q8}|X_`+AaZXDiv@0f8SO3|piHS!?6TJS#z(e8Ndrdg8b z8l9DSUPUWR9!aVZ(~ksU9pYHF{qZ~S1un1XMsR=;o57*mG+aMHGN+!h0*AL$L9B=PvH_`ybweRTE7D{$+2wXE9Sj7vSU0CxuPt{R;EvVY-R4w&(5 zTC^<8R=+tZ?w42H;fZq-}OT{@q~+27;398$veZ%;Og;tx6T4BCE-N?pp~OM(%9dXw@a`bD?d zaqJt_bi3X-u$BljKSW$QR{Q)4z>Z8z2mHorwGC^=(X9-X6)OisB_r#aC3adG*e3L- zoj1tg?#iiZvD%;{Ho_qQ>hWm6jdmiJ#*NiLZV`dR@u+w61K6Vw#glfgs&u%qh#YZL z5sw@i+`jwB){R5`Tc2Z##r%o%Mr&BNcKuagr?g5|OO>ASesGaIIC@6c)_}cR7n!Sk z#mDaUkfdfQ#hDLl+P=K$*5YwakUgxcwlze+TbzXxg^b1Gg-}K&v47?)Jj6IojOCUsMjUao#3+o&cHk?dMu4NTC<6MCV3ak%nI!5$wjN&fHcSIG zaVDYleEu+@%h-xDA-H(O1OsuDmk9)aUlyg}T4>jaDkDlwid5vRq*&|BsBD^MnS;TTXy)KU;f zhhY&*(~z-t^oE`T{rF8J$TGe3!sbd{aMaN3WU9Dj7Tn|CJo{nA8)Q7M>l_Z z2N@-HixGl72&*NZ{i?ACLQ%NMAP!}6+!G_EYy;^ zH~8&G7}L<+G<>7>ko}HNQC)buc*qjgh-$+SV}iPZxfu?8+umBG@uu-=-ZYje1e1qT zd=qZ-?&rPxZ=*i&tvJHElx#lAij`tw7GlRp^YJ;!&}@;Kl4@auVMi~HKhltcBB1#b zCGeGY5m(~Zd&F+82i|eKC@Cs&A*Fyw#*UQLcg1Y_*{I!r!6%KJA|SDeTV2-gQu788 ztXenRqvB|mjh1)RIsm(M<3R9nLOpt92gQRg4kghtUCNy4QX13fnM@+5)Q9o#-o2K_ z4`VH8fejSlFlZr-BaXMb;D;PVCD6HN?+j`Hk!|!A1y_39R$>Drd#ReUL4n_C^vH{$ z+2dx7$kMbs!@N)?jyF&DFP49c3@I(u{7Ls^*<$b4^~^$e#2k zzl3oKUbc!jn?rn!QOhE4_D5Qio3Itxn2s=FT@*^DL4Xy>L@`i39Loa^`Bp$t%h@ z18PG!N5>{O7E-r!h>qvA+PlW;>!L6cm!Gg&h|!)s1<&2$KgWT&0F81)sBkR-+m7); zEw$W(WUPQ}bNxL8$1|qc?1n~$801njgJcQ4zIdzu%Skwj7zZ$Xh|jH?k*Vt2ynA|l z8iZpistyq;)8z4wHrG!K{`hVC(u3_oxBI6)8wb*T?d4^+5YI~-tRw* z59YMvze0hDwuUoWymT7hs0nvWR!tL^^Q`w={n7&8JWp}r*v&Vrl8g%piKq|>Vw>n4 zKf3h;@s1Y11iKji6;hm8!Gnq-Jc*!ukxIW1J7ic-c+|Zcne3MVbA-BNj@a12oWD1jvxfde`AN@EDFa_ z?C>yM6j=I>Acr}Z(oUsF$ug2C5LVvbsMlR%q#X?i(uzT-+{(>n*C#~w(f9?_(mA%O zp40MI+n!Ay59^G8DdMMe_2`3&a;ohRJZfkNkXG6T3b*dC55T)e{E@hGPhrlSMz{*3 zt-CZ6$Y%%ggrG9cc0wrES=9iVem>|O`C)VY+riDF+sEFs?B3d_D}TlDTtjF9D*{Vo z_*oO9&WWhLN0<<8aOCXP+lT3ReRNqhV8TM+AL)pDi=eLRLyzg~=^%Du)4(r*I?H3A z=C}c(GXNDMDiJ+4=@=dKsg&58dJ35vvOZB?2uY z8K#|ALJ8(V7J?`d+ccGL-#Xv_=|ca)@&1*|VbJuILm-}otAWRLiOI-bi-sY!#EiS_ zuo4u@?CnCVtRRfcBQFy)h&8x#V{79m_RX<~B|bs5+^8jeSY2838#Sk?e#2xFb@ujB zVteU&PV(=acCi5iXOpbn(i>C-=eZpD5Oh95m}hYEF>lclfiqCR>i?p1YUc&bjKc_c zp3gY(WY88KH~%S9qOV24E>RoA(sa)$1HUGPrqSPlnP$=n_3xbDL$XJ$-NFl6;1B()21{3G*-an2D}YR_ z=CzkS*B4ig$yC$8Z{0ix3bO>?U0wE^x@&=ZA*i83R%mG>f=26}>2W7ftd7(Nwe1{b z@m;^r?38Qfqc zbe!5Np{PnSn!5Bws>8PL!Jq6@KmzX^gjT@|;Ge?T=Nh$6|9cVK;qIM z)&TCqC;C5r1{(%63C$dBukLz*M;%SRvhR1@@1B!YV= zS1uBllboX6`APyr7MMhbY46g`30gmHLK1}c!Y&;>PhNnyy&o%0{@f1ud9Dy}`N2F{p z5(<)qoiY=LS&1wXj)yIF%iD)UT#BM0F|qS4$9G8GH$CW%(oNVR$Q*5<}ZWi2gj&D&mjj@Opk z?RZYJ!cJ8Hr%SddNvs*9KD0fMLFI=bh~^{<4U_RM2yT0ms}mZ{N)o(mlsRm^U z%^X#ONeZpo0;Lm#x*1=S*gf4?G#R>T_|kP3)FL;V9R@#(`ry;k2#p2V+9+k5?Ik;< z*t8N|xHtwCLnI2SWe@FU!xWS_+4VeES)?aDDSdA1>K}t&-hoK9J*1@;o|vWPkb`@U zcGs)91t=;Vd}3YIl`4A_aIa~BVw(kmokRZodY>9-n`Q(s!SIn0DSs?Yo%83c~t0nH+MmIf~W!ohQXPFWEdviE{em@3x;9bC~^cftqe03NrnwW6$rf}hkMNC z#(U%*GYm=2M>f>-Mb>gb3x(PtP@1d)M0!()qyvV?jDWF|bf9j{;)0esutSjCI^-nC zXW?l`Yz9#}oHQk1o-IFh{RDzDE3m7^3M-uBRaCa9`7GHoDUEECq(z3rBY86vS^U@l z7K+Fi5vxW*gjfd0zJbln=Dicy;_8%5bnwe$tjdu@N95~WQXxeJoBllg_ek^7T`!~dF3q<`wvIQ|4#JH7< zSVz>Ym?dJY8fJ+iY&1+rXR*tAW{7R|jGZpZ3TFXGn;8zPV5*2Trsd+q!xN8Lj)%&! zLSc;eZu)!~{8Wx4sPw>Dxdn_?n{LOoi)M*%MPV({{Gm`60Y`P&aHr*3AIdI4;ub}ApX%n*VFRb^+5XEaxa!cV|Em>(2F)f89plcEYXA#6cH$Z`}#@nd4o?hbfu zgoW9%uOhZe92yDXhiTQ&`EN#=(R>KO4H;J z+Oe?~x8qolNNYIjH9P`;myJ^Z+AhFk8~4I;W23v=cq*d3qDgImy`9nL*Jvd)*!=Q` z(bcnbL|KH7JH-qN)uL!2?F!W#<#P*#ESdReqMmRq-cOa3K|hgL6X_`188CcS(X97(y)gYS;wuJ>Mx{P)$i`K(2nZ+ z_hPeWNlZiRDzcn`l3a-;PS-ol1}-YxoHd=JVtQOG96K$nV0cT+q z?}QOTf?Qf?#Rd~Jtm;!zmvRRcD%#zMjH?Nld{ZjpEw|j#!27)-s5Qw-XK&mYiiaeU z6mDxPykK zrqAhWcL+)0yGiNp!?PEbcM+E821CX`Y5uj6o7vaJPAe{=%2|rwB1|Q-tX2e|CyR5wyu8;t{j_WEg;R3 zkVw;~wt^1)g2{FzP=WDDXnm6yKG|qPOUu4G9jrE}4HR9WBv}hsp9XI|A`)yxq>SRa zz4hF*ntCCm!e02<8J?^$P}PL8P-V=25hh~CsrEoLCe)y0o` zpf>7>32voV2<=j0x zMOMA>&jD33)FM?SJD_rcMuL#0SOhN%3RLlSo6Q0wV}FThu}$*sJ%dGgDg+kRU~N&`HD>t)0knOa@0X_C6wEqAj;)dK-ED6s^(Bp6BaVf z1E6WS@StW&bgXsg9_=k8aMS?iJk7ZRl=L`b+}-knad&Gh9}`QObcBmh;r& z-USY_yF%`DvQ~TH($O` zzQ|fF9sP5hrVyG{qeAW%D8u9N;emC6RF*EI2qgjfT^mLDjNg50`~3}$b*200MQxIh zDIsg!!SnIDu?kZ@8x4qDqH3zJnCJ>gvd(4u$dS>}zo{xuL&rG#^}_eDVKOjqRshvl z;FD{c=l;H9`?C{UCy%>Df9OWx2d!i+D@j4Ddh$=^fim>%1Bf*cD?8mj4w+jiMi)e# zMvT+3q(hwpbd$|h7-_?Fgn}AqT9^OVJ_d%_|?k z+>z%>Co5+nW+BDX-$3$teNQi|ZX~>9_W~Eprc6^)!B7y?5iG)%K%qa71!>d6Je5|a z;@3h6Gnicw8BFA;0SP}tS26zRcZfby`Kk)_(e1mJ6=U2v?dlo>|i=L(~)+ftn#=Q}Krn zwK;&x+JirQnL-DM^JsrIe5B0*993I?@JL@Rz=xm*oNEK&v}*+6)@U%t{2GlLW>!PO zz!I-(J<<=Bs=rDzyKXmIprb7cIxW)YSnFI3#T(vUp)?^8GG2xrDq3I_hY^P=d z0b}!@bJqs-a&Gilj+!7=yO!PZSSIkQp0q2N=&2RbAY13&yKcYxp8Fcvw!{Z-jxN5t zb>@32S_#5xl&+M0W0YvIl5Y2D+qP}nwr$&e+O|&Hwr$(C?e5byU*9`3>&@JmS#Q0) zl5ACKC-q~mFG=MqSpAyGdeUe4FAn*UtFYn%Q5bS6*T4f?>;n^+eDZv-KABRvhH6}b}mXuA3*Mft6%alQW z-}5)oPzrDPjHhy1V)izxJe-X*%^22v0FV7pU^fEJAtOw<-m zy>@lGAu3m|P?`9h^p7C}Dq+;V`oPRSOPF@1l?)tIFovz?$&+XebuWgzB(kmLdv=lh>0n7uE(o795YNTgwLEArisz~^rEKZ^X1{R+cCa9_L!D{At~40OON{F z{UQRS1&PQ+*Y+K6sOu%Sq76A!)mZwE9GtJfL=jP13u!GWPp`Mh=!q}RLulm&sNX0M zjzDK%Ujt?FG^lr(w4xM?ODYj9Jv|POiFOylGHc8VPLv&+JI*YUi^l4Q!#me6m2@3& z1|MS3-!3<=7E24EqX*&lY?0OVTml>?Q-p&Z(9a6bphW;3n*#o z&LWbYXWfotSaTFP;iB!SNn5%1gR1k+c>b-KyOF_Kh17Crh%R|I4_uzxC@Wx^dp>MF<}$WR>B2$YkiRF$ zXc+5GBN9>WYovJFu5@*W({bqNxRz{2hpV;{8;8yQ_`Z%~nPk#F`e_@9`|9)dq{)pv z3H?I7)s~x5-XL?yL?9w&IB+e9(O6rQkOO(dN+Fs&!pHBsNI z=)PXauE||>!%EhH;O!!}zM;QHqW*|=BF-ePnst)-ZhqXrrGm%w+^k}eQdI=PiuN=P z{d9y|@V?vXV9MaZJYEO?GN1#Sm%eGJ>i(TU+JMsSlASvVDZWh?O^Kco1aNXv zlGH=la6LE&TfP3?w~IUcLfNd1P|akmywcmdQVvg49d=(V=m{vXAJc9%x`Z)32HQ3+ zdjy(?`<1?G6g4c2*XaInPx-MH%m%sZkgS*v`FU5DKR7ZX$1mLQXI7c#MyH3nmX>p9Q z$)&5TxibX5t9N<@Jt0s)+AuNg17CB@-Xe67CDh9WwAHy&JAVDT56eUiGAleqwI3lo zXPJ&^9d~ds&Hg~=L=}_Ua~hO|O<`&{2pz6lb&rT3az%bs5s1OLJ06}AYt0y*y|T*O zUv-o28md8&|AsvO0IFx_PMI3oQ%HVhys&#Ar7S2`P(+AV$P!KVW z6{y=E7S>N}Jt`W2L|C{52>pE=$L3@v?~O$Nae)k!Xp%2Q_6@YUroiVON zT{0@nCjSLCiv-VhlZ|P^;}!}U3D@>!USAAmTwqwKEe_?WJ7N z)US#v4kgYZRHz|L!&0m9o5r2u7e>N}LJJ=kFYhDU;7b3X&hpMx_X~hdRTbJ2<)pxn zSc{*2>v1Z*-vET;s{sM^KzTl+U_QAH4xG0E@B^y&Y}O)wo@Y?e4}I7S<8$ljV}n=9 z#LZwHp)wTRh&0N4gBmQ>lkDz7xZHrFs}jv>tfRw)eN*VDf#5V zlTe8Fe#b)>teNo%=+9)E9h5@NCLll-^D0Na;;mF6txV15h2Di@0&RS^mp=t(vDd;< zpRs_if8FvdxF<7yw7_nm#9Jd{k&316ZLBwTD|AP1vUn)^P*H`qfH}&2l2UpX!9yE* zh=kZbaOlA!!BPK)%D>THh1N3A_AnHbEu0`HA@2c;;eq?OOhfsh1I!mJ5;?BFmjt`` zyLx!8CkdwDn`__(F?cS2Ae#>TaMgi#VWD6tm!M)Y_X%>4pbrW`Hnj{+K!QsAANc&P&ohXy%hoFEY=Pfm2Pu~Z=MidE zO32i%e;H)}OEaSs#Q`!VUbYGfqG$X@pT>5~rixfDBOw+Si3y~CBF>~ovMJC?^^QbP zT=>S}(-m5a+PmNAuiN2t)o<357ePryA1wSWJQ_#$1D&?aR;RU$&0=538 zp=AwQs?@xidF>O3J)lUF`f6mTtm?aC2)K*iKHa}gTWkG$&TtiROQz|;Ykm#Og%F^d zOf*BxX0kSrjFtv5aDF0r?N?1vEc}aM#rm)IAiw$~(QU+EWXbKYV)qso|E{n2~s z(_fQRn88C%8~325ge7sPf|TGaQY(rC+Lxp5A7*=xJ|_fgBa~SdT(lUru@Zg5Mo+dN zB?Ehy)I=2NeHoB~@6v|GV&n6K`IBec3FC|F>!NHL65UySytR|87ph|2A3cRcz($i<%R5wog8?8Z4Q)#fM;mnq54|1stuSO} zb*L;Yz+V>{*#2Soq99rdSP7}pQVM44t=wfGcAR{Hu5%V&T1c`c&|iX_ngqCDfh?DB zb2wlCV>Py2EG1>375DJV782b-oxnt?meRsOUkgeRXXP3g6B5uZn4e0Vk$kFOJtTAK zR4(IfeU;jIgZ{lL=YIYTv69pVmuuY65#6=pK@*T~8S`Zf-4u~t6^cu<-VSu?Wd z-)A$}5@93Nv{;@EfdmIs0|L?}AL+DGBej^6w8bkIJNT|@M6z0y^zPd{pu&?p_Ecvz zqv?TbXv|`PJn)M&rijKIGoSKhtEyd-YgG+s5gL!(C(H4oG#zR(?5Q(~Dt}`IOV8>a z#xD&Nm1p32w?9tPZRGS6{|^6TkA4q5Zw_h@HaxzU-@Klm>tG&rqWZi&f@9_TcJzA1 zekuO@N45_DU#p$ZF}P);3#{Ywsr?4OR-7;FeVKx$jd7y99 zMs2m&GDK*&x1-xr(;CJ0&Yv|85$uJi2UT*K7(pd#F^2P`Kh{<}hS?>|17V!s-1rCrQJ!g`1pa>-90Dve$qQ z`9J#U{rl+9#QCJ`?3zq|Tu``MAjSlLSFOZ=d6CPE_x8n)srDhiMmLd4WWcwd>8GI{ z>93KdRR0<$Nk!m6C$Zs8HxZu_5L7flPF%orm`#1bp+&tU($F8>qcSJ2`4tMVdvpAD zv0+C0hjkmL$Nd*5$D{o@D1Rh{DZ`Ss4qsVT+H_^eGR5bGS}TCl{pt+ULdMddX7m1X zQJTe)WfpHDeize1sTxgHv<%_JnkE%(H)VLGV$==?4oY!GX=eGryb4J9M?_2{;-aS| z$}ux;M`cM=U2K7xayxnyCK(=X1EPT{7P&W4qcd6RMvc9omw|JJ6jm^>kiRZSmi@OaxTns(8w!+1y>D+4Z8kKrdikfb9#d(NG$PF_- z1B>Hn0%G!W=>VUCvY_rLonNA!s0mFrVqw{;?J(LFV_E^~9WOSAa=xEEw|W@?-F3S2 zs=dgA1{PeXD~mknEMPhj!c_xZLGH+tBot4d{)pBt9r}uVqCg4~ z&|Yf5FF@$?o&q=Xz%^8g#XC_G>XCqQ;tY!Q*N0H1=RQ0Ph_0&s5d0JhWO9|47HxHx zPM!f>$QcUUw2D|D6$*6ew*}Y35^IQ;j)*L$G0`jThg~96_Bw%*I@{a#JyI^HDa14^ zIj@~po>Mjit#-TmMJ(j2m;g_lXW)#>Is|b7=vePGP{8}fxN1=1&x-9b zn|C=pa#9Noc-S!nIIw$Zp16?{tqSzBaA=eTFc-=u$)?ujYup z%bt`5k#emSkWn}1(;e7tWX&fCW7#f=iJJEQ4fX+N1i15=Dx;IR6VL<(``M+Td6;uj zQ7_-NF8sNVZPAcL)amJ#Yjz6fdtoa?qwDr`gOi3#Kw@C z6zm^0A>SjWQUfO-fdeD3rZSme#Hw7H6gh%Ge3f_-@$UuU3Qm z#c1@X|7TA#6h5`QHELH?(U+m4>y>T^0k$pK6 zE_Ci~A$>})hd3H+vEo4P6tTyzh>x$Qm62gR9Rs#_9651g)yBg_I2kRvDcK>3SlyL>9;0f9) zza@~P3$r>PU=#y3np26}9~&WVl6qJ|2P%Ay#Kw@g%`3_4>bl#f4m!+hAT(Nw@|9)e z@AR62fb>}7bG7Paem$;K_ET>7Kt6GccOb`e6DhRb#ST)PztCjOL24N*0n_OcmDB!S z30QAJ2u=@4GbP}d#udYY(_=6bJx6)OU?2c(xDlh0xZ}~6d`CJOPCpSxzo@jhAuJ&y zfZcYd(1wRlE{O+kh_A<+^=WJ*G)JbD1lfND5$=W9>+O-oA`hYuh*Wst${B|?au%=H#>NMtC`!w*Bk|qTfmhhJCQ7`!-k9@(OeI=n$W9d8 zZE-z?2gbGYOsgFfdMp;LVFG;PwqnPt6qEmq$@w+_GqjDiathN3iTt~Qeo+o9bW!^s zX-WIMB-(RP`&n6HI?!QodU(tF-nQ8x%m&vGD|GGHpxFU#qf<;7NVsF*-J|9kfT2|a zhBc1?ExuML6Z=(?bQmGG)}7RlB|lezdKbRntZ35NVK$}}um~4MtO3oRe@@&(OYJw^ z&wR6koA?H&sU=ObU#J+5hH&w21QYVA=ZbX{uQROO}oI1IAJx zJW;f1J|+ZkrHb@AOZI(b?T zsM+=F`jl9pml+|~KDFl}K6mPe1I}TER9$3pFe}ljoy5^g8&89&g%rNYcSeZbQgfau zJ~KT}zCHHuedqn;BqP=&MIOCE$bQN#L^M`oyM`atj;axoK#R)0t{6Ds+?Pw`WDG`Hjj{z)__3$?5zP|Sb~h!UL$V7wah@sQxyr57iN$~O8pu- z+08O{g9b8+)9Dui(*hJPa|f7r92)P%SB~(L2{NK}$|tRsG(kCA5p8tq4MVL!ka6bx zE2D+3(I}o8cE*~_Y1?~Za_pZws@_N^n{2{7zI*4c$1_^YQPvpHNhE3))M4H%4BF97@M-_=n>$`ra#6Y zz+b!wmh{tfw}@=lxTvwSxJ$PFZIvi}Ftz9Mkksd?k zR{Dm<@XnH>X=5e0^?^;W2(0B6=3rCg7!7j&UoaOQN!XkI;8@ zB;v=cZo5GPj|M?EanISj<|&6NMx><)4#r8L;%4Q?eIlf8zMdC@dQVf28>VUDpMonF zZd_OBUb2KC{*{Ugl&qJO%W728ie7M$BnnDf&-%UH_T8U+bE^*5Whf^el1oe%Bj{8Y zRovl_&nrW&Eb9cEDKDPCw&7mzJYTWTi>Q;0IdQyMd4`;e4M-EZD|R3pC|JI-H-yIA zKO9R_Gvs}**?9bT*zL|^F*M;=BR3Mr`bOC*zxl3UWof$5P(^CUY{>#hw82RzTCj}3 zz^FQVb)WK^P6rKRsS00TzdQ@XdIzKiNnH22fL=Y2DNa!>TdXUg^J9{}M~S>5JLLv( zh$OdHRQ%UkKdjfhP37zDo<&s+_KSFLf}+5xO#jg+j4JoSeXvtsCo-aztaoKbYCO+x zBma-2COgtRukvc(y)0?N&qZxT)T; zP0|2dnS%)4Cmj$%QY8}MJV)<@+Pj)>z{iaXHl!ttakhL@7Q4F{!x2DsaE0qF{>3a$N($eLC zkHR)fn7qKYiHZ<%$xU~PIF9P#Vr@~OM22#2}T@DUX7BH}Y-nE{q zQNL3R?gPm5zc%cjBiy!%Pm{2_PDxDc8_SD!S@6&Yb(yM{8HO82kNM*(IidqP86Z&E zHb)O4MYVO_@Q)d*X&|Hy3ZX6}x9NKA(6ul_wKU)@1!e~px@Kzp8UuHDH$N>qLYx7c zF}Hlkd|IsS>!@kwj45Dj3ZQ`O2-Ph->sS=|!akEr0D`-_FW(&|j^lvhMF@(iNrs8@ zN!x&Th^_XlH(6vcC!?tT~o?8#dQE6xmP= zha0i?h2vYNRCIUE!#X0C(M@)kP(lSYe#NJt_Ca?HIU<)&x(mdGOLJcSEYf7F1o_-R zq~^+m`ujjiAYt9B8ci!AY7Htt|bucgV~HByzNL=Ji?Qov1-fh{rjCQ1~bZSAMND1I$Q1pA4zWPbSKx zhP$g*dGk-S?iH2>i9T{p<1btdajRRO@pVg@jg?$qfAIiqbkxeL|x?-ejskgNR#>OGu>_=iwqc2)aI-y+7I? z!Mq5{ow>b|+2^!>2Ay4>!Zbhm`$EowL&-w2B5PPsRssyTq1X=t1WTYyb(q|IcvDgT zw4jUp?_{1(p+Ml9eT8#|KO>h^b$09V$jmREDxs^(TED-W%;i2zvta@wm>b&3E7e&W zgzyv@p4jzxogVIQpIuCL=;;TN$gW&vb9Xzf5x_+ zJ1?nA61zt$g-BS&2+Wcj420_QgGK^Q^(csTF$)qkz(Btux;L_WLn-RCyJ)1;C`ENb zO&&fNzv87C;h+%Q5~|3+u8D_9fdJ)!_oS_Z{bp8!T{j1Ph-R0NaYMO(aY*3f@F_6g zc?uM6!Fs$FQq{HY-MKWb^uK@Ur^hSDMINx3!eG+sRk(D5x7=#k?$3i_qgr@U**Y~i zSYMGk)t7}Xx7r+|V88D!w3N9>w5u(k?Q2jHJhS%C#0 zY6-R}B#CjGRE0Z}G)4bf($&Kxk1tujV|1Q&xE)%f>ps(SM|z&(d*kma-WS2eqbgjm zlr^)}^jvnCKM0X^cYfB^l9PuOJg`TlCZgys0{B$4HF=NXRbyC^cMRH}pMNQ0+dVt$ z@R-rt@;m`kU`eiwloM0sMz97QD(wu5K8MVl(-@eu07s#pP@ z1Ke?Q|MBh@e!BA_E&qs3K@*|9BJhXWO7E*UBtJ?!b}z0~ih6Nz3K(TC^hz3V^g$^< z)BCi3ey-9g$E2vt+BEBsxrX??rPN0Jg;|8If19;VB=ZPg^0(%7tYCZGt=wQc^j$?) zg2jGqRUSSW$c#}w8L)!!2+ilLs}-h+RWhmR<22~%fY6&+$5R2fWj%)`*NnmUX>=Z4 zvNYN^df^xLYzLw znKzl$m~_^J%fF-+@+Ns4iNkhjC~^;hD;yNfBQ@obt^}ZN*LLj=h`+_8i<8FVW>Y>G z#NxxeTtM=Kmn(b4kyJXJP0fS}kXhx9!7VfV#_#A}ZP?d!b`7l-Qy64fxwccMSOO2k z(bWS;tpMa)nP5MNv}*l?0CjDL4$WqLUmtcar+0iaS6orcjRzt{Sq-D>G)euN5(0BA z%V@BisSgmWcOHZH`Ln_i%N|M4@<462=DF#f;boXo#XI=Zl&T}!TXh7$Z;os#JEhS|*g<$4yokb&_DfC83~xU5^sZ z$w4v(2lnK8ev9KIVza7ItssraA2+w`NWgD&eN@AeOchnzB1mJ@q{nqMWvyH;XV%lm zl%cfuJWf`rtm=UyRm35zHtzWa;5MUmm(2sP-H_Z#2Iu!&nEfoskb`0+8G{_DGB80+ zp|^=CT9u15$!SPs9o_~aA{!g`$F7Lz6?z?4IE;J|1eVNVSSDe~Tdw&DPCHvT3Fw3@ z_3;762til}3ENCX*%G2WeSH&+TEm2~(wT{Z&ov*W{;OfjA&`BJtNWlom&6-MxQ2OEmxN|e_&p9t~Mg{Z&b{oeJuK0v^ldNbXI(f z09tg+g!f+EdmR?Ri6LSzpI9JR5pm2qr}83LzzV4>)R`X0RH8Z`yyP?$?tXF~RPft_H{NqMIzHSA%K~M^ zo=v5~5f{U)oaksd4h|R*Bl6fGHyV&BMK|h@p+}cXWd5bRi5f&FlD$zE8iK5owx8Ih z{z5nlfuSA|)?=56wlTm3{_f1j1J|Z-LYAIu9=;i-1HBG zT1Z!VZ9Ya9uYsaWbG&D^!%wNzTdiMrKC|FtdvzmZc1Y?NOZH^R{VtTb%naf25S%hz z)&eIyW=(Ylw1Dy53p~w-BIs?j6ws0Mo!8!BF}xjUy17ix3ZTvex~DScF2SiIV%oF5 zQfdPN>}O(QlJ`n z$=%>aCi=~n|Mo$5tJzkF=u4sSYhVL{AbI6EV&+3mGG6<9z)-iI!ZfD`h;A;qDSzDS zDkT%l3(Y{?1j>6lvo6Vl(bcOZ>cV1d(Om-GFNP}Z_-}^mPpSevkYErO7m*4By+mKs zJo&C(_1v#-N22}a`>HUf_pusG@1=S@CzWTri4G(oc+hMx=m7ch%|2*xi^eBGU~4k4 zzeV?Y`dMcTtkGTVQg(V%=$h)QA`VpDOihO!NS+A%3-R23FI)25f8Y4d@bdB6MOSm# z{Q#4Rbk*Ia183NVM-7Ir4FYdQmyP9Khb-0O<}24pke7p?Cs+q{;)G?&j1KK z!Cp_`{ixcx>b*u8`$nVH6{TapeJj#7sp2RbY?VbTs+688gk?hp&HKQuWpL zn?R*}@+!TUV0dcu+E|tL#F0G$|Dgz}~bq``{Teqvj z^#g`7|MmWK^k2I2HA45S-fjzXn)h2W6oS1GnnH?E6A##7~wgE*$ZzlJ#T*&Js-67rQHWw4`nJ2ze< z4(_^__&(PPY`}Y%_6~e9<>KVQ#C^U!i<2R&iof)}z299=c@*!rK!#VMxbprXl_{}t zlld5as%g^wU`KTSJ8NTs_v%N~uzjQ!=6s7QyIRyGMI-_av0sQGl5RnH9Vu->u{4LA z@tkZhs;L4sekQ5V&(vT*DPGoY*r3}x@Kj0yg#jHb6EOZ$0xpp!Nsu(DNG7@exZ;0F zX%%QiqFIE?IVaF}^*JDuqPE+`WAuF+&`nI*s3+sWDcF+HnC?cc$rnMAp+DNNA01^? z#-_oMw?!Z?2c`k&=kXxc#K*>}5VFI;RTJez6FZ)m=VpZfHnM|9{)7yxApUy3Qnr%p zCs69&tAtZhydr?cqmL-snQkqFj%(y_%8=cg= z&s?(lPkd^Ug|ZV@uW01M8f-*z<*R5eK8bDM7m&OZ5HK>pKaN1t)-Klt%!^iWIsLp7Me#W zJ-l)vZZDHtV5&&t0(>fIssud3we9)?)8zhb_f9jyQEvu!3)saR$V?f6X}$P=k5hUL6G>pz}haeOl(y(;`^K?QNPw~ z*Ch|EAm1`Jd6?!I4~0gntyh6Rlg;57(tV-oL3j0d7h}70Pz7hn(}57MaL-GQXMw8O z6z%37bn35Np(dFA7xs2+o%Q^1iDB%yE`wlHRqC5Yko4WFzV}Ju&9+g=rPekBP19!k z*v{^vh4N7EQId16^tpX{^W>O@e15&H(KJ_-h;ysVi4QnxQI?ETj@8mXdDT?yXjl(k%th_cACZr2MI@tys%d~d zn+!P&ghA?1n7*w#`(nfU@rBF4VVBxffNj{eEi^irwTzV}e!^c-+pgB2oHfJOUXy)2 z&W+zaguOVC^+tfrB$3p)t=GtxTk))84PVSTR};66GSh_a5CN4|M?8Vxm>KebOGII< zx*s)Y?a7BrLi3`a6vMtvevtpCHqqCj}7LG9&f246KPSrrR2EDM9MdvA6mbVY! z^~l8{DFl&NLZyfgos~8W~tW8MtQTw zwCk7ax;Lb9dnQHf{d#wqCPw)HJ6iSs5aa!iYj9iw9=ry3CyUI~jr#;vAxp zp*>ht-X7@jSWDS1FLPiRGbT|gI2hDS7>Aa*T&Y+&a?gbWAB*WOcoF3;a1)grgrdm=jD^9{>Sy?WK0+&b(S!NXEcd0k{OWwAUJ$r{K z1f1C)Gx`8saE(Hj8ybi^q6uhFfk99P|BN@*PSa$HTL3F4Tvr&sZX5sae-qbQlIU*HM`Slb)WO ztJL_}3AVk9*r6!s%X}RDGZy0=jnq>G031mz0~ZT|EGr{4DtXQEL@fr64VLqiiv<4! zrrQ*juolQy71SchO@$u+*#>%L57#h3DfMTwBtWoOB$F-5y=;Hq9lLmE%T_aNn175Q z;DR7pj5s0F+qI7U5$Qk7szfVEijnY(Kiy7swnZ_S>C2UWR{q zlA}}W&Hza$7O>2&NXUkgRPqNEDH9S^$LSaIi0x&C&6xDblnj;PbKW(JlXHk>G%ZVi)A~tuyi;4KbBqadem8OgIpj*;rXQ4MV z@u!7v)ayE!kgWS>d>|$SKK=w`a{V&BB+w|lLD)cQWrTGvdLdIuc*bG9O$qV30M%!@ z?SEpQ!guMEfk!?D7X_ereV7pS22ZfK#5@;TIoAwDHLjAe$;VHpDx47~Yu^5)hS9UW zaK>1t)EX(K=&8ajm^=1LAvyx-%LiVN)S4homvcT$WO9zX4~yRF9{WgahL8!yQ%V3N zjVcreqUohBtvtC`lXzmw5ODJG0ZMVt5E+eR0&&680~^Gq{>8Hfp|8JM~1VHbP=7B zh{XSb+C!fj4<3H48b7BmvkAvEs;hV~Zj|3q-nww+uf<%88Z7CYCGrE`cIPP29N>q$ zPvc0lNy^-aIT59sOd%-Wx&&u&RZg{0LO}8ULWP_1kRzO+{O-&w%_}6-2~H5yJfWuJ z7pMfF90SScpFq)QsyPLlQ6+W-Se=GJ;9tlTn&;`{ zut&!*2<|W0xNf7(QwAHkd(ZYsF+}bw^;N#ZU%MH*l@Y>f8uKmGvOz_QwP%qEu+eQ| zxWS*R*s7l~8SC8!5Kw*ZuX8q^$(Dp)xKV`~Wli2QAe^uuu{TVvZ)Dbo%Of@q>O(E4 zw7o(Ie^}h}7QACn@7uI3rQG@0Rz%zXa?F2d^VjgOZ7|H+kDLf`hNci~yw~+IHyo=q z+i}AXhX6?pwGbOk1%G5O?kR%TJuo)`jx#sfQfFmc6{cU-Fwo3qqTVgwBOR)VG^zK# zzV>ryD=i>tv_S-NYVIvY_^4y%=O&Cg-Mt1)y51pu0qe%ohl38BbSqt(Zo%dd#DX-P z3wnJl0Vbv5TJcy*K1FQFOxxgvKuUfpHbF7;aWlO@MBb{(z$HCgA@1XoW{`G6w-rGK z;O$o^=>~C(jYBzC+t*1XjApI$(c|imA6Z5sdF{9?2fvtV9&PyZR`Ye7qS0=y_`D2z zU#9n*3>Mza=r-V0e5^{0Uv(PI3ulYD#y7FOIvgtI-UTfp-PS%w>rUl^i@U79$EEI? z`$-RCU{=AnH|!LUT`)}eL-u+jDPedID;Kf7J-6?Xm3WmPCb)&u6l^GBq)*T1%If-w z`2%=+%QN+SLc;}zh9XgRECU9V^F$BxbN@+KGiS`a4xpJl;vCsXI}6q0{*p#}742-G zlEWccGwNZK0Nq%rKwP^Gi#Ws)eo|WaIHi-z`p+8w0!Yn>Oh*3v=soz!SpS3m z|Aa|RWF{c{`Jp?ZzJwqi3NOLjo^v0_bq5Cw3xJ;pGHfEldiLO6jZ9aXc$~qFQ`4lg zCqzg9N@xONWk9A*yf^#X(F5UVgcxP@z5XMm+Cn3e>uA_*zFoJ)ef_90X;>bA5o#uW}Y-ypteG3x#AR{gKQ`rqvI zuQ>I;LtC8xq4)n$%lb#jzd&4F*%ZPzOaK7aZ~y?(|5sH5mmhMse}Y{c3%h&f7cRta zg5FRUMK#+&0^kGDeV;Z2yv<>qf%(G0v3AE#*X#)gY%+^>P+;)z-`3%u+CJ8NDOnX2 z6>Kf-%76HtUW{(IK3^(FujAD-#7z|9liJlQl48cWHBmH^ILGe>Pt9`@GfFp4OBvf+ z>EqTcTq>X%@X@bE;Bu~*`@^>>?|7I$9hxa7vfLlfN)|q3`OxU@_K(lJ9W!Qkpj3t= ze9qc?+9Z=0;yj;UjIN$fA5T|yG75WYr0}^Uk(5MV(?=&3Rk7Yj$|)hUlFkU`(=>}Y zV;(%J)Q*Ui>1>_dyC@U5K52n$>J?7wDeFsxD^V>Tlpl^n`J&cck^sxOBSCLwX!DFV zljV?{6IC{fXyNlDnpHH*rB9LoqdJsv;x9=V-Bl_d2JhU3`FEx(Dxpn`Ej0J6kmm+Q zt3aHC{N%;;;4!F6*ctqQ7k`L=rzu6?Tih!b%82h`^k2~ZUBv@6J)_Zk=+e^V31YT~ zJgWG`6%6wui8}(v$_!X-esgx8qQ!<<27zuBzA6^QX;8>pt5b}3hArP*%a*)SQoyN6 zneaOuc(q8mFg$vBhW7CaUUroa4mN=d^YHX%D4vZl;UgDJATG`d*O~%8*J=)T%9l&C z=R`PU@5?0rE|=HR=J$)L2cS$f@F1j$C?Zgg$39xM2txoHLQ@srfJS(Zw5+%?fV9I> z`uXoVM;4U1c69O&P5?nY>q~ZJN&4Ycyo*s~J=QDk@p`Pes&!e=d z#QER)`yUihkEihURd770nFwjlNtzIjjVZ&S6BH(dPuDjEmO!^r3>h2_O#Id*reCpG zDyG2ipotP>NMh!7A%6p@>juN*V$3ld7JojP-newQF!H| z4*Z$s&yWM^=-38Wr~|BQ-+I(XMe=nG$X6&TmA}9MXyhR!}e{ul?{DnknK1Cn^MM~aDBGgi&mQQEvqcb*grVtU$E*{^EEdvG+kY)mi)}d3HOcQc$%q>FcU!b&Sl3Mx4Hj zhjM9saa;M4+3t}p^2o6S-SQ=xwDQ=@W2h3WMD|IHO)MnQ-z7UOAB* z^#XNYX+R#bFOMTkOmhL{?@HX=YE3Uk=>w^F=FmO$xR3MZ=Gt z%YXN8zE4i+wg#^8(apcf#!!}xBQ+st_X>D*~?uKxRurj+9j_1$T0Kl z@$*~!J39ws*qCQQ0D$=Ex@yC!1<2DRlFRPD&3rq(Bs|ASLw}e0_6}u9Dxgu=w@5CB z$DkQ(`qxDy^+y3iq9C49T3&Uuo7QTF7k8%u*lnLO}C^BVgk@bv#9n9qRb#btEmT0 zi@vLEfNQ--x!Jv28V-adXSk>R6h?##2H7{451Qw|Q=~EP`IDi_oGD;jfNN}}7N>q@ z;UtUbZgURMUw{be8993=7@~sgJt*92dzzUw+6hcRVk^ra^LZ~&?0-W>gl+z2201zJ zQCuCXpHw_8N<8RyITy4&2y6djMGDc6<(%tXr>_0f%u-WN;f|r1l5Cq;!R>F-r7Qtj zZ~*PS5p~ohW`z~r2uP^C%TLKuU!2?^Uysjz0EbbKX4*2~U=T7gUQ{sDK*MmqaMB)h z-KeX%#%lXnoy1C3b%ub}jria{iFc{v`;M@38PS3995(ns%e}rz+T4nJfowvxHj^JX-%G3p=_Xo7 zd$S<~`9W?~Pj%1vgP6|Y6)A9geI_JDlkBP{3b#3(qNr`IVxuf*2HfL>i}t2w9G10( zqKi$pDW?CZ;%)+H;B~PN)or3>X+EKNDY3s_STWM~ug`&K6X z*s~A}b%L3-=82t$N`2j4g6rBtAc8|3ZACO18@#k~Us?6`Ot+bHm{BgK&YpAe+S9~81EMXH24uamT zQ*ZW)XS$M~NlqNT*6!|{K>NKNIwyU&FPz;SI-PcAY`dI+N?BE`RUU))wfW(?v1jaB zdgEc~BFn!3?MQQ7J$BpAh!+q~yU(0a7mtxU7b!{wCorO>_^z=YC9~fl;1v!EV+Djf znEH<*oUGmFkq>!$OQ1v}BAnh~OO1k+F-(2)VahbwfC-2VRr)$Zb4(9p_H9=Om9TY; zg|StPJ88XZnanOG07Der$Id@+RqXh1DZh!TzniKN5HLTB>fZIMvZJ*6K`2!hxk3oPAAfAsTix7z2ODVgNv(5@TS$;daW$cy3ZOokW4V>}K2aVdVU} zRRw?WO@zN8GH#{|{MAIsRqXUE8Sl-Lg)mKrmK%zxzVx1(afcRqrP@#sw~H*C_(a`@hH{Az<=?r}Z^(~39c{hHWJXb%bkmBUapCNA%p&QiM`V5)hL|0;z z^3C2m(>W|WZ#o%MzXmX}&$>^s#{c)ANWA@EolUkNhTYjB7Pq%eeI(*rieKPB@vm$O zz5E&LX>t@xxEguXat*2nDdGC^CeZZlNe5bE3CeDntX?tOO%D&@8Tgsm59e$bsvK`w z=Gwp*Ic2qS;X>p<~*J@sR0TB5Dk&OGaC}nLFEf8gtSSmCUcwr$U^SbqrK-Z6!(}@a#3kh z`HOJtmkou@I8N+VuH7uvsSD+w%-h-YEXu%;ff_G#b0BJ)g1>lb+z4*^SZ`+O7C=9mr6yHQXAwcs$6olM$j4Js9?(AaRtvYx7&zp#jrISFpsva(rM#MB zsZ!I1`VuJ;&KlGGIjkL@=QGUaz3?SY=doeyaoBNDTLwZIqVIrg0%dh&l_&kK+90g8 z%L`pMS80+L2*mxHA)K_vFfJ3q0utfGHY{RVsh`a`H_jI~zWLV@-7 zUvppb38wW=T7c^)aC`-gJosR#L0-G^-QEFX7p0Yc^0Z-QfqH@|$YQBWPs;_G7&N>m zDVHiG0ieFBU49EU&#W3=hS$9vUM+AuiUs@MDQ&lm{O}_)<3{Wo=)+tlfz>@6P3(ZstlkO}P+GCCKK3DVGd?KC`}OTEUcr=8{YbEHph;)=## z?^N$dv;Y(PlIgDDI%@_Jk~8%TS>Z9l4H7o&wPR+K9^*=(MwEflIH=D#Ffjy-Wbc2L znV=^~X&=Y@ONd$GL5E4y*qeL@&_6WdS+9IZB7ebKLyAuwsN@MGYi(bPVeZP*SR}wU^5D6`!)+AIkAC z%yjcZj+rMsTSq9OB1?I53ySZrlDkgME{eCM#^@_xWL@eetAZ1TVFQo93@gJf{pVME z>MS%}3Iofh$LEYTWTQ|!80k+RupRunK6I#W>v`m3+gQRb$wUf4tEoup9S4%toVE5I zU=)cfVGhfU14AT^pr4*5Q1$w?dPFVMrQQJ-Z^^v>WOFDgl(8#dMwHkHX##E%Rs^Xl zT4m!Ts{C*ZbTjKwvbPVbfge+1q{qy-C#x2VvGbjty5lmG|SqFud zXu{X>zcr+5Ae%%7$!MSkt`Hn=|Cx-{lbIRQ4+kh|H}>a*s83OGshInht=zajnFN=3 zhixZy-m`@LZS@L0u%XHA{dmrHe2}AOI?w4t+xEKa1h{Gk9H=O0dKkW14HF!+JKN*2 z$Q-KR|B;!+=(Iv)atu+PAn}zHuO~ z+4k;RYY|BX(SUBZjS9{6aEaBJ=7zjVT3@)ApjM4=_ z+B6Eh{<;sEY=YsZfr?UI<-$BPL*Y`j2m~^H;VB;?zn+GZCczl)Dgwuao<7AqJ#RRfB$!2(bZd`ce*#*T9bw3mV=jN36$w3VNRLj6R z+fE@^#(tdxaqhH1gQ&kWe!BODiU(RFa@m|^Q9hWGIDQWuvP&f@1<-&Iw`fESz>$a6 z#v@&eR5ywf?kNOK#YF<>ZlPcZ1_tB#%6NPcS895d#D$j?diaNPyBce;aphw_M>c^_ zhHi zb%XsJ0+SxFJHbwbv)W89GXMn!L=R}D(H=HLy#@;W$}bP&q|X26}oEVM#?HJ zHgQc)L9;Iu+AJcxx`~n}ADnsC18zsI-HA13Ike~rN6|N^nWLFVMpDL`_d7@_3pO<@ z5Vc*mK)6^qWdqLtFf&e~19OPo7SMa)gE7O#cNUtYT?1%pm`ucRZ9@dcHTz?u-Wvxtf?sXF(twMC>w>)X(aiofH2H7Yr3 zF5t{wQO%px&e~feY~<4(_%P(n--H5b%hfp%Yz+BUpSenPnu;Amm1<%MfUDYv)Tou# zeZ7Eant@}B1eEpl&>t05aGA3n7wwQ;o-NJC9_kq zWKRRYMr$}jkg?Jc>O$P^7ET=cnh(_bu+^hxk$Gk&?gcx}E}bd@a046K8rGjk08FqO z1uktm2tPv>s%YxfEmHMDT$SK?D%xq0`f^C-)!G?|rnKili~GR{!GhTH0Ekp>uaJ}? z({3sv4~Ptg8hKxGO005A{oj&-_>nO6JQ)KDvGn!42gw(?{=Gg48WOX2(VNXWvGSSj z;y$>+djpgNoCv-)`lH%vp>vRR0!U{9g7YP!M7$r( z4QV*wvcJ!d8du z^mRU(e7^B-?I>!D-}&Z)W(?EA+q;7r2Y#ar2v&kup*5Q#2>)b3Dk6i7q^KBuE+eL^ zh0fn^(sfH>iW5J%krURWR^^Tg#n<#ypcqUv=DgVf3);r;E##Z_upMP8D>T(1nhZ)h z-awl-C>o!;0|EN@gAsxTBN?vc<;Ge63c-hfsVvN|s0U?8&5%GRioC-vje}*V?z#{D zWl&szbI&@AA|S|BWIf93*zz?e?tM&O2~=13+0OYdY~K-@$nz78#~~C$-WRk=|1BT0 z`Y5UE&z6bv^zV6B)$iqTge?oJojfjD)>F$rh-`xm)0f#;TjN_|`nOYo$VV@BTcAEf z0WlO64Lyx_>F!T3xteAEA8BUTr1<;059LT~ebpoiW?wMM)wT0 zb(=#(Kr=Td30&J;b-8={qzmua`SbeQ{)i>^Gb}N2ydq+p1a)$MG)jB~ue`wmzkxb!6LoW|uqX3@S#FI)!1n z6w-CeKvqGTr*6ySLY-oEH%liEMHu*Ny#sr=OeJZ!LWqrK`vx6r%345LFHHxe?5&lh zecz=qK=3qq76ti$_h^@}b&T@K7I6X4$-cHb4@I3){=I_tx^?a^I{vi_!s#)Sw}Z7ALmV9ZaY+zx zw+pem1>{Wh={ZhvyhpXeFB>E^hJrL=uhBc97^1|WAngUz121<-FgvPfv-vVY=&Pu# zT*8Po7_LSFCR~GwvIa-afhDm7Uu6+Kw2B`1PHAyYBXd$5y>O7euRf`!Zp}fGpXI9y zX2QLXX?0;9>vgcy#NAAZDhOMVoP4jG_F-$nM#DIbj<2O)8` z;0fYkr#g5mLQrb*V8$K-SjB; zxayA6RZgPlY8B#g!B^#Jp8+LlRAi_Z8iYKC&b*-BNn;}E6nA`9>|}UVnC-E4a4jc? z%wx})6SO2v^q9nDWXX8h4bqx`qupsV6vp!oQ|S-_V-F7xpnJFd?sf0(@z*F|O%V<8 zlnDgE3R$Z8VKa!LeFOeN7ubO^{Q=AIq#><_fj@&*l|q??3A`ZKcY>8T^WF(7KGYQP zH}&xyk8cHOu;FESJ|x#{1O;@FNm`u)l{Hsf@_)x|6Y`pYseI-~GJ>o_;OMu0cIN_5 zj!!^Ah8aOys1J`C!x^&F8%WSG4jRyIxO%LUwI4w-H4{Lt&pxX88BM7vde*;pra_|j zj3eq>CaRdLL!!$BhP}j2`LfQ`RkKU9hhAhUKCN93rZguLxekh#iyPGa%hv|ZgkSoM z1Chc3Uyf_0SXwcBdTb??VEq@6f$-}FWiIr7g>}0xVlDyQaK%f?{};Avf?3khuJeAc zfJ&!!(NwJq<`6qyPfy4$8VeYRCGC?j)Q#^R0I=@_iQn0L6SrGKICriF^1ED7=;fD4 zpt>|X%vV>N3{ykmE_YA(MO6tYlwR1SRC~LT)?x- zGqTZuTgv2Vps%Sv^%C;!Tmgm~b+9$;{Q*aluRnLFqjzk2sPyPJz>2mMgOaSJm8h?I zJ4W_f$B+-RWDr&-Y#D%y(Hqa!9;Ea>J*K>QdNuyNJ2z|yoTl;l)MuBm*MO!kxmGSP zodoHXGRfOmGnJ+q;C^aD+I|?r%nyN;`_>yB1UM_4m2|*RJ~?Kx`62Q<4%A03e?n0D$y= zbI*+Qo%H|9JR8qNEv8=G6V!^r z+ziiV*QdDy`08cKnck(wW6GSSRh^m(1c$@(%e~f(P1?H4GH<97F=<0-Ix-PUQH+;n zuxL|5q;xPqLB&#`(i$tzckJZ(dcN4tfE)mAuQ*a+diGGnXk0;$!KFG5$(}k@td6mM z*R=7?C5|lAe?6`$(m?)&RJQUZK_4HTt)EymYF3f9l+Qr2MzH|7(Adxzv~BA$!PI?- zGRncACT`M_7?x4E7I<|ZWM>89tx#OR$>ta@qECV@p=EEZVd>@Du3k^dqbtAP)ku7} z?E5VFW^P7v2hz$(NU&COKLK1NdMFQZ*& zkZYlFQ(-Qx{WOJ=7h&N)-m{*|lK>_W@!)p~+%aFf=yy-@Yqzh{F-@PstdEdH1#&4j z0>#_$_o`fn^>>2f%&W9=ar^KVwz5%Pm+JDc?nZ8^QXZ*sEnF5mUC!43jFz$-kpn4S zWq=(SIo7JOG+ZCz?qZP}8Hk0X`YGFnsBriG*prd5MFBT?JN^{64hNR*HW3dZdEwi<1T%HtBt$1bMSj^f&P0{-f!I&B{L%cTD z6s|_GqG!7WK9T;Kl!hsWWKET>lAdRk^QGZosxN(_wtU2XUk_ZWoL|T2n!608{K!#l zCMJj}s2s}TMu`J-?$(hqRVo{Evu9@TLpp-&-cCetPJ)qi-!&*jFk;#uOUoelCeook@D{F&n(7z6dNE{-U zb$2wyaK9R&zJf|3-w^;cpek)h-4fp5+X?~-RT25ULm7W)rZW`F)*a2;yB(7PCTW?m zY=B1rZTEQ{BlDxNB*Wjm^jK6*oZ@~e&Vy(|b}CQcE8Xf%=X?9&&&`!0$K&o1#a>(I zou#+g#uQ0KqYMq#2-EDC7BMrW0y`9W1SAj78^<4eA1&YGc}hX>elpEPQi##V`Z0e3 zW#e<%Q3S`Qf}-`+B$vlK4yt^HQ1H|fv+hTG0$q&D_J%$ac(90fBAT=$miBZaW zHga(UAVh*+3|A%q3V!qSg29>k_I$&oJd|*1?YY8tju)iZDs8uadSAGfKv71?dv_TO zM%aS@2(#u{V=vfpYY8wW7BkDSSu)OPi@h>eG6Lm?uG!7ye<|0Y^!cq3xT2>YI@vVc zkL%<1K-0>s`|Ecu{wU3==j_yRt#NCmq$=|OF$*^`j>$JrAW3EimzBbw7Yn4_Op7_v zMrZA-)AH&McytK&yUSesTm8mG!%EJbz)Mp^t)KN$o=BRaWqw$c_^->H`Ry%Yww#JPXq<41&%;vnf#&b`o`toEbY3lS5WMXz`!=J;H zAxk?V>sb^35M*U~t^cZexcvVphw9<8My5^Sl*PP#KeTSInZ$%B| z`Bh##&VvS1ZX~7#ox7uT1wb;*60C9v|MledG+)kmBDfW(Eq~_7jLxH>Yrk%BaXpiE zu8jjT2mOWcyf}%C?3Y88Vap~Ev*kVxJqcLo>s7bmwNFb0i-R5=mVV#}wk^-=cFxjx zCNmD0Wvy z)pcf0XG!P}iZB^2rS+%M9X$-T2alcCmN~fDXXScs!U(@~XoI~04S zxb7sNq{y1pzMYrP!P^&!V2*;agZMugBU=Asy_ayv$2tqMOf&VR^baw-4)2EnobOWx z&KvWdGgI@(R2)Ljqe?pt{-DTH_W}=@d%_O2htSb+Zj54Qfl^>Tm^_b-EqP&_C!HL8 z)*|=X=>b>lt|TkW!b)d`sqJL84DPr&6_hNImQa8LKDymvZeiW}wPl@6;Q${*sP&Ka z3pWDueF*AvcvYPLSVTlcYt3&F_JmZ2UkF&E!O^7Lk^KAqQ+`c6zGTl`3gPV~o6Sz= z!_!C=n@y_(oKSZGy|RW~WB||wu+od?RZ`2%z7fg=&sSnwc|sjBZL+Z)8q)eCpNQfZ zXZdPJOWp~Op$h)n2YM96dqtn3f*|%(QY(06X`Kz=t3$lNb0hI|N;bA)5MEuOsS3YT zyg+y#v|S10f^+v43lK|8lpp3?*$OgYcZ66c_ue+{D0L`j`=)41_rsooKxJ&LbILzI ztGl{MX6#2{NQA9AUjA|p=5owgGt^_Ge$K^5YpKV#*gzLSNZpj z?`}vAowz1U;zLe;l!z37{f7{+K!%@=naROq&GXPnHp-|rc%Q&pCPOAZfzs~p;+ zp!3pDwKmh>$Z7KclsFJaZv5nJz-L{%l$7>epQMQTi z;nAqw#J%;^2uX&bhPVfT>g^IYSD5PqLsJ;P!1#t@?Q0TQ52-+T(5jI>w+^{O0@c?7s6- z80`_3eIl8K4sRKpvAlQ0OwKFSkWx3BB(b}5;+Nk}C#ay(QfIt#RewD#2namu=j@#Y zoOFwl-lvPnnlB&c-h;T|7Jm@V$gnNE03atl#Oy}>*JC|T^JzAU9H4jGq*G4VsWP%r$9(6ILG=X{>Yh2iaqa&{yKIc_zKE_gTt|dgE~fc3aewH znL8m{K@#nQIG6H{WG7++Js`D7NVEH&0^pSiIs=G|y@TbTccPrkdFha?TkgU51$6F9 zLynOG`jo>k$E*(rNgc;X7xScr3Bje9&RK+|5$v-PV*&b-d$|R)I5rMP0Pno2N7THA z&e$xQ_*x1U&P{NcR{6i7+mTZ)qnUc&2KY%>GNzyLjoBp^lM-XeO=|0m59>yr;^>ct zCJujJ^1PV^*bg|xVC9545!Z$1gr~@eBogkEh6TjskGaCRtf+ARF6(7wSf)GHv(;Bc zt}x1FU>j{D>hkSw%gv$Eu`6JmqG%A_PL$X8AbkPtEMz2Y(bktYK#8$Rcu|^9L|rov z$4p00wZ+8HTXi@6aCRh#cz*cg>$KU`qt2AkrFh%11;Y&|StYMq4SGQ%paP|gcxcjz zi-r2JW{^)Zs+J!Cz!|KYc`RkIgzX?}A%+wd+U&IN7r`%dp7B2BQt?q z9Z&qHjHuo*Sc}G1(47F=dG{gk416!;(M2_&cOkQd0CggVAQ78(!Bkwz-%y-_+1p)E z)!3YEJ>H1a5nF`o3+V^f7d27VVFqG6*?;$hS`{DQU^IwG{bXSvuFS@49!SImR0R(K zrJF7=t3iYHxCy~aHC(n>P(Vc)LwiJ)Eak@0GER;pQY+c?78MUvjTj%JyOi#y&{Ix) z8alMa-Bv?h#fIq<)h0c^q50K9QyPy94r236C<|Rw_ZC+CDVT~B-Ir1pu{#+nOCWnGOq0$;4(fp_m)yi#%#~*7OTwc zli@|Wu^Nwi8~uaiVya69)2xGu+Xg=Y?z!R^&*A7GR{8?P)ZE{e8bYVaAM)Of;IXBS z{RhWxviVPc_OSrccmMN*p2J|F@A;QBGuQr~(Aob>`ThroYGVE`WajSZWNiK4L@CaC z%%SidZn$sV9w8=0B4|(?Mv&h6wtsSp5cMeV-CR8v)AZWSUJF~$A=?|FPgKRlrfOC+ zIN=_k%g9YlXGLY@grmFryMDjr%LP?!4-nttZ%^3~bi93X9V4RgbR~_HyW(U~&#^?I zTeJMQ%8?fC-|0w}>-*o&n@8MH?{Tr@t-%BQlvd|%B~^I5qX$r5D$U7@lYX5o$Pe#p zKy5b+{1Of&N^=^w=j4^Zqwk~DU7-p58vxf7qbd`Ax`kO^v5 z*P_mf1m&RqyS!bL3A++s87P2J8#f?`7U?6I;3a=n#ewx&fdv$^vGQXg|I&O3?fK|@U zftqs9Td53DLrD^k3s!!z>Tp<%Lf=8EA>FLPR}}G_g=Yylfp7SxvA0~BTpIZ_{f|!~ zR+1XvSR8}&8V+kL!VrSr=C%cnk9>`800Afevbv{OvD5q=qlj}FysQ-n(IIPu#3m5R z6D8W{>#UJgkd@N<{nIM81{uT(c;B$P4;j2Go_0@I*>CrVBT~#>xu98hL=%MPR4g-0 z*-xR8Br)u30U$z@#PHVlmxgMhp$rpDJ`;G)k0u824Kskf@4$G%-@?Nh9yegvXkD7BT zH99^uZNd}UU2z=Jp2du!7)*|Yrdy4*=88}8K=HG^2f>OTNgR;DDAkf3Bwxj|$OHW( zh$5&WPgR&~x*$MBRS<@rErFu*IQR$bB16GOPDKu_5NZhFG{SBJS#5L*JVLOA4kbX$ zMk(qa;J5a(#YTNtl`wSL*bcxb=(#+rioe8)SHaNGW)gk4YRI#WZ|ImTeNgL3&Ea{t z(50!5!6J5PV!9UUUVvkx-G4FJo@WB0LO5MQs{eI}CGI$XiJA3UpQhPdB4VWmDj+oA zaSw>w$(}=5i4rexnz8Bt&p0f{lp0XA&9sko!cgba%Lk%GgU9E*T;1i&xK%`{wv|xy z2MA*Z`4&)W|!bW)8z52J>&a(n5I_N`;*wzbXM!9nAHjIAqk6;8Wx?W+bLze%AyXKAfkOZmZSiB~N~l?Ci39W-`_PXDIe4`#>7MABm~le^I0l%y zAs<6sFRCf$BsNc1JeFb#J1M~9?+I5ZWYR~5Gd(~zd6aB4U?z5quKT(WFJgo_TlBFu zlxy`wlfc!%XYfYsuJa;#6i2UMe9zPPRfa5n)E%A(y2Fn32Iv}^X`>6$ z$HO}h>m@*!A38W;KAG`_%>z}HYTDsXjSzS*uSj~bTLIjH!B!51f$D{(L|G74SW|Cb zkf+(DHy(n)O(`ydLVx*RzWhN$m{wCiB5I`C3OLCP(*pQIvu7b+j;-1%xem zB7;l1yn`Zmf(eP4D$)*X+(LSy7|qea_}3k;!Yk~V^AoXHV%@!Jx4%IZl@}10j(wV_-T8$51gs@jDk`f9tq-WxW9TEETBVKTNW@J3jC-EZEY_wTO>ymC9fbKX2)f zo?MKO#TVOd^P5kUe-V|GyuO7EvkVB8V35l)vCybJb`ziePEoK{`R9_=(Hbj7E{0i3 z8f&a_5t=40;}Z0i8t!YtdILS4^9t>BCdtG|fvrM3%1QnCY{03p%kH_GIPoJBTb8j@ zB22@yL^m5+xH;WvfxN8(Bxy!sPBK#Quq^+&1C>t7FLY3u@W~iMyN*sZXVC1qc z_1Q&mx?yl4w2D2`PUv|S&N(TziT9|(nw!*F36V9vr0ZhB)F$;oZoP~Z^Gd%mXyWp)Nn@jGyDjQf+_c8gBKXJ*%IAKP3~4ok^a z0|<0bCDm$mc!j_Mtw|EW9+#5er4M9DtBkv;3o%;GxmaneUsyGo$OSOpbnY3<0^yZm zweDE10aBRakI0qPf;H5wzNg82cyt`ILI^lXC?HzpF6YE`k)mKIhqq~N8g8`vanz3> z3G7OvJ)!7*-ckj5mf5E4fWVc-s>$9NRXF+se2rC^{h=Js9#^1}T1LPgW{hgKeRT&PcJtF!SLDr;Znp?-h~Js!qbN4Yf|9}YOu1zaQD;}(6OAe|e- zB`IWBeG|+DsMfw{pLP-Qq@XdVM}I1hUezqz)!96m_Ap15Mm+2GqI{+ft6F~Qap zvzLM~V8f8>M5VI#Gk=XPG+mOUL zJ!q;!VW+7jN}B|k1({rL)H-0j4liWRzt8);5j?2*83{|+iU(7nExF8J5qfyS$aPp_ z;o#jni@EiDeD&M!zZj>x>px$u3^Ef~(F4{`>8aj*fR| ziS|5pAZt1S0I~3@L{wuIQ?Gu@GI)KZt3S8el6|;7w7taRmCjdePO=o zqT~GbzaNQ~AOR=DRX+;0psafjP9oyspEEm?%S+XkcxB(wQb4G5^BbPR+?D0o!dRMz zIE1x?b%pI+Lo<|7_p1i(P|gS4V2UiQS;u0+)(wdvT|vK)a(7Ap>MZXL#sjYh;tvBV zq{x1;t=RU|`v8+hA)?Uon5gJDv+W^=~GYV9InPJlz49(dd%DlZ6aUZdj{9~V< zMEtG9*FXk$^NxL4dYG&Fib`wc4dlXS&N8E6m$4v()hJf*^tQUByYWy^X=#+ab$!;y zq!>W>CVlhi;NkJDR@>VW_&dK(!S)wmvh3;7oSA)VR21dX{;*)hMLR$(1LX?uc(;#o z$scUaUQ+R&s_cI<5plN{Qvdw4&)6`+S!#XS98b{DK{nTt%-=8JMwJR$x{Oy`$fNY#}~BO z*;q*vc*1J9WOKL`#OWw{R_vq;wtfjEvrt}+J)h|p(f=As1-sEFGMh~h2Y$R++~F%m zxw*Gse<4?7{%jH0Y`IhfLN6cYtR;@SUnt<=nit<;kT&Pj5cEaotT9wC{@i_;4B_xI zUJpm#d0do-+e0#P_A6;V;!xudH)ql%3D!xdRnlAvF@Yg(K5ozAV!|t>> z1r`Qkn&ZYWxO`qL?A@e>Z=mpL8z7*Zb$b#Ly>yGS)%nqj1n_qLR(|WnvD(u9Z|y zOwL5X0kIO*-D96~6)1a;FQI%_whTmvYy*nBvw#^j4@@`aKkNBpWo`*e8W~aFi`0=M zXo{VGQbKu!iGr*)(?>5$;U!C@t1C3%I7yG)6DkiniMUt-B^Tcpr0tbwi%k*Qb8F#3 z-W*0Z<3a7!=O5}Moo278lLHD3cq=VO{np>fq^O5#f*wjZi-+{?dFma0lJyhGbwc#BS147oajK`5^C}UP(*n?vXB&}~xVUex z-vEDm6OluY6aEJ(2ePe6WY^#)rAtN7^ONQG2(zf4u*7y$Pj#ypo>PCm@X)Syp>?}t zhefTFGh=j!r2i+b$dcVejxhZAu5>@C(8_=kHPKJ((=wliA7RDUJ2V6)Ehjg9@(R+7 zMGv+=!tURGUD(I$&OMTjtD2v8?epzgAGz#pm-l+7OmARxb#*|I`pO3G*B(0KM3ZS4 zlO;AWt-kJPtCOS3nyg!7;ze`+@`mxj@#p^W$lSp*wc4+m;sIHp^(3Vgib5{YBKf8W z2$^+w#)owy>g>KC7m4C0=M<7{M%MX#mx884?&xr(RwI|%2X|IdSSl3{IwGx$Z_O}U zfA=vUghjG3J!E_fL{R}4{|EGc%0L*>uD`SYgn9@3{|_p{#P)x5`fYWo*nd<+5Ai)d zbsGv~#GV>tzhJZ9kQ6l%!BD?UNi<<|;I&mN_Yc>h*g=u(f}j$dR>cUOFVn7@38Tx+ zR{NtFY=%y+%Qx0fE1#)5Eo+38h(r?sHeqi9>>{Q*RL$~IL{P3=E%aWH{e#*8QCu#0 z`bu!dc6Vl^R9miWu-5i=UF{UF9PCJS-G@SgQn5IX^S8!#DmMY256iR%k-vp}5E2~r z!`pE?qK8y6*mzGMPJbN*5Z4yKCNtWx5v`eI3TZC2I$Z4;mWi6YNCC^G{PogB3OiER!t*9j4)KC|) zOM0mP_BZp{eU7^BYGopfDUvmMsmbA#BzfEA*xH5!{Y z9C9Fo&;Abx+p7tb6dLCh>&K%c+o>{X|h+4aQVBT52GZ(Gw4EUR=g^ zCWpryN>G0CW)a|ruL)w?AD>wRLmgsea^=Z9rKK#X_k&XE>B~&@aL!N zhJ+=CL$qS5MP{8xN#2$s&aVJrRj-r+J@6MLq4AfJ)P$f0I z=Q&%qV(8~<7ZIHprOQr0{zwh6qXwxsBq11m}qDTeQH10rpimit?WDN9? zUdL)1I2OYh(Tq4{$#XpDEyQ7lXQW+2JyI(;%D9MU&()+KWvkh+jS?h3Sn?39r}0;f z;vE|QxJ={RTrkD=V4F3s!g%Y~*}NXiJC}@AtGgNuzM<97QO@+kw?Ym>d|e^N&NLie zWP(1yz{y32tDgOc3n0e)-O>9tzgbNgm9O77oraE$dSC`W_J9jd(Cb{Ri9~QcWU(jr zCKS@O=7I^}cjh|$auAl;T5SgbYpn4hm3C#L277<=AvJp+3_0#9=DpGZ*xId=Pu7EX zcRIK#W6ldTib1{-&!+9d1Ea_a7{Gx$rVkwy&(q?Aj@{^}W!Y!J!q1$S6Xp=6=s)ks zq4>mj3`Ycy%$Rm@#Zv$!u^K06W)ef`Xu+LNw)Uz8d3QKL_Ib^DN-pkkq^%|_K=8v7!@k|DAL0>*PCdo^l!i%7dfpiLkpo~y+8vIfMEEKS?z3e1~fK>pOd&xF^| zoMsdBp@H^M9^o$1S4Tf;2t^O+cDghRt{T>r3>Y{2^c9nmSuLwJz~f9c*L2IVWxvSa z9fwlM@L$yF7s-XgvwyIKUtBNXfBq5rbqVj!y#W9+V}SrD{x?p})Is0Q%-rz5Th*?# zFJrK!5PxEaxT5w(J%U%s(Q6{*)sTP$AOTsof)FyAM_=j=F`1ZRR>9-kz)5t%*!Csf zE*4tb*JVQhfX=h3OiMaD{`;xu__(;Z=*%pN>3s{P^8xIA&vm^d*+@AjqlH&U|GP<4 zyU@ujbt%+DJyAAtTIH5IrDEKrUHVA5ffA{mB5Xdqi)P#<_o)1rx{!K0(E>~P(oM?u z@+dz?w3hXrvb=y@R~U36bsqX}*eyU_+ov~UZDrZmWq^S4BcsHF`V$mgrIF52B$_M* zfAKr_CJjWTn*dE=dePJ&wMGdhuiP7#_x+|%xJrf8l89!eky28qdCZSUKU2ox^b8|=fq^;-3zn=S*?>)_%tR%%`pO^e6A6hV=cRN}Pndy> zi(wXVdNKG2?hNh>(O6njMA#D{6uv#CA5C=Q4-QT|(^UnuR4M>Zd{ZtWiFDyf?Q!6O zCA!7s4m1dG=zVX&Y(5oV{8Z@ukj{dd$mrEaRgU>ngz0dd#WVSD%6LE-j9_z-_ z3iX*uvK@cFPOe$^fp)1Py_1uAv#TyWG_`$SFsDbzBh?jZcsEO5&rSQUx||StxMmM3 zpvZ60dl6=iZ-sro8tGtcS~g)ErNvW_YHlakYY8A&IhmwqPdghx>b*QxO8&UooJ3*} z-8h6__(2}nxTt4$q#)U0%MAJGrE$F}l)%sPR;fZI2G=gQ#LGl;y~w>2Mj`-t`DcjZ#ZI@OVyPNDKu#VZXm_g>3*Wjp@D%_*55bWXZub(MhB*vOSG z(>BgcPK!Pze_40=N_TfYf6VEp5QfZp9W>Z2DABza$cIeah-X7`iy^ybn1Pzw52e!J z4!8(qs=(J+PKJORnSD#QY_(TL0;QSYx~mHFP@?IOsAR9Si;!N`2;`6+pXIx<}FgH~jsteJF9EGY*|L&4DVo^#i&_HKNs&hvgOC_Ba z$(azz5&qYibOXgYMS9s5U^cdBkxfn8{qB?rMevu|oBz{yjkMDw^3hH6b^_$>aw|&V zfiV5nja1yS3?dW6pkO3`VVH@o))n$64nc8Uu+gQn^8HwwyEhg}#GzF?kBp}MuQPl< zsxr$@^K=0a?1&HUD!Qo7yGI%AOuf7TbA0~vt_J556vAS$rPSDDjUs_&juE9y&SWCr zxjNO%Jn&O5h;cCPwdRE*YHw=2YhmCjk!+$DoQ`H#51N1-qMX`$6uc{gy?y+ppiW^= z_C`&5x!FW#MF}B@m^q-ryzT>$*1MN)kOeYuo9lK)=`lC9?HY#0ty(ka_c+qF^rEc4 zcS0T7)=%IuOaGthDVIO5v8`UYO~YE6X~q&-DnCs$ewdf(9WsmRG?`t-P$t>v>I$sO zN|BI0m0{to&H@vJJa~Pr2+QHf{w9Mh;wcPE>hJP54$$Uk+hpOgk#3E}G>$jPMBL_r zh;ABCX{@|tcp-cvaPh(MF3i=G6>tJExU00Q)2mr#fL)XS#%Fw!7e!-Ej72oR175vi z@n`X5g3;bw19@0OmalGKB+~0Ds>>-TplsNNmB7spPo5Fpu;T>FGd03uFPb5=3@4o0;Dr1Pfvx zAj@G>FG5GzTLdfh!0Y4sr7?rrgOgqf3l{0V;0psWanm2SY>`q|r^aC*3?E z^PqwHNJC$^BIDHy-%k01jYK_)1u%&op8k5yoj19ebyq^S?5%CJoTU&f7(`G=vpA=g zD8seIwf)4!WMym`&|@tVs5kvs$;(7q7xCqgjp3L~$d)rcAzslB0;AzXKM}<4%GlR& zj?@%CFjV(%lt6HN-y2AAx~0j)sWlL>$V%@{JN}kshH{pFssoRexBwBj~MwBVQ z)Vz6w8v^rz#y|PH`{K|zVOSVbdq8R78nDoM5Lvs~50dE^^y@}1#kfY`L|L25ydY>q zIUk77ICxbi1=FY$O-V)H+Sc#bVl*PNu_F&qXb0@VipJkLf?pN13Q4AV!l1Sjr?fh# z$=Y=rJ!x$mL2Ye<$wDozxQ0T75@4}|k#h@IT_IIj@v&qwKObe)fIpKpIhpcqg!v4H zqi9-fVXC0jec(H6ULEb6!OE7ZB-A*7^k2I~pmBJTVsuUYm@^o{Xa_P%qPHo0b1@rYpWT}ai@aoBhF5+Oi4MG(M z1UP(e)I{lHXvMBa;Qs?qK(D_GbDkwK-9n+y`&}9*j4C5BpEK928b-v7tZErh?of(v z6B-USp+daUx>zUtR3=y_WW#7JufjDn+ePA!w#=Y|y=#m}ezWg-Cr{Jp54(7w?|zD( zz5B3d?sxUzKODS=;=zCLzuZ6g5AMrl*J>!T*WV)Yg6KqtesOl=kLd3ZP`9QToI;ea zq}`ZLW_ZJ$<+Gl>q1%zVB}TTEm*L*>8~}$70Hp`uZJC0N)deQ9s8PD|5xylqj83<1 z?5aag@oroSANpIK11g-l!54?V^4;+71MF2^40hoDFjT{}VMRrI!Wnk8TW_8rG%;vC z&@>?KC#LUKHrQOxyE~|`A{=8@A6Qc1H_5e3)_B&Erz+~!P-FHGp2mY}frNU(_v886 ze35l#O$Mx8p2EyX4j(Ac>?ocX-l}w;i@!-dpIt%^6PqBZ#h$VN7+B@ldbF!Zx|0La zwuHHeDF}%UI~o9>0na`DyH{H5)r;r{uWw&RPqn-e+V3$EJgHJK{7%IkzE3L_r3b+$ z#{ZDaRKaZaRZzi&1CH5=J#W+0*1W(TaFDl zOeLP^s%GHkusPI5JfA8a37P{YvWj1#cRE7;ybBxavHZI^;eebkTrH4~kgpcT|3&P- zMZ{Weo^0Bz`k`Vsju43;j0Tx_Q{9l0mTLc&jfl1wF;|~^IaQh^Wa5O~ zLPh1~_u`ImP0A+ha!NhiVX(UPj*N6e;0hH>+2RQ^5#eBO=g=2Mn98(qX13uy<%L?(M+QHsNmBb{)5CxS>AQ>%JjpWJG4tnmF1@4-BlEw}awb z*cRZHrKgSo>7$_3Q}c#sg6c}0J{a;|iWN%;uR$Yn8+@Nbpcdv)d}Y+$Uc?QFCV6^o(Yl=dI8un42oz$2#)gVHVQr=Y&yM%$0vfez+-y$NtI!nXqF1Usx8)jP9~`o9 z&_bO-LM|fVnqL^Td2FU60<{^_iigq^w5~0t0b=n1%iTSlm-O6Z>qEuiw1f^# z7ohjeM~@!9{^*g`o098KMiU+C=+<*LaRC@dbwU|EDtUZDtIGg@3fcs*XEh1%} zC+64yhcSkuBv6z(w2Au(L#K%ze5woi;7&HWXc`x}Nb5Yg81bs!vuMi^KI6C8O->WU zW5}uoT|G*fWg$<9_x5MOz!h%bA|$m zxJtyA* z&&)$o4-$u3=_ZRa4wNayvs!V12$}lDjw-}n5_w*tYrmAX`?%&8EUmSWLDWtwXLE((XID3T zwA^9~rB!PTqshg5zP||e{6`V(pIe_!{``;|5|WKCM+EvnKVcFeCL?~O%@{~79kw>R zU1dyovif~OJ0!Okm?6)#E%F}aKhm_weLHShBry>Ez5w~E`Y_&6VIc4tkbeZgeUsIE z=hl_|_?<;&uz#lLk-q&)x^+u1`}$=HXw%^W#yFkWI|6cwX9FNrYZ$qkza*HaDJ^YW zj&_fs53jQ96xC(Xt+?oriKUK9S?vO;&{_yF$GZ0dv~v(GUiEz&eSL+~A_>epyt94! z!fBw<`!w#|9AFo3Jm8(%3=s{X=B)AHfz~_XI1)O~L586%0DW(I1zSYqkHCS6H_-ud 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

g~y* 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ńx%eUP2KOVqKb z<01D4-tLC(wY)bS2>QvUP2q`UkgE%Ll2?^4rttbeAv>6U_}ZwO>rY#JtOb#Q%nU>X zth__wvzYwRl zG^qg+|DV^Mn4SjCJxY#j&jeA*msq}Nw}kqQL5sNQzhwpXe$n{`Stli~$sS?tk6Q@c z3`%E$(HiDGbA-elY5)$3>GQmVq;{4VA=5-xdA3rR#~Wos^xY)sNgB;hPj6j}qf(N1 zQ44=$Q9?j*G*nCQH2hD~xHB7h>V3{)O1z!B{jd~uNw#+F0EI6pq!*V43=k=>TdS6h zR~Q|vJQNPVEh=eL!wLHJ+NSpJT%E*5Fltkpiqp~j=wjniI_i1jT>3@HMQ_bsdX&wh zR|dcG_}};f?)-ob>?HB;a2H%l_VSYW_9Ki1xaacHc+C%=0;u(Ak)UVsTAAJ#AwYeP zI9%NFs~-INj`L32_HVfM$dg(2R!k0hC1tJXqdBR2Pqq>Lw9iJd(>h==mb}2V0bl4d zhk(TLv^H5ig+?;*xC9Ai|4~^vG0Qpq_rubbyZk zA?L;J_QZo28cfvXN~dRxNvj(&=x^+WRlXKF>WQQdO!jl^bjRTmeoFyj+X-l+IJ z%LYG23_+Gf>l}r|OD___oPbsxAp8DaPL6RDFvx1~G%SEg#KA%T42amf5-=am3lgcm zQ-0k8wX;248q?_Q>*qFgo!_c8O~k?R!o!?dFP4A4U7wJnM$crh5~+0rH3cUt^fr!K z*j)gu#!YO9e&oK7uH8LuwJ#-R2GZ6MEgEmO&qZzx%7S%IsP*VBqPq&6VPiA&_-t)^w3QS8^rH&ttx!SX(?h=34M)?x>z%d*H&AY@S63U2O$+3 z1=js(SPkdfcS>mQLNdLZ!NZ5UuAtDs<4(}xL+)R+^W1>@cUuk566ptNe(CHlv?;%} za{>QIJtRokxw+L0LBYFbMtcmHuCA9Nzi*|A&Uz#;9@H6lpCJ%SPrrT?V!E+OA}_Qt zAuo$}o~P5LB&WzvGp=e+B!iFcBCgXKAd`g$_y$mGD8OeiYq4fwa6&QsA{)#df5n zP5i9THfF?SMYj9a`%NW)1nw-Q0Dm<3VP5Da18Tg6_%w9$zj37jk@%nTR!)(V<;*+i-%U1b3j%x z=>MvS*i|2w%!w|B1*}N7VlMye5etVc_Ldoe^BbrcgYa4E4v|Li1(3-ca$(Mdox1^k z`x@3LV|pvX<~-5#829Mb)Z;nZkiGKOOocLLpLn>FV|A6daL zKtl;PFRv}TIv&rbvz8Le#W6guFNQan-!AQP=s*MTJJ{vP*4}s><%!(n?v= zOT$HD6TrSnN(nL~l{F0pxz!P6m3J^d!;xaeD#?{fb49IA)wN2=$D^P<-|xevVr;)U zQW+ofEnl0&GM60j%kZ@KjPAs*r>Lk?kCH{OJBcL09b&tq<8@GFK_QO}S%jS+2@Pg{ z@oz^(HWYkz@kr+i-IchxZs{8Q@YqS0j#|=-_qf8u5c z-xX9yl3g{;pg{%9e_Xr|*pjfTt^T<`6_tUnQu;=mYR^p2rHV71l-6ZQ3}10vhl^TJ zK_(jn-Xn3~;sB&8Oc9i&-_>4jkk_2uMP{W7#5DCy<52x9G^G>DGLm0BRg)$_dQ9Zf z%l@tTX!x$@Fo&ESf}J&uS}AM7ByY-f%fwkG!mSof=)_PdGiWmafJ8Q_7DZaw@S#eh zlRvi=Wx0~PA8!vcX)&eCmn)Uk`Q-v_FEt}k23D@#>$2+Vt35yH+MYQvgyv)q!8szR!??I*1#M}BCZ6$PRNtiu=7 zmZlI_Wq!ctX6IBhDsy}7)DB6gy4DqBL-aotDyaHZ9#oTK(;|TePPL^DRGkRr-^YRi zA%CWTTxD1RN%rI^z~wdQ^Fc7DE{b)NFTEqD%_~`|ECQ6LU_OOKm%2;mPI&sIu@WOZ zAlIR!T1csuyl3LF(w2r2#| zP{JX@vYh^9+bz!Vb@a$FdSp!ehJh37aRT@MJ z{Udy>p@H9qU4to%si8FRi~O~budgp&7!;@C0gN(wNvctbg;V8E z$qdu|V~}&A(Inu0*_|L>tSxytx1!N>f?g7|1N%(%xx~2bdwbkY6Ugg;*2NcuKk&>| zN5;~7uU+8cckY>)vifae1D;xbT)7bs986c`4CLJZQ)B^fnQR(js?4#}?;kel0;s>R zt_@h=f>E^yYz%YnINa-zoJ=)i0o`56C}+D)KKO_jBuFm@Ew0roNrQm$nZenlU1{&dU=> zMo?73?DzQ9)D4WpL%7=m?Y~Qi8OyFI^_b-hEFhl3awZ6mfDFjMu9ySe9ZG*23UFMi zTry1nZ^sN8j)hHF>7j}|@3A+li3;T;uuS<1Bk;pnC&6KIX@)&V8&EdNy0Krs0Bl>Wvd|V8>G&Dlm!M3G`|IJEj-O~;NA-{$ zaP)oyA0xN%E*m<@0Sp@eGEWGDneXNkquhR|6)|$&tPirbK|9DeW?>zbMBT?+CdF7w z77s(Q_VG)h2PkAzV1~VFiZH8LKL%irtIGio7Dxc@pfUo?RlxU2mnDRcKLUxs%wHlK#8@l)UPAX~o%@b_LSB-@xhB0b9&HQA z0dguk+>}&zI)ISW`l($?G2P%%>C!XQif6KP3HcA5?S|t1Cuh%ad+x7IaeSVyUtMg) zPvTXRTX}t60w1r{Fgk8n$LHj-W?4*2in6T;$_;nGhxlr+W_Kae+v; zfiO)m02sL&RuTa>s*|-g&Z3q1PRHQnze{|lNZVULpUNzjB6)Rw`5jKU_&lGTrSB-| zorES3i!pm-nVw3~ZR;&oY1i19OTm)`{S5G75OIW`#^8;W#6(h+vH`6-R7Haj@?H7w zQV_X)tt~OgWxptBhMnf$cjc2OvFXX4?S1sedF{p7>2n|tRSM)(h0@r=#&WZR0h!6D z7A==v=x#H|ok3Frx>`Wk%$FjdizMo@88kF!)}%_!b9K(UkGdt*_QkE3vM~W^j>j+9sI+*rrcpBXVEm_N|xQ^Ll0UxU6y87(gNC;it1C za4-rL+9G$2!~`Kmp!r|9u*6~O z7mv;oKN3bzuHSU2L2W5C-%#$Qf_%Dxt72<<;0&a3yx|XWN(}MRWU)lPAe|MNH-1QI z98x%1ew(s;t_~F@q>1&%xt%4vl~{@grz(eqDlBXzmq68}x)pwO0cy)eD@KfKWooWN z_&q{0hyFF}=X8d0EDA-I2|texl9X1t6{tp(tx}5yrvh~x3C!=TK-8Furb*=uvIqFd zDSNqaI|(U&lSU(8M<*qJiYILXE6UAanQr6RfkXYN7>}gs=Ni*cLYCtJ&GN0~j0e;Ay7}BG*;(0o43@9{rhk z`kCkDAfO4p{Sr@wADztJsk1xJ>1cU7~}4k_3t=}m#Y-{Uhw*> zzSOwzpN4f3kDk%FtEl|ch8}a#rWH;(EaEBVAa8X3ROBuHtJHvr1lriN6BIBAMgWnZ z(j>0(90-*e(+%RH3eb#?p}OINY3Z$}bS**6EiF$7=$kB1uu705sd;J*z%P46A^y$Q zd%&1uVc^mP$CqOz7Tvj1QjA6)%}W=iij~z2IbP4Ku2ofF(L0k6ayz97R%ID_2B72V z7gjK(nzZ@T&H?s((9D6%ie3ajTu}F-AHwu&Q`<}$kNTUx7ELYRtg$TV2q$~r_=B5; zZ`wMzt;=wqt_Jjbt3ox+3fgxkP3?pP>!F0^fPtu{WUWVhvopkc~f}~lYFsrZx}z5Uhgi9+4op) z1$+l`F-bU|J0CL*GI3e@VdNwB_D|%%LQYksbM8jtF>q#0eAszDu7}2w z8uyLzA#{4cu@!N!aquVi2MT1^JX0)n$&@#s5?i?pcVD{x&h`l>RU)0>#qy$j1BKx9 zcD?6lOYDE0^gdAzUr1IVR!+OMO(FxW(3kt|Nz`03fL=SOt1p)j?1LEx)T66blIxf^ z$gmfo6ovpUwmDa#FFK1ThMQA@Th%WE9~lRhsij+8KA~jul*&VtP|M-(R;2a7|5QwE z`3JD;O9Z;xXb0kWUVK^B@fw*-^UTNj^4J2dUqJyVd{|6PFJIlj8oqd+x&l0?B+xv;0cXDf7jn zZGx2NLJuCm5ZKK3}Qo@LO(t$3t+9Kn=deR;P0~>%X@Sp>hHVz z@c>4&HN~+!ne+2moE)hpF2sx$;I8Z4oCS_G;svIw(3|2K$U1~rg05kM5jH{AmJDlnG2vaPp{x2+>(Q%vYNf`5mpBG_@VUj4+?IBl4K#H$S;vZY zfk}ZJK-!GR`)bS0vl_d2ij|hg%mqow^5j!3D#?cK3cxhxQt!Y|{>`fCj%Ks87|i97 zi~Fy*N-*jKXKHy#EBL`QRnRZBW>KL5nRbz5*f2?oZ&pFBoUHMjnVNn~N9rsU>#Udc zU5Odu4cSY!)n&fhrm%n*)?Wn~{((S;X^C1RPKO>yQm8iDzdE`8R7~`+BDbQzwBU$7 z_+Coyt$X=WsE%O>59P!)GNLX#iEBAdmDth%PI+lcxNV&|Y#vrYE`c6Y0^-Y9qmz(Ax1$w;;W@ke`0HkT-D7Mxg)GeSxx8nxlwYmD~(@TtiCzt{Px+a^$ z8`$z0Ru{ANTvN2wVS%^!2M^UYij&7=X zi-3T6R{CmS(L-&3nIkypn)l0ZHb50qZc+W@W>`ERxdc`K8oZgt0^|bcLj`3Av+%szYtz9jdA*AX*UJC-t@#; zg*TA>-OZl^!rpEK=)3(=)IA-kHHz+MI`!O0^-0Rrp@m-V-@h7cV zRVZy+jhz5180M0fIl>FvTibBaq*rmTz)AzQ`7PD@iQp9`$a0mp#^Ywn)?K4=$g~rY zt8RBIe|lb8qzgAFO;QFD^`V7Pef5epj8)SvWUw`<#^ui`F6tOVOv#(S&O+ZTltsT@b3itfeW z$qU;EE*PR@*!vrsJmJs`5ZECb3RxwVvUC(sQ6n*Ux9}mYguRfF%tZXx1NURasX_|= zva2;hP2>t0kh!tz>rFP#y%0lQp&D{7TE|)=$T%&lZ#HtNX8-9J+ds}oLpXRth#c59 z`;tpyq^nBncx69U-c1jCem0A;UTvRaM`oULPnFc|*N&g5AB>!QAM|4h*uh-^asBJk z{lQGFE31D3jq=$9b~1J{3kcoF5ou3P=b`%Oz2iSePxpM(>O1h=nVe>zbWPW4_CRu$ z|BdJ>+1q??+w(JmKx3ME5dT=BR{H$(SJ$%)t3B_+f;?ffj3Ea7BHg;!V#vynFUTz5 zDv4#;#hk-F0TAftbJqEEwpWZ49S5_@(?Jd@0^gA4C`_I;kWWc{+=_{DSlJ#e@S`LtW&2Y{7wJe5qIija#wJXL394g|Z5^%GqdkLzm_G(TpC zWVs^sI?|MTWk(VZ<`_U~l-*8O#s6*Mje>Zi3)5;Fe7=%?zeZh&1$c1ZZkINaS9pn` zYt?IQC;&46^s#*Hvl!D`>0y<2v#T+fh_F$GHc9B{+y270Q}=iym`&achHj=En2vba zzI-5R{ZJ*{>K?1j$h#g4BC_)ayHP@&f^u=$BWu8k9{+ zq+7!@;F2dEXdHYjT{q#hgm%3?`*lMit9C;(z*;rzb^3kitfKJXa#2s3gel8lCYQNT zkt4Xox)CaMzI3)HBGGuLjf#8|hGgoN@B*&-_ptWL4c+JkWe&A>4@W%D=H*|e%_B#~EA3F5rYcm7jroI$T^LjPyM>(tNKB$F z+AjX7aNM@s`B)eau=)d4E*L$d0XnPn4GT^-xp<*9*PT`}E}_wSJ0!Hjl}m>hEw-rA z5f*w-e9loJ$O=sC!ee?hpsnC#WVU%Cry!X}Ax=u5v6@J+=ytGWlX2UG5*q{rMk;Iz z5u)=y&@3HF2w7fIm}$&3`YGwFEzax?Ngivl8PNVU%L@%lwu|^JJt^9$BLphZz4m@9 z%I#sbTTaTuXi_9T*%GRctZLYyaX`fjrdGMJH~mrQaS^vh+NN<$&BV9Ex?W6yO=(<6 zf8YB9*Kdhm9O2em%zxp-`N>7D6%or;YKj4C8EMEeHmuGyPJwd*afzA#;1U0k74kO4 zuM#5x&Qmd#FfXaLa(FI)=Td8C2voIK%DS$fr9;^}^mt_h)c6F&7aw_{vk#9maRQ>x$EX>xydl1qOIqD>u%GJx3 zYn4lLlv}6GyVxcGQi_K8dlz8?^73nyK7Stv3=aNpLiV~(P{5#YT$jAl-)&-I^~z

*xPklv#|$`0EO=)@-J z@fO!fAo)vIs$|PSV&0Keyf%71(OAP*3`$3)$6R$Q`%7V7Z2efm>0&1fuEUBo zc`}L=)41I;sNjd>#Edn6{tO+_14D^Sn-9^J%sg0>9Hy2T2wm3~t)rv!u%|0ML8N@v z{OnS3L6LV6U(6E+agNRhAe^9BfW)Ije?hM~s2V>z-4VI7r=h+`Dg!Qiom2n_T4(;L zkDmD}1vDL-n*~NL$cb8e{Tr`nVq0laD>)Cs>#;=2J+XRjk&cWjFr#h<6JiC6q@&(k z{l_NJ+I2!1G~#e%bf=WxWdSw5IPpQ+|G+N4m-UN%IWh}%c8e!-c_<{Aj^2g zvZdnQ`I^CusxO0$fw3ZKYV{N z6o~$+;5LfC1}Fk(zMe2|Yqpuh`QywLiKn(xx}Uqc$A%a!b*@e_QuYVWrK+V5kcjI| zpkaz&l3kdsd4>*+*9o0U6QA-oXR7N6-EO3A?sMPCp4uZH#U=ZxKjT-LN2p(_xNV6m zYQuF5`K;9WZ^uzBOiu+FPY85P8w#Uyso<7`G!-u)A%7jxvq~u0-vxB`Xh^=GI!{T= z+SGzjiJ{)I4fD!zGh^KfY_uTfTiTNbe)u-0OYGJq@#)}K?^w&Buz*xhG~p9Ds(2tj zH~=m!*pyq0HNIkKfI%OW+}iV|9N_xAH)C0$S#P3m<)!QDzR5%8Dd@)R>dMQs2sCP| z&yKU$g(0o^9tP`@Wi{&g<*Fy}wiJN;vdfo4p@C3^Iv*!Td5RZhu=;rha7JTy zZl4$_F!lmflQwRXDdhOp@&o)nLA%dV+~P=@8Gz5ouo;`{jjreyEP#C>!4H3IY@v;e zVCN)VTVAX^28dkx9<#Qb=`1j*<7XjfyS<{r<&oarjVYz-_Vp3bg0HQT0BXw*V{AyP zs}x<^(AJbi?6b!v43ICp;vU_D2ING~7W8zBZ+qV##WakO3L$4Y7y+)VD0$c}e}Xxq za0##0eZKNy+v)QIB(4H64{RBh!sZm zp=dx-^<(vaC3YJ9-iN9-w-$*#(wZK&`{U$21c9@mB~1~g*wCBUePA|eb|$;Z062!h zgzEbAvjhcgmMU|QP;}~JnpLDOM6Nx#N=ujFB0KgN>GEu?;FxnbTTrI-1O`qnFV2{q zBuKc5RFTg7+%+UA_9>Exfb9wMq3OFxgzDPBxNyM(C)GY@7LM}$%_ar;LQ7`T#?j>n z)vbczV1iaXnSG)K`A!ew@1MZ`L|KF_0<4;Q52PLIL<9wxs0q*_c%R}@S5Blho-n$I zZRRyZ!{c0A$aD|iGV)CuMhXhiAnYJ-Q=d7LR`^@0k&K?39R)NU7~rW+)n-SBd~I<; zl<$!szjx+o)=J?j4_7ohy3Z5p^n0x9Hi>n^5?R#-n^v5vRN0#ID66cGDbkC0wDBuO zV_Ivhu0bPt0Y*Q9o20R$v71t+B21pQ8j&%xVJiAt#8xE6&n9d^ur!Jd;kv8hq%oi$ zsr*<6>3Z)K=9zi6hV@etYIZ!OYACg%^D>YcH+_taNc_!SzBMznG(7S$ zHVB4@4n;Z--_yYte*trnE_8Xt?$39D1Vu1Z*KD?;^0i(RualrUj~@$(q)j8&O*qzF zJjVnWgR{Sc1!Um6wBUf%-45*Ok%MA-jpMWLkaWelYwiYVz-X(oKi_?1AuLp}GH=+Y z4gC5zRJ=H4Yw1T6SgT!QpRyMtIS%%1dmjZw*yX%%eWtv_^cuq8h#%&>~J;^ z4&h$Yg`g$@kbIJ@Ucj@NInw;YH*og;+|we#@$i!!v^&xPP@Ynwc0 zyjJirTh$~Me|J-4@JOOX{&8pvPSUHRG6P-MC)!Bzz!&_pbF0nFUQO!yS5{csA3q~y z@Ol$q;vV*GSF~*nPoPMxwz)>Bgrq;8nfmdOLbbZXC+`|4 z3aT@;1KQt|=Z(O*bq{SUaW(^@=q;X z>6nYWT`!Xe1ne8D1-egxoDdw|N~9byUH>>ialV?I6ml3xb0S2e57^nCdM{<-H@*Ih zv-aT*_#uS`$IzA@S+m4Gj{uerocGso$eh~t%`bf+Z`WCabQXNQWS zG$7AiuG^I7$40X~k4s}oxLm*(L*}>clF}V}xV<^cc=)BmjeK@|cNIUq@Ve*wZ3Y*9 zdY$!JvD1{eg!$IzrSD~Cxzq#i+B}-RW^&YLxixmSUB)t;G;J96EQcV+r9Lm(2g&TXT_bXvb1Y7c;QUq;>(2J$~eLccds zOKyKbCn|-SH`6}8eoQlE+@(6AI!Cc1tr`bbFAu6ZL%O58@2QX#5`(`i#+e2B40R%O z8mi3#y)Im}+rwp^A>cG+&FH#sDd=6&P4q&)Tf-EGh|?xwP2G8CbrhQb-!ijoB5Y-r zT{zA^V&_}%*V7Bw7LDDW=6TCX3J?S5x>-=JBiTrlb41}y1+((XrqDTTkT(k`R>-9H za__FDWf~f~4=ThWA2rM>$}n+us(ru+{Q@RL#Mu>o1`8Q_4B;ODg9V#FhLlo*t^>h| zR9b@Yh>Z2G%>&GfF?iTXo(f~fJGEQuAt?@6^VY;Y*W*i?Tya0?&nS9iLBJOprr1?h zTbvDgbnIIS3x=?z^oSU8I@)*w2kWkKfg)@atT8Psg9l^Vp&y~UQ}2 zeL&))g-cq?cny!W7&@HEZJ+mYE)ihezl#bHP~5El0R3Co3b2>Fg7T$z+!2g0lS!v? zm<056zzyJUnypg6FC_t6ACgTM9uT?B?6a?W=|};HI}m?~nscHv#^~yuNRX{tS?_@v zKXlJ|4x?iMXGow6=b%+%rE#Sn!Ec%uwNL%cIhNiW8Z|-B4#pLIXsT)G$^%K=>6wUQ zNuW}8!TDGZ24}d8);BpJlbPH|Nl7<_lDePdcUFC?RWngo;2~=tUnvNQYKG2h4*SVt zNx&eX=8juD07xLIgv8Eg91zPurGGs{TR-6;QH30E?io)3rm=90Q~%SRFkIUq!6K*5QbA zy!pg?nuwD%-VrhGsM}2m@H;Qo0RFb_=>QwNF3-<6I27P)g(}a-*|DH+e4><*+hUBi z&hIUh$7{6jR6aZaAR?}J7=ek5c-dQ-`0vT0Fa>1Axv?O+419|Dynxlm8FGB?F@v&l zU33AsCbCo9WBMD%Zs)n!iQDbx#s8UjC-Xt)W1l<@zibKlqrR*Aebs*BxGk36LM6 zyUniWb~lHct-Z7%&HDecUc;{WB3bd^r$Ef9a6iup1S@>O2$4^DZtXail#I6beX!4J zFZ8SP?j^D^6}lJch+K5t)t?puBu2A1FFi$ND?Xe@83u4$0J?aNt-fD6sbF-cwxj7p zyg3G|nuA*l0X>Yg9FwPzHzYhoul#6G~fGW@Mhw z_^LtS;XNOZoIYq!aucz=%wsn+Vb5!^+8Z0#6BWd(-P0zW?z*_FEylie>1z~qHSi?@a3kg$m`wf6+Lzq;n3(jp~o+I_?s z5n@lf2KyQ$_W5a2@qL;zG43TU^kHc=S!X3vlReGB=HDVhVO)&F@LHQvrCW!p8!-`` zQ)Z2}`r$6^+{^VC48iQ%cPr01YNjOqTsfSPsP&t+l^gi*r{Exjuea!L>R$?T;$dx! zW|9VagKrT($79~Vg$@gx!na^dVW5QBUgzNLjC-4XSvEwxR+qP}nwr$(CZQHhO+sTfd9qoC) zIh#3{>4W|Sy;fJ>U3Ha}*z`@SOGlHIxFo+BOXhFvBvZSEo*jhK@xw8X7|4M;1!}^nZK%+pPOigom##}%LNn>lb z&@rC9%jo?iuR>3<+wiw-U!&UqzUhr@>xPI#grl3Zj{*aC;Wx0jTdxOKC;_)JJN$aZ z{XLOcCoW{e+IEPzr>)k`33FXlhl_n=?w0$`W{bq^&_dl&58t2BKftAPfdV>r2<89$ zLRT2(`+DI+3sNZZ5EMS$E~LWcb9g8$f|TE z!6zF39rc0BCnso#_Ci{Kv+`=mq?9MbM=%tB<02S%j!SU)EM09}i0$e9gQP(y2{)9w8fzd07^h21( zCV!Nnhpu}4OwQgq#?H%$fHek9_7H^e~q(7VEouDXtsy@%p-q0ZJ& znwIv3EHZ#Wd4C9`?%w@KIsi8K{A`B`%9s$0R#o;}R5s;C= z$7EO_C#i^{jxn0Bv)5q6hmpra-|1MY@)LU9dQAq%=-LGNzmpQK&A3-TGjrTG96} z7oj85l(Uj4e-It`hbOV;&@|%5mi9G9{SyxYzcB7Bs3;6@==cWft9{0*Q3(!2y{>%N z6s`65tpY#6L$w}O#?CD{IUe|#rbqr4b}JQc~qu-aT!lMU4gQ$F&*GZw~Bf{+=%N2Kj~ z$5tmGi}6ix)t4PvU;Ct+YVpieBM36-Y}T55G&$ZP5B- z)`3unRpA!_1r|Nj*A1Lv8HUc#xkd?nqaZO*V`}g)2)+jM}}p5Lc+2UMPBWSCDZ9|96o_aON+di`NhD%uRO>IBQM<1 zqaEV-gG^-8fU#^u#cPZbx5V5*QBaCeuKYor&%(X^-u1y0J)A%v-&j@A6q+0vE}p&3 z;cc_&f`0un!8&)$nF(V)Zb$5hJd2^CAZ$D5LjvIf+Xm$zt87bQUyli!)D`@hc)H~C zppA450tIJ^*WA~urr*vb{69)pwl>ZP(oy1&;b(YP!cWtc@r(b6lk-4|C7m&4K8~*X zWjNWHh`bP)HLDWng6OP=PgmVx7X*=Iw5$`9I5^{{G!BF(lPFqWmzn1D09u;^82A4! zrlSzecp2~J82g0=9n3wDf(XG062;VKPsUb5-$fJQ`Slid?Eo_N*PDc9r29bcBPMyS zTG~6oX#19jn+TV%TXmWzVT5s@L-|O6B5s<c6*v%()_=6i{|_U@%-zi1^?#hneVG^WtBi<& z|41I;(Z7L8%ii~W?)9_{j?LiW@pLuQpRjuo8OCE#*tf7$!akfTa(}!&Wpj7BTrRT2 z#k#y!&gC9*1Nbs&nAq;}4$Ahaa4L$O+?b_j%j)8wi5tL~p6ij2G&iUjO4=JlHNz{j z^+GCPq@pfE!FM~yZ&ohyG9!7bULDS zItX-m)Bkz@NvuWi`HsZTb(cd?0o8aUXG}W zbOvc?d;m%o{H|})+>WwT$wc7%fCi84+Y1|Xb-j@_ zGleuJWOu;MACr1~eC9N|h)d>=MeUWN77FaM-tD=m(Tg@Eicf#cCtU`QoR1?V%F_g&kHPwuH2Fk~LnB!Mm85HPJN*>Xn)|Ao-YOJ< zrId0v%BZ9hMbMWMObV(7G~vwLjm|GtOE0*Rl?J3`-<&4IMqEJGhOXpsX>u}WQ93Uj zX+`~4GQo0|k|!@ZXgxl%{ug|n;fM&jW>M%WLlc-TGfe1mBv*!sk_G3Y17>eJo5)iK zEOqwJ0vcmb@sP8qi5a?mu8l`pN(A`BuHN$aBJtINM9A;MUjBR zqU1~JM?Y?hEOvyta&J@d-bm1r@|bFB&DGJ2^fLK5L|Ksw9Z~^PvL(0BGGSN^&s#cP z*fhYQd8{kcD0geIZR^m;zPDgue+T_bFehr$5uQ8(4#h~N1$dg=uVWab5`&}P-^*2@ zGmdw$NJhxOTIYfU+-j?uku|>3EcGPcsw_jUy*y)!4W?kChx-@rfgfQ2UKcJ*eku^g ziQfxB0dry17!#p(XB^uOb7x2CNAza9?K&e3#QA_6Pl7+MZ4r@DEt}u)1Ae9|J=200 zS@p)&ufd6Q9lF*cu9@5=?7Y!eabJjNRkHftMP@M2sx@uTR?86X$TCbX=9|!nGb@Ia z=Y$XQuo^l<{a-J$<^*-*AdgkI<7qKNA54eCh@f3gBuZk7qxFRAPuli`%h64H=RU@i zxZQ8{UbqfIb-uZwh`K|+hf4s!gw5M8s8WarTv_A!o=VmaV3T3fI6N*%r+Ir&d#!gh zO;Hx)A^XoibN-NlZSFl9u5z>%^L7O4Q;+F7DYtXQPspupKpmM93}FE929XxW-A?k$ zBL+vpJ-y$FHK}@ejBtJYkF=@7YLa9QI#!`qS8z^*iyTbHsfe&`Z>ZoP-aCANroP5( zgQAB0ElrX^H3nxzC?1VKF_%DZOl|c>phX{5i4w z6){(gs|2KA6urv~k82_cE;#o>QY;Y$w+hNRi6ojZgOizL(k#B0coHps7Rot|B%5%9 z^Xb2h>nWU&gVPw&IfVpH$lhrb`IKD(SLn{Mlx$KjzL#v0FWxhF_d=3z5+q(UnDcl;j@jDV0PfnD=B7BKYQL5lNu*%hvq`1kP<3_2zA}S}CuSidSDFPf_j~Q(Va;<=TIHmo z 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

2HhPT%Zy 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�HNnpz1tWl%>lj#1gd6x4h;)J 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
#u$Lwxe17nefv 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ɻ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%0DT+dDgFZfv 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®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

yUgW2L164wo2|`5{TBL;Xd{rgrwc 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µW15G+n5>wHK{rzB2`5qDF} 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�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

)iY|*m! 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

T)V?9XK(xW!?sWo+*GsqW=G2jOhSX6% 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

H2slJ5Fb# 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

Z%_#jekWT#B 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 J_cq60{|C%4J#hd4 literal 0 HcmV?d00001 diff --git a/TombIDE/TombIDE.Shared/TombIDE.Shared.csproj b/TombIDE/TombIDE.Shared/TombIDE.Shared.csproj index ba20308e29..d9a9a1ffe7 100644 --- a/TombIDE/TombIDE.Shared/TombIDE.Shared.csproj +++ b/TombIDE/TombIDE.Shared/TombIDE.Shared.csproj @@ -1,257 +1,136 @@  + - net6.0-windows - 12 - Library false true - true - Debug;Release - x64;x86 - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 + + + $(MSBuildProjectDirectory)\TIDE\LuaLS.zip + + + + + + + + GlobalPaths.cs + + PreserveNewest + PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - + - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + + PreserveNewest - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest + + + + + + Never - - PreserveNewest + + + Never - \ No newline at end of file + + + + + + $(TargetDir)TIDE\LuaLS + $(IntermediateOutputPath)LuaLS + $(LuaLanguageServerOutputDirectory)\.extracted + + + + + + + + + + <_LuaLanguageServerArchive Include="$(LuaLanguageServerArchivePath)" /> + + + + + + + <_LuaLanguageServerRepresentativeStagingOutputPath Include="@(LuaLanguageServerRepresentativeOutput -> '$(LuaLanguageServerStagingDirectory)\%(Identity)')" /> + <_LuaLanguageServerRepresentativeOutputPath Include="@(LuaLanguageServerRepresentativeOutput -> '$(LuaLanguageServerOutputDirectory)\%(Identity)')" /> + <_LuaLanguageServerStagingFile Include="$(LuaLanguageServerStagingDirectory)\**\*" /> + <_LuaLanguageServerExpectedOutputFile Include="@(_LuaLanguageServerStagingFile -> '$(LuaLanguageServerOutputDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" /> + <_LuaLanguageServerExistingOutputFile Include="$(LuaLanguageServerOutputDirectory)\**\*" /> + <_LuaLanguageServerObsoleteOutputFile Include="@(_LuaLanguageServerExistingOutputFile)" /> + <_LuaLanguageServerObsoleteOutputFile Remove="@(_LuaLanguageServerExpectedOutputFile)" /> + + + + + + + + + + + + + + + + + + + + <_LuaLanguageServerOutputFiles Include="$(LuaLanguageServerOutputDirectory)\**\*" /> + + + + + + diff --git a/TombIDE/TombIDE/TombIDE.csproj b/TombIDE/TombIDE/TombIDE.csproj index 8b5c13a49b..17ed345059 100644 --- a/TombIDE/TombIDE/TombIDE.csproj +++ b/TombIDE/TombIDE/TombIDE.csproj @@ -7,28 +7,10 @@ - net6.0-windows WinExe false true true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 TIDE.ico diff --git a/TombLib/TombLib.Forms/TombLib.Forms.csproj b/TombLib/TombLib.Forms/TombLib.Forms.csproj index 763fe52055..bdeddac36f 100644 --- a/TombLib/TombLib.Forms/TombLib.Forms.csproj +++ b/TombLib/TombLib.Forms/TombLib.Forms.csproj @@ -7,30 +7,10 @@ - net6.0-windows - 12 - Library TombLib false true true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.Rendering/TombLib.Rendering.csproj b/TombLib/TombLib.Rendering/TombLib.Rendering.csproj index 1e19851327..9873a30f2e 100644 --- a/TombLib/TombLib.Rendering/TombLib.Rendering.csproj +++ b/TombLib/TombLib.Rendering/TombLib.Rendering.csproj @@ -1,28 +1,9 @@  - net6.0-windows - Library TombLib false true - true - Debug;Release true - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj b/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj index a44aebf4ac..268c4df7e0 100644 --- a/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj +++ b/TombLib/TombLib.Scripting.ClassicScript/TombLib.Scripting.ClassicScript.csproj @@ -1,27 +1,8 @@  - net6.0-windows - Library false true true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj b/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj index 08d3d8c2d4..bb0c052139 100644 --- a/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj +++ b/TombLib/TombLib.Scripting.GameFlowScript/TombLib.Scripting.GameFlowScript.csproj @@ -1,26 +1,7 @@  - net6.0-windows - Library false true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index f747d18305..95aea4184a 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -1,29 +1,9 @@  - net6.0-windows - 12 - Library false enable true true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj b/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj index 2fc068c975..435a2bca6c 100644 --- a/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj +++ b/TombLib/TombLib.Scripting.Tomb1Main/TombLib.Scripting.Tomb1Main.csproj @@ -1,26 +1,7 @@  - net6.0-windows - Library false true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj index 6e08d2b09b..a38e061219 100644 --- a/TombLib/TombLib.Scripting/TombLib.Scripting.csproj +++ b/TombLib/TombLib.Scripting/TombLib.Scripting.csproj @@ -1,27 +1,8 @@  - net6.0-windows - Library false true true - true - Debug;Release - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.Test/TombLib.Test.csproj b/TombLib/TombLib.Test/TombLib.Test.csproj index f96c3a483c..efdaf2ee7f 100644 --- a/TombLib/TombLib.Test/TombLib.Test.csproj +++ b/TombLib/TombLib.Test/TombLib.Test.csproj @@ -1,25 +1,11 @@ - net6.0-windows - 12 enable enable false true - x64;x86 - - - - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib.WPF/TombLib.WPF.csproj b/TombLib/TombLib.WPF/TombLib.WPF.csproj index 4d40511969..d461ae8fa7 100644 --- a/TombLib/TombLib.WPF/TombLib.WPF.csproj +++ b/TombLib/TombLib.WPF/TombLib.WPF.csproj @@ -1,22 +1,9 @@  - net6.0-windows enable true true - x64;x86 - - - - none - true - - - x64 - - - x86 diff --git a/TombLib/TombLib/TombLib.csproj b/TombLib/TombLib/TombLib.csproj index 599b3f3c9c..012f41a9be 100644 --- a/TombLib/TombLib/TombLib.csproj +++ b/TombLib/TombLib/TombLib.csproj @@ -1,27 +1,8 @@  - net6.0-windows - Library false true - true - Debug;Release true - x64;x86 - - - ..\..\Build ($(Platform))\ - - - ..\..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 diff --git a/WadTool/WadTool.csproj b/WadTool/WadTool.csproj index aa3f17900c..acba098513 100644 --- a/WadTool/WadTool.csproj +++ b/WadTool/WadTool.csproj @@ -1,26 +1,8 @@  - net6.0-windows WinExe false true - true - Debug;Release - x64;x86 - - - ..\Build ($(Platform))\ - - - ..\BuildRelease ($(Platform))\ - none - true - - - x64 - - - x86 WT.ico From f8b256b9fbd65e832726c15a8bc41cdedd746b7a Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Tue, 21 Apr 2026 23:23:54 +0100 Subject: [PATCH 20/34] Refactors Part 1 --- .../LuaStudio.Intellisense.cs | 179 +-- .../LuaIntellisenseDocumentManager.cs | 277 ++-- .../LuaLanguageServerClient.cs | 1113 +++++++++-------- .../LuaLanguageServerDiagnosticsParser.cs | 445 ++++--- .../LuaLanguageServerIntellisenseProvider.cs | 676 +++++----- .../LuaLanguageServerLocator.cs | 29 +- .../LuaLanguageServerPathHelper.cs | 153 ++- .../LuaLanguageServerResponseParser.cs | 916 +++++++------- .../LuaLanguageServerSemanticTokensParser.cs | 148 +-- .../LuaLanguageServerSettingsFactory.cs | 89 +- .../Properties/InternalsVisibleTo.cs | 2 +- .../Utils/LuaDocumentLineParserStateCache.cs | 2 +- 12 files changed, 2063 insertions(+), 1966 deletions(-) diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 40cc31c9f9..e841b40774 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -1,127 +1,128 @@ +#nullable enable + +using ICSharpCode.AvalonEdit.Document; using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; -using ICSharpCode.AvalonEdit.Document; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombIDE.Shared; using TombIDE.Shared.SharedClasses; -using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombLib.Scripting.Bases; using TombLib.Scripting.Lua; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio +namespace TombIDE.ScriptingStudio; + +public sealed partial class LuaStudio { - public sealed partial class LuaStudio + private readonly ILuaIntellisenseProvider _intellisenseProvider; + + private void HookLuaIntellisense() { - private readonly ILuaIntellisenseProvider _intellisenseProvider; + EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; + EditorTabControl.FileOpened += EditorTabControl_LuaFileOpened; - private void HookLuaIntellisense() - { - EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; - EditorTabControl.FileOpened += EditorTabControl_LuaFileOpened; + _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; + _intellisenseProvider.DiagnosticsUpdated += IntellisenseProvider_DiagnosticsUpdated; + _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; + _intellisenseProvider.SemanticTokensUpdated += IntellisenseProvider_SemanticTokensUpdated; + } - _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; - _intellisenseProvider.DiagnosticsUpdated += IntellisenseProvider_DiagnosticsUpdated; - _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; - _intellisenseProvider.SemanticTokensUpdated += IntellisenseProvider_SemanticTokensUpdated; - } + private void DisposeLuaIntellisense() + { + EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; + _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; + _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; + _intellisenseProvider.Dispose(); + } - private void DisposeLuaIntellisense() - { - EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; - _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; - _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; - _intellisenseProvider.Dispose(); - } + private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() + { + TENApiService.InjectTENApi(IDE.Instance.Project, IDE.Instance.Project.GetCurrentEngineVersion()); - private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() - { - TENApiService.InjectTENApi(IDE.Instance.Project, IDE.Instance.Project.GetCurrentEngineVersion()); + string? executablePath = LuaLanguageServerLocator.ResolveExecutablePath(); + return new LuaLanguageServerIntellisenseProvider(ScriptRootDirectoryPath, executablePath); + } - string executablePath = LuaLanguageServerLocator.ResolveExecutablePath(); - return new LuaLanguageServerIntellisenseProvider(ScriptRootDirectoryPath, executablePath); - } + private void EditorTabControl_LuaFileOpened(object? sender, EventArgs e) + { + if (sender is not LuaEditor editor) + return; + + editor.IntellisenseProvider = _intellisenseProvider; + editor.DefinitionNavigationRequested -= NavigateToDefinition; + editor.DefinitionNavigationRequested += NavigateToDefinition; + editor.TextChangedDelayed -= LuaEditor_TextChangedDelayed; + editor.TextChangedDelayed += LuaEditor_TextChangedDelayed; + + _intellisenseProvider.OpenDocument(editor.FilePath, editor.Text); + ApplyDiagnosticsToEditor(editor, _intellisenseProvider.GetDiagnostics(editor.FilePath)); + ApplySemanticTokensToEditor(editor, _intellisenseProvider.GetSemanticTokens(editor.FilePath)); + } - private void EditorTabControl_LuaFileOpened(object sender, EventArgs e) + private void LuaEditor_TextChangedDelayed(object? sender, EventArgs e) + { + if (sender is LuaEditor editor) + _intellisenseProvider.UpdateDocument(editor.FilePath, editor.Text); + } + + private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyList diagnostics) + { + if (InvokeRequired) { - if (sender is not LuaEditor editor) - return; - - editor.IntellisenseProvider = _intellisenseProvider; - editor.DefinitionNavigationRequested -= NavigateToDefinition; - editor.DefinitionNavigationRequested += NavigateToDefinition; - editor.TextChangedDelayed -= LuaEditor_TextChangedDelayed; - editor.TextChangedDelayed += LuaEditor_TextChangedDelayed; - - _intellisenseProvider.OpenDocument(editor.FilePath, editor.Text); - ApplyDiagnosticsToEditor(editor, _intellisenseProvider.GetDiagnostics(editor.FilePath)); - ApplySemanticTokensToEditor(editor, _intellisenseProvider.GetSemanticTokens(editor.FilePath)); + BeginInvoke(new Action>(IntellisenseProvider_DiagnosticsUpdated), filePath, diagnostics); + return; } - private void LuaEditor_TextChangedDelayed(object sender, EventArgs e) + foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) { - if (sender is LuaEditor editor) - _intellisenseProvider.UpdateDocument(editor.FilePath, editor.Text); + if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) + ApplyDiagnosticsToEditor(editor, diagnostics); } + } - private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyList diagnostics) + private void IntellisenseProvider_SemanticTokensUpdated(string filePath, IReadOnlyList semanticTokens) + { + if (InvokeRequired) { - if (InvokeRequired) - { - BeginInvoke(new Action>(IntellisenseProvider_DiagnosticsUpdated), filePath, diagnostics); - return; - } - - foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) - { - if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) - ApplyDiagnosticsToEditor(editor, diagnostics); - } + BeginInvoke(new Action>(IntellisenseProvider_SemanticTokensUpdated), filePath, semanticTokens); + return; } - private void IntellisenseProvider_SemanticTokensUpdated(string filePath, IReadOnlyList semanticTokens) + foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) { - if (InvokeRequired) - { - BeginInvoke(new Action>(IntellisenseProvider_SemanticTokensUpdated), filePath, semanticTokens); - return; - } - - foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) - { - if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) - ApplySemanticTokensToEditor(editor, semanticTokens); - } + if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) + ApplySemanticTokensToEditor(editor, semanticTokens); } + } - private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) - { - if (definitionLocation is null || string.IsNullOrWhiteSpace(definitionLocation.FilePath) || !File.Exists(definitionLocation.FilePath)) - return; + private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) + { + if (definitionLocation is null || string.IsNullOrWhiteSpace(definitionLocation.FilePath) || !File.Exists(definitionLocation.FilePath)) + return; - EditorTabControl.OpenFile(definitionLocation.FilePath); + EditorTabControl.OpenFile(definitionLocation.FilePath); - if (CurrentEditor is not TextEditorBase editor || editor.Document.LineCount == 0) - return; + if (CurrentEditor is not TextEditorBase editor || editor.Document.LineCount == 0) + return; - int lineNumber = Math.Max(1, Math.Min(definitionLocation.LineNumber, editor.Document.LineCount)); - DocumentLine documentLine = editor.Document.GetLineByNumber(lineNumber); - int columnNumber = Math.Max(1, Math.Min(definitionLocation.ColumnNumber, documentLine.Length + 1)); - int offset = documentLine.Offset + columnNumber - 1; + int lineNumber = Math.Max(1, Math.Min(definitionLocation.LineNumber, editor.Document.LineCount)); + DocumentLine documentLine = editor.Document.GetLineByNumber(lineNumber); + int columnNumber = Math.Max(1, Math.Min(definitionLocation.ColumnNumber, documentLine.Length + 1)); + int offset = documentLine.Offset + columnNumber - 1; - editor.Focus(); - editor.CaretOffset = offset; - editor.Select(offset, 0); - editor.ScrollToLine(lineNumber); - } + editor.Focus(); + editor.CaretOffset = offset; + editor.Select(offset, 0); + editor.ScrollToLine(lineNumber); + } - private static void ApplyDiagnosticsToEditor(LuaEditor editor, IReadOnlyList diagnostics) - => editor.SetDiagnostics(editor.LiveErrorUnderlining ? diagnostics : Array.Empty()); + private static void ApplyDiagnosticsToEditor(LuaEditor editor, IReadOnlyList diagnostics) + => editor.SetDiagnostics(editor.LiveErrorUnderlining ? diagnostics : []); - private static void ApplySemanticTokensToEditor(LuaEditor editor, IReadOnlyList semanticTokens) - => editor.SetSemanticTokens(semanticTokens ?? Array.Empty()); - } -} \ No newline at end of file + private static void ApplySemanticTokensToEditor(LuaEditor editor, IReadOnlyList semanticTokens) + => editor.SetSemanticTokens(semanticTokens ?? []); +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs index 2fcb82e0f3..8e2bb6f406 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs @@ -1,193 +1,188 @@ +#nullable enable + using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed class LuaIntellisenseDocumentManager { - internal sealed class LuaIntellisenseDocumentManager + private sealed class DocumentState { - private sealed class DocumentState - { - public string FilePath { get; init; } - public string Uri { get; init; } - public string Content { get; set; } - public int Version { get; set; } - public bool IsOpen { get; set; } - } + public required string FilePath { get; init; } + public required string Uri { get; init; } + public string? Content { get; set; } + public int Version { get; set; } + public bool IsOpen { get; set; } + } + + private readonly object _syncRoot = new(); - private readonly object _syncRoot = new(); - private readonly Dictionary _documents = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary> _diagnosticsByFilePath = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _diagnosticsVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary> _semanticTokensByFilePath = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _semanticTokensVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _documents = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _diagnosticsByFilePath = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _diagnosticsVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary> _semanticTokensByFilePath = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary _semanticTokensVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); - public IReadOnlyList GetDiagnostics(string filePath) + public IReadOnlyList GetDiagnostics(string filePath) + { + lock (_syncRoot) { - lock (_syncRoot) - return _diagnosticsByFilePath.TryGetValue(filePath, out IReadOnlyList diagnostics) - ? diagnostics - : Array.Empty(); + return _diagnosticsByFilePath.TryGetValue(filePath, out IReadOnlyList? diagnostics) + ? diagnostics + : []; } + } - public IReadOnlyList GetSemanticTokens(string filePath) + public IReadOnlyList GetSemanticTokens(string filePath) + { + lock (_syncRoot) { - lock (_syncRoot) - return _semanticTokensByFilePath.TryGetValue(filePath, out IReadOnlyList semanticTokens) - ? semanticTokens - : Array.Empty(); + return _semanticTokensByFilePath.TryGetValue(filePath, out IReadOnlyList? semanticTokens) + ? semanticTokens + : []; } + } - public LuaDocumentSynchronizationRequest Synchronize(string filePath, string content) - { - string safeContent = content ?? string.Empty; + public LuaDocumentSynchronizationRequest? Synchronize(string filePath, string content) + { + string safeContent = content ?? string.Empty; - lock (_syncRoot) + lock (_syncRoot) + { + if (!_documents.TryGetValue(filePath, out DocumentState? state)) { - if (!_documents.TryGetValue(filePath, out DocumentState state)) - { - state = new DocumentState - { - FilePath = filePath, - Uri = LuaLanguageServerPathHelper.CreateFileUri(filePath), - Content = safeContent, - Version = 1, - IsOpen = true - }; - - _documents[filePath] = state; - return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, CreateSnapshot(state)); - } - - if (!state.IsOpen) + state = new DocumentState { - state.Content = safeContent; - state.Version++; - state.IsOpen = true; - return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, CreateSnapshot(state)); - } + FilePath = filePath, + Uri = LuaLanguageServerPathHelper.CreateFileUri(filePath), + Content = safeContent, + Version = 1, + IsOpen = true + }; + + _documents[filePath] = state; + return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, CreateSnapshot(state)); + } - if (!string.Equals(state.Content, safeContent, StringComparison.Ordinal)) - { - state.Content = safeContent; - state.Version++; - return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Change, CreateSnapshot(state)); - } + if (!state.IsOpen) + { + state.Content = safeContent; + state.Version++; + state.IsOpen = true; + return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, CreateSnapshot(state)); + } - return null; + if (!string.Equals(state.Content, safeContent, StringComparison.Ordinal)) + { + state.Content = safeContent; + state.Version++; + return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Change, CreateSnapshot(state)); } + + return null; } + } - public bool TryClose(string filePath, out LuaDocumentSnapshot document) + public bool TryClose(string filePath, [NotNullWhen(true)] out LuaDocumentSnapshot? document) + { + lock (_syncRoot) { - lock (_syncRoot) + if (!_documents.TryGetValue(filePath, out DocumentState? state) || !state.IsOpen) { - if (!_documents.TryGetValue(filePath, out DocumentState state) || !state.IsOpen) - { - document = null; - return false; - } - - state.IsOpen = false; - document = CreateSnapshot(state); - return true; + document = null; + return false; } + + state.IsOpen = false; + document = CreateSnapshot(state); + return true; } + } - public void PrepareForRestart() + public void PrepareForRestart() + { + lock (_syncRoot) { - lock (_syncRoot) + foreach (DocumentState state in _documents.Values) { - foreach (DocumentState state in _documents.Values) - { - if (state.IsOpen) - state.IsOpen = false; - } + if (state.IsOpen) + state.IsOpen = false; } } + } - public LuaDocumentSnapshot GetDocumentSnapshot(string filePath) + public LuaDocumentSnapshot? GetDocumentSnapshot(string filePath) + { + lock (_syncRoot) { - lock (_syncRoot) - return _documents.TryGetValue(filePath, out DocumentState state) - ? CreateSnapshot(state) - : null; + return _documents.TryGetValue(filePath, out DocumentState? state) + ? CreateSnapshot(state) + : null; } + } - public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) + public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) + { + lock (_syncRoot) { - lock (_syncRoot) + if (publishedDiagnostics.Version > 0 + && _diagnosticsVersionByFilePath.TryGetValue(publishedDiagnostics.FilePath, out int currentVersion) + && publishedDiagnostics.Version < currentVersion) { - if (publishedDiagnostics.Version > 0 - && _diagnosticsVersionByFilePath.TryGetValue(publishedDiagnostics.FilePath, out int currentVersion) - && publishedDiagnostics.Version < currentVersion) - { - return false; - } + return false; + } - if (publishedDiagnostics.Version > 0) - _diagnosticsVersionByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Version; + if (publishedDiagnostics.Version > 0) + _diagnosticsVersionByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Version; - _diagnosticsByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Diagnostics; - return true; - } + _diagnosticsByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Diagnostics; + return true; } + } - public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList semanticTokens) + public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList semanticTokens) + { + lock (_syncRoot) { - lock (_syncRoot) + if (version > 0 + && _semanticTokensVersionByFilePath.TryGetValue(filePath, out int currentVersion) + && version < currentVersion) { - if (version > 0 - && _semanticTokensVersionByFilePath.TryGetValue(filePath, out int currentVersion) - && version < currentVersion) - { - return false; - } - - if (version > 0) - _semanticTokensVersionByFilePath[filePath] = version; - - _semanticTokensByFilePath[filePath] = semanticTokens ?? Array.Empty(); - return true; + return false; } - } - private static LuaDocumentSnapshot CreateSnapshot(DocumentState state) - => new LuaDocumentSnapshot(state.FilePath, state.Uri, state.Content, state.Version); - } + if (version > 0) + _semanticTokensVersionByFilePath[filePath] = version; - internal enum LuaDocumentSynchronizationKind - { - Open, - Change + _semanticTokensByFilePath[filePath] = semanticTokens ?? []; + return true; + } } - internal sealed class LuaDocumentSynchronizationRequest - { - public LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind kind, LuaDocumentSnapshot document) - { - Kind = kind; - Document = document ?? throw new ArgumentNullException(nameof(document)); - } + private static LuaDocumentSnapshot CreateSnapshot(DocumentState state) + => new(state.FilePath, state.Uri, state.Content, state.Version); +} - public LuaDocumentSynchronizationKind Kind { get; } - public LuaDocumentSnapshot Document { get; } - } +internal enum LuaDocumentSynchronizationKind +{ + Open, + Change +} - internal sealed class LuaDocumentSnapshot - { - public LuaDocumentSnapshot(string filePath, string uri, string content, int version) - { - FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); - Uri = uri ?? throw new ArgumentNullException(nameof(uri)); - Content = content ?? string.Empty; - Version = version; - } +internal sealed class LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind kind, LuaDocumentSnapshot document) +{ + public LuaDocumentSynchronizationKind Kind { get; } = kind; + public LuaDocumentSnapshot Document { get; } = document ?? throw new ArgumentNullException(nameof(document)); +} - public string FilePath { get; } - public string Uri { get; } - public string Content { get; } - public int Version { get; } - } -} \ No newline at end of file +internal sealed class LuaDocumentSnapshot(string filePath, string uri, string? content, int version) +{ + public string FilePath { get; } = filePath; + public string Uri { get; } = uri; + public string Content { get; } = content ?? string.Empty; + public int Version { get; } = version; +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index 76209f7dae..a372d9ec2e 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -8,717 +10,744 @@ using System.Threading; using System.Threading.Tasks; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed class LuaLanguageServerClient : IDisposable { - internal sealed class LuaLanguageServerClient : IDisposable + private const int ReceiveChunkSize = 4096; + private static readonly byte[] HeaderTerminator = [(byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n']; + + private readonly string _workspaceRootDirectoryPath; + private readonly string _serverExecutablePath; + private readonly Func _settingsProvider; + + private readonly SemaphoreSlim _startLock = new(1, 1); + private readonly SemaphoreSlim _writeLock = new(1, 1); + private readonly ConcurrentDictionary> _pendingRequests = new(); + + private static readonly string[] SupportedSemanticTokenTypes = + [ + "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", + "parameter", "variable", "property", "enumMember", "event", "function", "method", + "macro", "keyword", "modifier", "comment", "string", "number", "regexp", + "operator", "decorator" + ]; + + private static readonly string[] SupportedSemanticTokenModifiers = + [ + "declaration", "definition", "readonly", "static", "deprecated", "abstract", + "async", "modification", "documentation", "defaultLibrary", "global" + ]; + + private long _requestId; + private bool _isDisposed; + + private Process? _process; + private Stream? _inputStream; + private Stream? _outputStream; + private byte[] _receiveBuffer = []; + private int _receiveBufferCount; + private Task? _readLoopTask; + private Task? _stderrLoopTask; + private string[] _semanticTokenTypes = []; + private string[] _semanticTokenModifiers = []; + private bool _supportsCompletionResolve; + + public bool IsReady { get; private set; } + public IReadOnlyList SemanticTokenTypes => _semanticTokenTypes; + public IReadOnlyList SemanticTokenModifiers => _semanticTokenModifiers; + public bool SupportsCompletionResolve => _supportsCompletionResolve; + + public event Action? DiagnosticsPublished; + + public LuaLanguageServerClient(string workspaceRootDirectoryPath, string serverExecutablePath, Func settingsProvider) { - private const int ReceiveChunkSize = 4096; - private static readonly byte[] HeaderTerminator = { (byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n' }; - - private readonly string _workspaceRootDirectoryPath; - private readonly string _serverExecutablePath; - private readonly Func _settingsProvider; - - private readonly SemaphoreSlim _startLock = new(1, 1); - private readonly SemaphoreSlim _writeLock = new(1, 1); - private readonly ConcurrentDictionary> _pendingRequests = new(); - private static readonly string[] SupportedSemanticTokenTypes = - { - "namespace", "type", "class", "enum", "interface", "struct", "typeParameter", - "parameter", "variable", "property", "enumMember", "event", "function", "method", - "macro", "keyword", "modifier", "comment", "string", "number", "regexp", - "operator", "decorator" - }; - private static readonly string[] SupportedSemanticTokenModifiers = - { - "declaration", "definition", "readonly", "static", "deprecated", "abstract", - "async", "modification", "documentation", "defaultLibrary", "global" - }; - - private long _requestId; - private bool _isDisposed; - - private Process _process; - private Stream _inputStream; - private Stream _outputStream; - private byte[] _receiveBuffer = Array.Empty(); - private int _receiveBufferCount; - private Task _readLoopTask; - private Task _stderrLoopTask; - private string[] _semanticTokenTypes = Array.Empty(); - private string[] _semanticTokenModifiers = Array.Empty(); - private bool _supportsCompletionResolve; - - public bool IsReady { get; private set; } - public IReadOnlyList SemanticTokenTypes => _semanticTokenTypes; - public IReadOnlyList SemanticTokenModifiers => _semanticTokenModifiers; - public bool SupportsCompletionResolve => _supportsCompletionResolve; + _workspaceRootDirectoryPath = workspaceRootDirectoryPath; + _serverExecutablePath = serverExecutablePath; + _settingsProvider = settingsProvider; + } - public event Action DiagnosticsPublished; + public async Task StartAsync(CancellationToken cancellationToken) + { + if (IsReady) + return true; - public LuaLanguageServerClient(string workspaceRootDirectoryPath, string serverExecutablePath, Func settingsProvider) - { - _workspaceRootDirectoryPath = workspaceRootDirectoryPath ?? throw new ArgumentNullException(nameof(workspaceRootDirectoryPath)); - _serverExecutablePath = serverExecutablePath ?? throw new ArgumentNullException(nameof(serverExecutablePath)); - _settingsProvider = settingsProvider ?? throw new ArgumentNullException(nameof(settingsProvider)); - } + await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); - public async Task StartAsync(CancellationToken cancellationToken) + try { if (IsReady) return true; - await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); + ThrowIfDisposed(); + ResetProcessState(); - try + var startInfo = new ProcessStartInfo { - if (IsReady) - return true; - - ThrowIfDisposed(); - ResetProcessState(); - - var startInfo = new ProcessStartInfo - { - FileName = _serverExecutablePath, - WorkingDirectory = Path.GetDirectoryName(_serverExecutablePath), - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardInput = true, - RedirectStandardOutput = true, - RedirectStandardError = true - }; + FileName = _serverExecutablePath, + WorkingDirectory = Path.GetDirectoryName(_serverExecutablePath) ?? Environment.CurrentDirectory, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true + }; - _process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }; - _process.Exited += Process_Exited; + _process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }; + _process.Exited += Process_Exited; - if (!_process.Start()) - return false; + if (!_process.Start()) + return false; - _inputStream = _process.StandardOutput.BaseStream; - _outputStream = _process.StandardInput.BaseStream; + _inputStream = _process.StandardOutput.BaseStream; + _outputStream = _process.StandardInput.BaseStream; - _readLoopTask = Task.Run(ReadLoopAsync); - _stderrLoopTask = Task.Run(ReadStandardErrorLoopAsync); + _readLoopTask = Task.Run(ReadLoopAsync, CancellationToken.None); + _stderrLoopTask = Task.Run(ReadStandardErrorLoopAsync, CancellationToken.None); - using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); + using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); - JsonElement initializeResponse = await SendRequestAsync("initialize", BuildInitializeParams(), initializeTimeout.Token).ConfigureAwait(false); - CaptureServerCapabilities(initializeResponse); + JsonElement initializeResponse = await SendRequestAsync("initialize", BuildInitializeParams(), initializeTimeout.Token).ConfigureAwait(false); + CaptureServerCapabilities(initializeResponse); - IsReady = true; + IsReady = true; - await SendNotificationAsync("initialized", new { }, cancellationToken).ConfigureAwait(false); - await SendNotificationAsync("workspace/didChangeConfiguration", new { settings = _settingsProvider() }, cancellationToken).ConfigureAwait(false); + await SendNotificationAsync("initialized", new { }, cancellationToken).ConfigureAwait(false); + await SendNotificationAsync("workspace/didChangeConfiguration", new { settings = _settingsProvider() }, cancellationToken).ConfigureAwait(false); - return true; - } - catch - { - await DisposeProcessAsync().ConfigureAwait(false); - return false; - } - finally - { - _startLock.Release(); - } + return true; + } + catch + { + await DisposeProcessAsync().ConfigureAwait(false); + return false; } + finally + { + _startLock.Release(); + } + } - public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) - => WriteMessageAsync(new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken); + public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) + => WriteMessageAsync(new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken); - public async Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) - { - ThrowIfDisposed(); + public async Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) + { + ThrowIfDisposed(); - long requestId = Interlocked.Increment(ref _requestId); - var responseSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + long requestId = Interlocked.Increment(ref _requestId); + var responseSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - if (!_pendingRequests.TryAdd(requestId, responseSource)) - throw new InvalidOperationException("Unable to track a new language server request."); + if (!_pendingRequests.TryAdd(requestId, responseSource)) + throw new InvalidOperationException("Unable to track a new language server request."); - using var registration = cancellationToken.Register(() => responseSource.TrySetCanceled(cancellationToken)); + await using var registration = cancellationToken.Register(() => responseSource.TrySetCanceled(cancellationToken)); - try + try + { + await WriteMessageAsync(new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken).ConfigureAwait(false); + return await responseSource.Task.ConfigureAwait(false); + } + finally + { + _pendingRequests.TryRemove(requestId, out _); + } + } + + private object BuildInitializeParams() => new + { + processId = Environment.ProcessId, + initializationOptions = new + { + changeConfiguration = true, + viewDocument = true, + trustByClient = true, + useSemanticByRange = true + }, + rootUri = CreateFileUri(_workspaceRootDirectoryPath), + workspaceFolders = new[] + { + new { - await WriteMessageAsync(new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken).ConfigureAwait(false); - return await responseSource.Task.ConfigureAwait(false); + uri = CreateFileUri(_workspaceRootDirectoryPath), + name = Path.GetFileName(_workspaceRootDirectoryPath) } - finally + }, + capabilities = new + { + workspace = new { - _pendingRequests.TryRemove(requestId, out _); - } - } - - private object BuildInitializeParams() - => new + workspaceFolders = true, + configuration = true + }, + textDocument = new { - processId = Process.GetCurrentProcess().Id, - initializationOptions = new + completion = new { - changeConfiguration = true, - viewDocument = true, - trustByClient = true, - useSemanticByRange = true - }, - rootUri = CreateFileUri(_workspaceRootDirectoryPath), - workspaceFolders = new[] - { - new + contextSupport = true, + completionItem = new { - uri = CreateFileUri(_workspaceRootDirectoryPath), - name = Path.GetFileName(_workspaceRootDirectoryPath) + snippetSupport = false, + documentationFormat = new[] { "plaintext", "markdown" }, + resolveSupport = new + { + properties = new[] { "detail", "documentation" } + } } }, - capabilities = new + hover = new { - workspace = new - { - workspaceFolders = true, - configuration = true - }, - textDocument = new + contentFormat = new[] { "plaintext", "markdown" } + }, + definition = new + { + linkSupport = true + }, + publishDiagnostics = new + { + versionSupport = true + }, + signatureHelp = new + { + signatureInformation = new { - completion = new - { - contextSupport = true, - completionItem = new - { - snippetSupport = false, - documentationFormat = new[] { "plaintext", "markdown" }, - resolveSupport = new - { - properties = new[] { "detail", "documentation" } - } - } - }, - hover = new - { - contentFormat = new[] { "plaintext", "markdown" } - }, - definition = new + documentationFormat = new[] { "plaintext", "markdown" }, + parameterInformation = new { - linkSupport = true - }, - publishDiagnostics = new - { - versionSupport = true - }, - signatureHelp = new - { - signatureInformation = new - { - documentationFormat = new[] { "plaintext", "markdown" }, - parameterInformation = new - { - labelOffsetSupport = true - } - }, - contextSupport = true - }, - semanticTokens = new - { - requests = new - { - range = true - }, - tokenTypes = SupportedSemanticTokenTypes, - tokenModifiers = SupportedSemanticTokenModifiers, - formats = new[] { "relative" }, - multilineTokenSupport = false, - overlappingTokenSupport = false, - augmentsSyntaxTokens = true + labelOffsetSupport = true } - } + }, + contextSupport = true + }, + semanticTokens = new + { + requests = new + { + range = true + }, + tokenTypes = SupportedSemanticTokenTypes, + tokenModifiers = SupportedSemanticTokenModifiers, + formats = new[] { "relative" }, + multilineTokenSupport = false, + overlappingTokenSupport = false, + augmentsSyntaxTokens = true } - }; - - private void CaptureServerCapabilities(JsonElement initializeResponse) - { - _supportsCompletionResolve = false; - _semanticTokenTypes = Array.Empty(); - _semanticTokenModifiers = Array.Empty(); - - if (initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities) - && capabilities.TryGetProperty("completionProvider", out JsonElement completionProvider) - && completionProvider.TryGetProperty("resolveProvider", out JsonElement resolveProvider)) - { - _supportsCompletionResolve = resolveProvider.ValueKind == JsonValueKind.True; } + } + }; - if (!initializeResponse.TryGetProperty("capabilities", out capabilities) - || !capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider) - || !semanticTokensProvider.TryGetProperty("legend", out JsonElement legend)) - { - return; - } + private void CaptureServerCapabilities(JsonElement initializeResponse) + { + _supportsCompletionResolve = false; + _semanticTokenTypes = []; + _semanticTokenModifiers = []; - _semanticTokenTypes = ReadStringArray(legend, "tokenTypes"); - _semanticTokenModifiers = ReadStringArray(legend, "tokenModifiers"); + if (initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities) + && capabilities.TryGetProperty("completionProvider", out JsonElement completionProvider) + && completionProvider.TryGetProperty("resolveProvider", out JsonElement resolveProvider)) + { + _supportsCompletionResolve = resolveProvider.ValueKind == JsonValueKind.True; } - private static string[] ReadStringArray(JsonElement parent, string propertyName) + if (!initializeResponse.TryGetProperty("capabilities", out capabilities) + || !capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider) + || !semanticTokensProvider.TryGetProperty("legend", out JsonElement legend)) { - if (!parent.TryGetProperty(propertyName, out JsonElement property) || property.ValueKind != JsonValueKind.Array) - return Array.Empty(); + return; + } - var values = new List(); + _semanticTokenTypes = ReadStringArray(legend, "tokenTypes"); + _semanticTokenModifiers = ReadStringArray(legend, "tokenModifiers"); + } - foreach (JsonElement item in property.EnumerateArray()) - { - if (item.ValueKind == JsonValueKind.String) - values.Add(item.GetString()); - } + private static string[] ReadStringArray(JsonElement parent, string propertyName) + { + if (!parent.TryGetProperty(propertyName, out JsonElement property) || property.ValueKind != JsonValueKind.Array) + return []; - return values.ToArray(); - } + var values = new List(); - private async Task ReadLoopAsync() + foreach (JsonElement item in property.EnumerateArray()) { - try + if (item.ValueKind == JsonValueKind.String) { - while (!_isDisposed) - { - Dictionary headers = await ReadHeadersAsync().ConfigureAwait(false); - - if (headers is null || !headers.TryGetValue("Content-Length", out string contentLengthValue) - || !int.TryParse(contentLengthValue, out int contentLength) || contentLength <= 0) - break; + string? value = item.GetString(); - byte[] payloadBytes = await ReadPayloadAsync(contentLength).ConfigureAwait(false); - - if (payloadBytes is null) - break; - - using JsonDocument document = JsonDocument.Parse(payloadBytes); - await HandleMessageAsync(document.RootElement).ConfigureAwait(false); - } - } - catch (Exception exception) - { - FailPendingRequests(exception); - } - finally - { - IsReady = false; + if (!string.IsNullOrEmpty(value)) + values.Add(value); } } - private async Task ReadStandardErrorLoopAsync() + return [.. values]; + } + + private async Task ReadLoopAsync() + { + try { - try + while (!_isDisposed) { - while (!_isDisposed && _process is not null && !_process.HasExited) + Dictionary? headers = await ReadHeadersAsync().ConfigureAwait(false); + + if (headers is null || !headers.TryGetValue("Content-Length", out string? contentLengthValue) + || string.IsNullOrWhiteSpace(contentLengthValue) + || !int.TryParse(contentLengthValue, out int contentLength) || contentLength <= 0) { - string line = await _process.StandardError.ReadLineAsync().ConfigureAwait(false); + break; + } - if (line is null) - break; + byte[]? payloadBytes = await ReadPayloadAsync(contentLength).ConfigureAwait(false); - if (!string.IsNullOrWhiteSpace(line)) - Debug.WriteLine($"[LuaLS stderr] {line}"); - } - } - catch - { - // Ignore stderr read failures. + if (payloadBytes is null) + break; + + using JsonDocument document = JsonDocument.Parse(payloadBytes); + await HandleMessageAsync(document.RootElement).ConfigureAwait(false); } } + catch (Exception exception) + { + FailPendingRequests(exception); + } + finally + { + IsReady = false; + } + } - private async Task> ReadHeadersAsync() + private async Task ReadStandardErrorLoopAsync() + { + try { - while (true) + while (!_isDisposed) { - int headerTerminatorIndex = FindHeaderTerminatorIndex(); + Process? process = _process; + + if (process is null || process.HasExited) + break; + + string? line = await process.StandardError.ReadLineAsync().ConfigureAwait(false); - if (headerTerminatorIndex >= 0) - return ConsumeHeaders(headerTerminatorIndex); + if (line is null) + break; - if (!await ReadIntoReceiveBufferAsync().ConfigureAwait(false)) - return null; + if (!string.IsNullOrWhiteSpace(line)) + Debug.WriteLine($"[LuaLS stderr] {line}"); } } - - private Dictionary ConsumeHeaders(int headerTerminatorIndex) + catch { - string headerText = Encoding.ASCII.GetString(_receiveBuffer, 0, headerTerminatorIndex); - ConsumeReceiveBuffer(headerTerminatorIndex + HeaderTerminator.Length); - return ParseHeaders(headerText); + // Ignore stderr read failures. } + } - private static Dictionary ParseHeaders(string headerText) + private async Task?> ReadHeadersAsync() + { + while (true) { - var headers = new Dictionary(StringComparer.OrdinalIgnoreCase); + int headerTerminatorIndex = FindHeaderTerminatorIndex(); - foreach (string line in headerText.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)) - { - int separatorIndex = line.IndexOf(':'); + if (headerTerminatorIndex >= 0) + return ConsumeHeaders(headerTerminatorIndex); - if (separatorIndex <= 0) - continue; + if (!await ReadIntoReceiveBufferAsync().ConfigureAwait(false)) + return null; + } + } - string key = line[..separatorIndex].Trim(); - string value = line[(separatorIndex + 1)..].Trim(); + private Dictionary ConsumeHeaders(int headerTerminatorIndex) + { + string headerText = Encoding.ASCII.GetString(_receiveBuffer, 0, headerTerminatorIndex); + ConsumeReceiveBuffer(headerTerminatorIndex + HeaderTerminator.Length); + return ParseHeaders(headerText); + } - headers[key] = value; - } + private static Dictionary ParseHeaders(string headerText) + { + var headers = new Dictionary(StringComparer.OrdinalIgnoreCase); + + foreach (string line in headerText.Split(["\r\n"], StringSplitOptions.RemoveEmptyEntries)) + { + int separatorIndex = line.IndexOf(':'); - return headers; + if (separatorIndex <= 0) + continue; + + string key = line[..separatorIndex].Trim(); + headers[key] = line[(separatorIndex + 1)..].Trim(); } - private int FindHeaderTerminatorIndex() - => new ReadOnlySpan(_receiveBuffer, 0, _receiveBufferCount).IndexOf(HeaderTerminator); + return headers; + } - private async Task ReadIntoReceiveBufferAsync() - { - EnsureReceiveBufferCapacity(_receiveBufferCount + ReceiveChunkSize); + private int FindHeaderTerminatorIndex() + => new ReadOnlySpan(_receiveBuffer, 0, _receiveBufferCount).IndexOf(HeaderTerminator); - int bytesToRead = Math.Min(ReceiveChunkSize, _receiveBuffer.Length - _receiveBufferCount); - int bytesRead = await _inputStream - .ReadAsync(_receiveBuffer.AsMemory(_receiveBufferCount, bytesToRead)) - .ConfigureAwait(false); + private async Task ReadIntoReceiveBufferAsync() + { + if (_inputStream is null) + return false; - if (bytesRead == 0) - return false; + EnsureReceiveBufferCapacity(_receiveBufferCount + ReceiveChunkSize); - _receiveBufferCount += bytesRead; - return true; - } + int bytesToRead = Math.Min(ReceiveChunkSize, _receiveBuffer.Length - _receiveBufferCount); + int bytesRead = await _inputStream + .ReadAsync(_receiveBuffer.AsMemory(_receiveBufferCount, bytesToRead)) + .ConfigureAwait(false); - private void EnsureReceiveBufferCapacity(int requiredCapacity) - { - if (_receiveBuffer.Length >= requiredCapacity) - return; + if (bytesRead == 0) + return false; - int newCapacity = Math.Max(ReceiveChunkSize, _receiveBuffer.Length); + _receiveBufferCount += bytesRead; + return true; + } - while (newCapacity < requiredCapacity) - newCapacity *= 2; + private void EnsureReceiveBufferCapacity(int requiredCapacity) + { + if (_receiveBuffer.Length >= requiredCapacity) + return; - Array.Resize(ref _receiveBuffer, newCapacity); - } + int newCapacity = Math.Max(ReceiveChunkSize, _receiveBuffer.Length); - private void ConsumeReceiveBuffer(int bytesToConsume) - { - int remainingBytes = _receiveBufferCount - bytesToConsume; + while (newCapacity < requiredCapacity) + newCapacity *= 2; - if (remainingBytes > 0) - Buffer.BlockCopy(_receiveBuffer, bytesToConsume, _receiveBuffer, 0, remainingBytes); + Array.Resize(ref _receiveBuffer, newCapacity); + } - _receiveBufferCount = Math.Max(0, remainingBytes); - } + private void ConsumeReceiveBuffer(int bytesToConsume) + { + int remainingBytes = _receiveBufferCount - bytesToConsume; - private async Task ReadPayloadAsync(int contentLength) - { - byte[] payloadBytes = new byte[contentLength]; - int totalBytesRead = 0; + if (remainingBytes > 0) + Buffer.BlockCopy(_receiveBuffer, bytesToConsume, _receiveBuffer, 0, remainingBytes); - if (_receiveBufferCount > 0) - { - int bufferedBytesToCopy = Math.Min(contentLength, _receiveBufferCount); - Buffer.BlockCopy(_receiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); - ConsumeReceiveBuffer(bufferedBytesToCopy); - totalBytesRead = bufferedBytesToCopy; - } + _receiveBufferCount = Math.Max(0, remainingBytes); + } - while (totalBytesRead < contentLength) - { - int bytesRead = await _inputStream - .ReadAsync(payloadBytes.AsMemory(totalBytesRead, contentLength - totalBytesRead)) - .ConfigureAwait(false); + private async Task ReadPayloadAsync(int contentLength) + { + if (_inputStream is null) + return null; - if (bytesRead == 0) - return null; + byte[] payloadBytes = new byte[contentLength]; + int totalBytesRead = 0; - totalBytesRead += bytesRead; - } + if (_receiveBufferCount > 0) + { + int bufferedBytesToCopy = Math.Min(contentLength, _receiveBufferCount); + Buffer.BlockCopy(_receiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); + ConsumeReceiveBuffer(bufferedBytesToCopy); + totalBytesRead = bufferedBytesToCopy; + } + + while (totalBytesRead < contentLength) + { + int bytesRead = await _inputStream + .ReadAsync(payloadBytes.AsMemory(totalBytesRead, contentLength - totalBytesRead)) + .ConfigureAwait(false); - return payloadBytes; + if (bytesRead == 0) + return null; + + totalBytesRead += bytesRead; } - private async Task HandleMessageAsync(JsonElement message) + return payloadBytes; + } + + private async Task HandleMessageAsync(JsonElement message) + { + if (message.TryGetProperty("id", out JsonElement idElement)) { - if (message.TryGetProperty("id", out JsonElement idElement)) + if (message.TryGetProperty("method", out JsonElement methodElement)) { - if (message.TryGetProperty("method", out JsonElement methodElement)) - { - JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) - ? paramsElement.Clone() - : default; + string? method = methodElement.GetString(); + + if (string.IsNullOrWhiteSpace(method)) + return; - await HandleServerRequestAsync(idElement.Clone(), methodElement.GetString(), parameters).ConfigureAwait(false); - } - else - { - HandleServerResponse(idElement, message); - } - } - else if (message.TryGetProperty("method", out JsonElement notificationMethodElement)) - { JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) ? paramsElement.Clone() : default; - HandleServerNotification(notificationMethodElement.GetString(), parameters); + await HandleServerRequestAsync(idElement.Clone(), method, parameters).ConfigureAwait(false); + } + else + { + HandleServerResponse(idElement, message); } } - - private void HandleServerResponse(JsonElement idElement, JsonElement message) + else if (message.TryGetProperty("method", out JsonElement notificationMethodElement)) { - if (!idElement.TryGetInt64(out long requestId) || !_pendingRequests.TryGetValue(requestId, out TaskCompletionSource responseSource)) - return; + string? method = notificationMethodElement.GetString(); - if (message.TryGetProperty("error", out JsonElement errorElement)) - { - string messageText = errorElement.TryGetProperty("message", out JsonElement errorMessageElement) - ? errorMessageElement.GetString() - : "Lua language server request failed."; - - responseSource.TrySetException(new InvalidOperationException(messageText)); + if (string.IsNullOrWhiteSpace(method)) return; - } - if (message.TryGetProperty("result", out JsonElement resultElement)) - responseSource.TrySetResult(resultElement.Clone()); - else - responseSource.TrySetResult(default); + JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) + ? paramsElement.Clone() + : default; + + HandleServerNotification(method, parameters); } + } - private async Task HandleServerRequestAsync(JsonElement idElement, string method, JsonElement parameters) + private void HandleServerResponse(JsonElement idElement, JsonElement message) + { + if (!idElement.TryGetInt64(out long requestId) || !_pendingRequests.TryGetValue(requestId, out TaskCompletionSource? responseSource)) + return; + + if (message.TryGetProperty("error", out JsonElement errorElement)) { - object result = method switch - { - "workspace/configuration" => BuildConfigurationResponse(parameters), - "workspace/workspaceFolders" => BuildWorkspaceFolderResponse(), - "client/registerCapability" => null, - "window/workDoneProgress/create" => null, - _ => null - }; + string messageText = errorElement.TryGetProperty("message", out JsonElement errorMessageElement) + ? errorMessageElement.GetString() ?? "Lua language server request failed." + : "Lua language server request failed."; - await WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None).ConfigureAwait(false); + responseSource.TrySetException(new InvalidOperationException(messageText)); + return; } - private object[] BuildConfigurationResponse(JsonElement parameters) + if (message.TryGetProperty("result", out JsonElement resultElement)) + responseSource.TrySetResult(resultElement.Clone()); + else + responseSource.TrySetResult(default); + } + + private async Task HandleServerRequestAsync(JsonElement idElement, string method, JsonElement parameters) + { + object? result = method switch { - if (!parameters.TryGetProperty("items", out JsonElement itemsElement) || itemsElement.ValueKind != JsonValueKind.Array) - return Array.Empty(); + "workspace/configuration" => BuildConfigurationResponse(parameters), + "workspace/workspaceFolders" => BuildWorkspaceFolderResponse(), + "client/registerCapability" => null, + "window/workDoneProgress/create" => null, + _ => null + }; + + await WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None).ConfigureAwait(false); + } - JsonElement settingsElement = JsonSerializer.SerializeToElement(_settingsProvider()); - JsonElement luaElement = settingsElement.GetProperty("Lua"); + private object[] BuildConfigurationResponse(JsonElement parameters) + { + if (!parameters.TryGetProperty("items", out JsonElement itemsElement) || itemsElement.ValueKind != JsonValueKind.Array) + return []; - var results = new List(); + JsonElement settingsElement = JsonSerializer.SerializeToElement(_settingsProvider()); + JsonElement luaElement = settingsElement.GetProperty("Lua"); - foreach (JsonElement item in itemsElement.EnumerateArray()) - { - string section = item.TryGetProperty("section", out JsonElement sectionElement) - ? sectionElement.GetString() - : null; + var results = new List(); - results.Add(GetConfigurationSection(settingsElement, luaElement, section)); - } + foreach (JsonElement item in itemsElement.EnumerateArray()) + { + string? section = item.TryGetProperty("section", out JsonElement sectionElement) + ? sectionElement.GetString() + : null; - return results.ToArray(); + results.Add(GetConfigurationSection(settingsElement, luaElement, section)); } - private static object GetConfigurationSection(JsonElement settingsElement, JsonElement luaElement, string section) - { - if (string.IsNullOrWhiteSpace(section)) - return settingsElement.Clone(); + return [.. results]; + } - if (section.Equals("Lua", StringComparison.OrdinalIgnoreCase)) - return luaElement.Clone(); + private static object GetConfigurationSection(JsonElement settingsElement, JsonElement luaElement, string? section) + { + if (string.IsNullOrWhiteSpace(section)) + return settingsElement.Clone(); - if (section.StartsWith("Lua.", StringComparison.OrdinalIgnoreCase)) - { - JsonElement nestedSection = luaElement; - string[] parts = section[4..].Split('.'); + if (section.Equals("Lua", StringComparison.OrdinalIgnoreCase)) + return luaElement.Clone(); - foreach (string part in parts) - { - if (!nestedSection.TryGetProperty(part, out JsonElement nextSection)) - return new { }; + if (section.StartsWith("Lua.", StringComparison.OrdinalIgnoreCase)) + { + JsonElement nestedSection = luaElement; + string[] parts = section[4..].Split('.'); - nestedSection = nextSection; - } + foreach (string part in parts) + { + if (!nestedSection.TryGetProperty(part, out JsonElement nextSection)) + return new { }; - return nestedSection.Clone(); + nestedSection = nextSection; } - return new { }; + return nestedSection.Clone(); } - private object[] BuildWorkspaceFolderResponse() - => new object[] - { - new - { - uri = CreateFileUri(_workspaceRootDirectoryPath), - name = Path.GetFileName(_workspaceRootDirectoryPath) - } - }; + return new { }; + } - private void HandleServerNotification(string method, JsonElement parameters) + private object[] BuildWorkspaceFolderResponse() => + [ + new { - switch (method) - { - case "textDocument/publishDiagnostics": - DiagnosticsPublished?.Invoke(parameters); - return; - case "window/logMessage": - case "window/showMessage": - case "telemetry/event": - case "$/progress": - return; - } + uri = CreateFileUri(_workspaceRootDirectoryPath), + name = Path.GetFileName(_workspaceRootDirectoryPath) } + ]; - private async Task WriteMessageAsync(object payload, CancellationToken cancellationToken) + private void HandleServerNotification(string method, JsonElement parameters) + { + switch (method) { - ThrowIfDisposed(); - - byte[] payloadBytes = JsonSerializer.SerializeToUtf8Bytes(payload); - byte[] headerBytes = Encoding.ASCII.GetBytes($"Content-Length: {payloadBytes.Length}\r\n\r\n"); - - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + case "textDocument/publishDiagnostics": + DiagnosticsPublished?.Invoke(parameters); + return; - try - { - await _outputStream.WriteAsync(headerBytes.AsMemory(0, headerBytes.Length), cancellationToken).ConfigureAwait(false); - await _outputStream.WriteAsync(payloadBytes.AsMemory(0, payloadBytes.Length), cancellationToken).ConfigureAwait(false); - await _outputStream.FlushAsync(cancellationToken).ConfigureAwait(false); - } - finally - { - _writeLock.Release(); - } + case "window/logMessage": + case "window/showMessage": + case "telemetry/event": + case "$/progress": + return; } + } - private void Process_Exited(object sender, EventArgs e) - { - int? exitCode = null; + private async Task WriteMessageAsync(object payload, CancellationToken cancellationToken) + { + ThrowIfDisposed(); - try - { - if (_process is not null && _process.HasExited) - exitCode = _process.ExitCode; - } - catch - { - // Ignore exit-code access failures. - } + if (_outputStream is null) + throw new IOException("The Lua language server output stream is not available."); - IsReady = false; + byte[] payloadBytes = JsonSerializer.SerializeToUtf8Bytes(payload); + byte[] headerBytes = Encoding.ASCII.GetBytes($"Content-Length: {payloadBytes.Length}\r\n\r\n"); - if (!_isDisposed) - Debug.WriteLine($"[LuaLS] Process exited unexpectedly{(exitCode is not null ? $" with code {exitCode.Value}" : string.Empty)}."); + await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); - FailPendingRequests(new IOException("The Lua language server process exited unexpectedly.")); + try + { + await _outputStream.WriteAsync(headerBytes.AsMemory(0, headerBytes.Length), cancellationToken).ConfigureAwait(false); + await _outputStream.WriteAsync(payloadBytes.AsMemory(0, payloadBytes.Length), cancellationToken).ConfigureAwait(false); + await _outputStream.FlushAsync(cancellationToken).ConfigureAwait(false); } - - private void FailPendingRequests(Exception exception) + finally { - foreach (KeyValuePair> pendingRequest in _pendingRequests) - pendingRequest.Value.TrySetException(exception); + _writeLock.Release(); } + } + + private void Process_Exited(object? sender, EventArgs e) + { + int? exitCode = null; - private async Task DisposeProcessAsync() + try { - try - { - if (_process is not null && !_process.HasExited) - { - using var shutdownTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); + if (_process is not null && _process.HasExited) + exitCode = _process.ExitCode; + } + catch + { + // Ignore exit-code access failures. + } - try - { - await SendRequestAsync("shutdown", new { }, shutdownTimeout.Token).ConfigureAwait(false); - } - catch - { - // Ignore shutdown failures. - } + IsReady = false; - try - { - await SendNotificationAsync("exit", new { }, shutdownTimeout.Token).ConfigureAwait(false); - } - catch - { - // Ignore exit notification failures. - } + if (!_isDisposed) + Debug.WriteLine($"[LuaLS] Process exited unexpectedly{(exitCode is not null ? $" with code {exitCode.Value}" : string.Empty)}."); - if (!_process.HasExited) - _process.Kill(true); - } - } - catch - { - // Ignore process disposal failures. - } - finally - { - ResetProcessState(); - IsReady = false; - } - } + FailPendingRequests(new IOException("The Lua language server process exited unexpectedly.")); + } + + private void FailPendingRequests(Exception exception) + { + foreach (KeyValuePair> pendingRequest in _pendingRequests) + pendingRequest.Value.TrySetException(exception); + } - private void ResetProcessState() + private async Task DisposeProcessAsync() + { + try { - try - { - if (_process is not null) - _process.Exited -= Process_Exited; - } - catch + if (_process is not null && !_process.HasExited) { - // Ignore event detach failures. - } + using var shutdownTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); - try - { - _inputStream?.Dispose(); - _outputStream?.Dispose(); - _process?.Dispose(); - } - catch - { - // Ignore stream disposal failures. + try + { + await SendRequestAsync("shutdown", new { }, shutdownTimeout.Token).ConfigureAwait(false); + } + catch + { + // Ignore shutdown failures. + } + + try + { + await SendNotificationAsync("exit", new { }, shutdownTimeout.Token).ConfigureAwait(false); + } + catch + { + // Ignore exit notification failures. + } + + if (!_process.HasExited) + _process.Kill(true); } + } + catch + { + // Ignore process disposal failures. + } + finally + { + ResetProcessState(); + IsReady = false; + } + } - _inputStream = null; - _outputStream = null; - _process = null; - _receiveBuffer = Array.Empty(); - _receiveBufferCount = 0; - _readLoopTask = null; - _stderrLoopTask = null; - _supportsCompletionResolve = false; - _semanticTokenTypes = Array.Empty(); - _semanticTokenModifiers = Array.Empty(); + private void ResetProcessState() + { + try + { + if (_process is not null) + _process.Exited -= Process_Exited; + } + catch + { + // Ignore event detach failures. } - private void ThrowIfDisposed() + try { - if (_isDisposed) - throw new ObjectDisposedException(nameof(LuaLanguageServerClient)); + _inputStream?.Dispose(); + _outputStream?.Dispose(); + _process?.Dispose(); + } + catch + { + // Ignore stream disposal failures. } - private static string CreateFileUri(string path) - => new Uri(Path.GetFullPath(path)).AbsoluteUri; + _inputStream = null; + _outputStream = null; + _process = null; + _receiveBuffer = []; + _receiveBufferCount = 0; + _readLoopTask = null; + _stderrLoopTask = null; + _supportsCompletionResolve = false; + _semanticTokenTypes = []; + _semanticTokenModifiers = []; + } - public void Dispose() - { - if (_isDisposed) - return; + private void ThrowIfDisposed() + => ObjectDisposedException.ThrowIf(_isDisposed, nameof(LuaLanguageServerClient)); - _isDisposed = true; - FailPendingRequests(new ObjectDisposedException(nameof(LuaLanguageServerClient))); + private static string CreateFileUri(string path) + => new Uri(Path.GetFullPath(path)).AbsoluteUri; - DisposeProcessAsync().GetAwaiter().GetResult(); + public void Dispose() + { + if (_isDisposed) + return; - _startLock.Dispose(); - _writeLock.Dispose(); - } + _isDisposed = true; + FailPendingRequests(new ObjectDisposedException(nameof(LuaLanguageServerClient))); + + DisposeProcessAsync().GetAwaiter().GetResult(); + + _startLock.Dispose(); + _writeLock.Dispose(); } -} \ No newline at end of file +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs index d394d6fb81..af0f79d4b9 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs @@ -1,297 +1,294 @@ +#nullable enable + +using ICSharpCode.AvalonEdit.Document; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; using System.Text.Json; -using ICSharpCode.AvalonEdit.Document; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static class LuaLanguageServerDiagnosticsParser { - internal static class LuaLanguageServerDiagnosticsParser + /// + /// Parses a LuaLS diagnostics notification into editor diagnostics for a tracked document. + /// + public static bool TryParse(JsonElement parameters, string filePath, + string? documentContent, int documentVersion, [NotNullWhen(true)] out LuaPublishedDiagnostics? publishedDiagnostics) { - public static bool TryParse(JsonElement parameters, string filePath, - string documentContent, int documentVersion, out LuaPublishedDiagnostics publishedDiagnostics) - { - publishedDiagnostics = null; + publishedDiagnostics = null; - if (parameters.ValueKind != JsonValueKind.Object) - return false; + if (parameters.ValueKind != JsonValueKind.Object) + return false; - int diagnosticsVersion = 0; + int diagnosticsVersion = 0; - if (parameters.TryGetProperty("version", out JsonElement versionElement) - && versionElement.ValueKind == JsonValueKind.Number - && versionElement.TryGetInt32(out int parsedVersion) - && parsedVersion > 0) - { - diagnosticsVersion = parsedVersion; - } - - if (diagnosticsVersion > 0 && documentVersion > 0 && diagnosticsVersion > documentVersion) - return false; + if (parameters.TryGetProperty("version", out JsonElement versionElement) + && versionElement.ValueKind == JsonValueKind.Number + && versionElement.TryGetInt32(out int parsedVersion) + && parsedVersion > 0) + { + diagnosticsVersion = parsedVersion; + } - IReadOnlyList diagnostics = Array.Empty(); - string resolvedContent = ResolveDocumentContent(filePath, documentContent); + if (diagnosticsVersion > 0 && documentVersion > 0 && diagnosticsVersion > documentVersion) + return false; - if (parameters.TryGetProperty("diagnostics", out JsonElement diagnosticsElement) - && diagnosticsElement.ValueKind == JsonValueKind.Array) - { - diagnostics = BuildDiagnostics(resolvedContent, diagnosticsElement); - } + IReadOnlyList diagnostics = Array.Empty(); + string resolvedContent = ResolveDocumentContent(filePath, documentContent); - publishedDiagnostics = new LuaPublishedDiagnostics(filePath, diagnostics, diagnosticsVersion); - return true; + if (parameters.TryGetProperty("diagnostics", out JsonElement diagnosticsElement) + && diagnosticsElement.ValueKind == JsonValueKind.Array) + { + diagnostics = BuildDiagnostics(resolvedContent, diagnosticsElement); } - private static string ResolveDocumentContent(string filePath, string documentContent) - { - if (!string.IsNullOrEmpty(documentContent)) - return documentContent; + publishedDiagnostics = new LuaPublishedDiagnostics(filePath, diagnostics, diagnosticsVersion); + return true; + } - if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) - return string.Empty; + private static string ResolveDocumentContent(string filePath, string? documentContent) + { + if (!string.IsNullOrEmpty(documentContent)) + return documentContent; - try - { - return File.ReadAllText(filePath); - } - catch - { - return string.Empty; - } - } + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + return string.Empty; - private static IReadOnlyList BuildDiagnostics(string content, JsonElement diagnosticsElement) + try { - var document = new TextDocument(content ?? string.Empty); - var diagnostics = new List(); + return File.ReadAllText(filePath); + } + catch + { + return string.Empty; + } + } - foreach (JsonElement diagnosticElement in diagnosticsElement.EnumerateArray()) - { - TextEditorDiagnosticSeverity severity = GetDiagnosticSeverity(diagnosticElement); + private static IReadOnlyList BuildDiagnostics(string content, JsonElement diagnosticsElement) + { + var document = new TextDocument(content); + var diagnostics = new List(); - if (severity > TextEditorDiagnosticSeverity.Warning) - continue; + foreach (JsonElement diagnosticElement in diagnosticsElement.EnumerateArray()) + { + TextEditorDiagnosticSeverity severity = GetDiagnosticSeverity(diagnosticElement); - if (!TryCreateDiagnostic(document, diagnosticElement, severity, out TextEditorDiagnostic diagnostic)) - continue; + if (severity > TextEditorDiagnosticSeverity.Warning) + continue; - diagnostics.Add(diagnostic); - } + if (!TryCreateDiagnostic(document, diagnosticElement, severity, out TextEditorDiagnostic? diagnostic)) + continue; - return diagnostics - .OrderBy(diagnostic => diagnostic.StartOffset) - .ThenBy(diagnostic => diagnostic.Severity) - .ToList(); + diagnostics.Add(diagnostic); } - private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagnosticElement, - TextEditorDiagnosticSeverity severity, out TextEditorDiagnostic diagnostic) - { - diagnostic = null; - - if (document.LineCount == 0 - || !diagnosticElement.TryGetProperty("range", out JsonElement rangeElement) - || !rangeElement.TryGetProperty("start", out JsonElement startElement) - || startElement.ValueKind != JsonValueKind.Object - || !startElement.TryGetProperty("line", out JsonElement lineElement) - || !lineElement.TryGetInt32(out int lineIndex)) - { - return false; - } + return [.. diagnostics + .OrderBy(diagnostic => diagnostic.StartOffset) + .ThenBy(diagnostic => diagnostic.Severity)]; + } - lineIndex = Math.Max(0, Math.Min(lineIndex, document.LineCount - 1)); + private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagnosticElement, + TextEditorDiagnosticSeverity severity, [NotNullWhen(true)] out TextEditorDiagnostic? diagnostic) + { + diagnostic = null; + + if (document.LineCount == 0 + || !diagnosticElement.TryGetProperty("range", out JsonElement rangeElement) + || !rangeElement.TryGetProperty("start", out JsonElement startElement) + || startElement.ValueKind != JsonValueKind.Object + || !startElement.TryGetProperty("line", out JsonElement lineElement) + || !lineElement.TryGetInt32(out int lineIndex)) + { + return false; + } - int startCharacter = startElement.TryGetProperty("character", out JsonElement characterElement) - && characterElement.TryGetInt32(out int character) - ? Math.Max(0, character) - : 0; + lineIndex = Math.Max(0, Math.Min(lineIndex, document.LineCount - 1)); - int endLineIndex = lineIndex; - int endCharacter = startCharacter; + int startCharacter = startElement.TryGetProperty("character", out JsonElement characterElement) + && characterElement.TryGetInt32(out int character) + ? Math.Max(0, character) + : 0; - if (rangeElement.TryGetProperty("end", out JsonElement endElement) - && endElement.ValueKind == JsonValueKind.Object - && endElement.TryGetProperty("line", out JsonElement endLineElement) - && endLineElement.TryGetInt32(out int rawEndLineIndex)) - { - endLineIndex = Math.Max(lineIndex, Math.Min(rawEndLineIndex, document.LineCount - 1)); + int endLineIndex = lineIndex; + int endCharacter = startCharacter; - if (endElement.TryGetProperty("character", out JsonElement endCharacterElement) - && endCharacterElement.TryGetInt32(out int endCharacterValue)) - { - endCharacter = Math.Max(0, endCharacterValue); - } - } + if (rangeElement.TryGetProperty("end", out JsonElement endElement) + && endElement.ValueKind == JsonValueKind.Object + && endElement.TryGetProperty("line", out JsonElement endLineElement) + && endLineElement.TryGetInt32(out int rawEndLineIndex)) + { + endLineIndex = Math.Max(lineIndex, Math.Min(rawEndLineIndex, document.LineCount - 1)); - if (!TryGetDiagnosticOffsets(document, lineIndex, startCharacter, endLineIndex, endCharacter, - out int startOffset, out int endOffset)) + if (endElement.TryGetProperty("character", out JsonElement endCharacterElement) + && endCharacterElement.TryGetInt32(out int endCharacterValue)) { - return false; + endCharacter = Math.Max(0, endCharacterValue); } - - diagnostic = new TextEditorDiagnostic(severity, BuildDiagnosticMessage(diagnosticElement, severity), startOffset, endOffset); - return true; } - private static bool TryGetDiagnosticOffsets(TextDocument document, - int startLineIndex, int startCharacter, int endLineIndex, int endCharacter, - out int startOffset, out int endOffset) + if (!TryGetDiagnosticOffsets(document, lineIndex, startCharacter, endLineIndex, endCharacter, + out int startOffset, out int endOffset)) { - startOffset = 0; - endOffset = 0; - - if (document.LineCount == 0) - return false; - - DocumentLine startLine = document.GetLineByNumber(startLineIndex + 1); - DocumentLine endLine = document.GetLineByNumber(endLineIndex + 1); - startOffset = startLine.Offset + Math.Max(0, Math.Min(startCharacter, startLine.Length)); - endOffset = endLine.Offset + Math.Max(0, Math.Min(endCharacter, endLine.Length)); - - if (endOffset > startOffset) - return true; + return false; + } - string lineText = document.GetText(startLine); + diagnostic = new TextEditorDiagnostic(severity, BuildDiagnosticMessage(diagnosticElement, severity), startOffset, endOffset); + return true; + } - if (string.IsNullOrEmpty(lineText)) - return false; + private static bool TryGetDiagnosticOffsets(TextDocument document, + int startLineIndex, int startCharacter, int endLineIndex, int endCharacter, + out int startOffset, out int endOffset) + { + startOffset = 0; + endOffset = 0; - int safeCharacter = Math.Max(0, Math.Min(startCharacter, Math.Max(0, lineText.Length - 1))); + if (document.LineCount == 0) + return false; - if (TryGetWordBounds(lineText, safeCharacter, out int wordStart, out int wordEnd)) - { - startOffset = startLine.Offset + wordStart; - endOffset = startLine.Offset + wordEnd; - return endOffset > startOffset; - } + DocumentLine startLine = document.GetLineByNumber(startLineIndex + 1); + DocumentLine endLine = document.GetLineByNumber(endLineIndex + 1); + startOffset = startLine.Offset + Math.Max(0, Math.Min(startCharacter, startLine.Length)); + endOffset = endLine.Offset + Math.Max(0, Math.Min(endCharacter, endLine.Length)); - int trimmedStart = 0; - int trimmedEnd = lineText.Length; + if (endOffset > startOffset) + return true; - while (trimmedStart < trimmedEnd && char.IsWhiteSpace(lineText[trimmedStart])) - trimmedStart++; + string lineText = document.GetText(startLine); - while (trimmedEnd > trimmedStart && char.IsWhiteSpace(lineText[trimmedEnd - 1])) - trimmedEnd--; + if (string.IsNullOrEmpty(lineText)) + return false; - if (trimmedEnd > trimmedStart) - { - startOffset = startLine.Offset + trimmedStart; - endOffset = startLine.Offset + trimmedEnd; - return true; - } + int safeCharacter = Math.Max(0, Math.Min(startCharacter, Math.Max(0, lineText.Length - 1))); - startOffset = startLine.Offset + safeCharacter; - endOffset = Math.Min(startOffset + 1, document.TextLength); + if (TryGetWordBounds(lineText, safeCharacter, out int wordStart, out int wordEnd)) + { + startOffset = startLine.Offset + wordStart; + endOffset = startLine.Offset + wordEnd; return endOffset > startOffset; } - private static bool TryGetWordBounds(string lineText, int index, out int wordStart, out int wordEnd) - { - wordStart = 0; - wordEnd = 0; + int trimmedStart = 0; + int trimmedEnd = lineText.Length; - if (string.IsNullOrEmpty(lineText)) - return false; + while (trimmedStart < trimmedEnd && char.IsWhiteSpace(lineText[trimmedStart])) + trimmedStart++; + + while (trimmedEnd > trimmedStart && char.IsWhiteSpace(lineText[trimmedEnd - 1])) + trimmedEnd--; - int safeIndex = Math.Max(0, Math.Min(index, lineText.Length - 1)); + if (trimmedEnd > trimmedStart) + { + startOffset = startLine.Offset + trimmedStart; + endOffset = startLine.Offset + trimmedEnd; + return true; + } - if (!IsDiagnosticSegmentCharacter(lineText[safeIndex]) && safeIndex > 0 && IsDiagnosticSegmentCharacter(lineText[safeIndex - 1])) - safeIndex--; + startOffset = startLine.Offset + safeCharacter; + endOffset = Math.Min(startOffset + 1, document.TextLength); + return endOffset > startOffset; + } - while (safeIndex < lineText.Length && !IsDiagnosticSegmentCharacter(lineText[safeIndex])) - { - safeIndex++; + private static bool TryGetWordBounds(string lineText, int index, out int wordStart, out int wordEnd) + { + wordStart = 0; + wordEnd = 0; - if (safeIndex >= lineText.Length) - return false; - } + if (string.IsNullOrEmpty(lineText)) + return false; - wordStart = safeIndex; - wordEnd = safeIndex; + int safeIndex = Math.Max(0, Math.Min(index, lineText.Length - 1)); - while (wordStart > 0 && IsDiagnosticSegmentCharacter(lineText[wordStart - 1])) - wordStart--; + if (!IsDiagnosticSegmentCharacter(lineText[safeIndex]) && safeIndex > 0 && IsDiagnosticSegmentCharacter(lineText[safeIndex - 1])) + safeIndex--; - while (wordEnd < lineText.Length && IsDiagnosticSegmentCharacter(lineText[wordEnd])) - wordEnd++; + while (safeIndex < lineText.Length && !IsDiagnosticSegmentCharacter(lineText[safeIndex])) + { + safeIndex++; - return wordEnd > wordStart; + if (safeIndex >= lineText.Length) + return false; } - private static bool IsDiagnosticSegmentCharacter(char c) - => char.IsLetterOrDigit(c) || c == '_' || c == '.' || c == ':' || c == '\'' || c == '"'; + wordStart = safeIndex; + wordEnd = safeIndex; - private static TextEditorDiagnosticSeverity GetDiagnosticSeverity(JsonElement diagnosticElement) - => diagnosticElement.TryGetProperty("severity", out JsonElement severityElement) - && severityElement.TryGetInt32(out int severity) - && severity > 0 - ? (TextEditorDiagnosticSeverity)severity - : TextEditorDiagnosticSeverity.Warning; + while (wordStart > 0 && IsDiagnosticSegmentCharacter(lineText[wordStart - 1])) + wordStart--; - private static string BuildDiagnosticMessage(JsonElement diagnosticElement, TextEditorDiagnosticSeverity severity) - { - string message = diagnosticElement.TryGetProperty("message", out JsonElement messageElement) - ? messageElement.GetString()?.Trim() - : null; - - if (string.IsNullOrWhiteSpace(message)) - message = "Unknown Lua diagnostic."; - - var builder = new StringBuilder(); - builder.Append(severity.GetLabel()); - builder.Append(": "); - builder.Append(message); - - string source = diagnosticElement.TryGetProperty("source", out JsonElement sourceElement) - ? sourceElement.GetString() - : null; - - string code = diagnosticElement.TryGetProperty("code", out JsonElement codeElement) - ? codeElement.ValueKind == JsonValueKind.String - ? codeElement.GetString() - : codeElement.ValueKind == JsonValueKind.Number - ? codeElement.GetRawText() - : null - : null; - - if (!string.IsNullOrWhiteSpace(source) || !string.IsNullOrWhiteSpace(code)) - { - builder.AppendLine(); - builder.AppendLine(); - builder.Append("Source: "); - - if (!string.IsNullOrWhiteSpace(source)) - builder.Append(source.Trim()); - else - builder.Append("Lua language server"); - - if (!string.IsNullOrWhiteSpace(code)) - { - builder.Append(" ("); - builder.Append(code.Trim()); - builder.Append(')'); - } - } + while (wordEnd < lineText.Length && IsDiagnosticSegmentCharacter(lineText[wordEnd])) + wordEnd++; - return builder.ToString(); - } + return wordEnd > wordStart; } - internal sealed class LuaPublishedDiagnostics + private static bool IsDiagnosticSegmentCharacter(char c) + => char.IsLetterOrDigit(c) || c == '_' || c == '.' || c == ':' || c == '\'' || c == '"'; + + private static TextEditorDiagnosticSeverity GetDiagnosticSeverity(JsonElement diagnosticElement) + => diagnosticElement.TryGetProperty("severity", out JsonElement severityElement) + && severityElement.TryGetInt32(out int severity) + && severity > 0 + ? (TextEditorDiagnosticSeverity)severity + : TextEditorDiagnosticSeverity.Warning; + + private static string BuildDiagnosticMessage(JsonElement diagnosticElement, TextEditorDiagnosticSeverity severity) { - public LuaPublishedDiagnostics(string filePath, IReadOnlyList diagnostics, int version) + string? message = diagnosticElement.TryGetProperty("message", out JsonElement messageElement) + ? messageElement.GetString()?.Trim() + : null; + + if (string.IsNullOrWhiteSpace(message)) + message = "Unknown Lua diagnostic."; + + var builder = new StringBuilder(); + builder.Append(severity.GetLabel()); + builder.Append(": "); + builder.Append(message); + + string? source = diagnosticElement.TryGetProperty("source", out JsonElement sourceElement) + ? sourceElement.GetString() + : null; + + string? code = diagnosticElement.TryGetProperty("code", out JsonElement codeElement) + ? codeElement.ValueKind == JsonValueKind.String + ? codeElement.GetString() + : codeElement.ValueKind == JsonValueKind.Number + ? codeElement.GetRawText() + : null + : null; + + if (!string.IsNullOrWhiteSpace(source) || !string.IsNullOrWhiteSpace(code)) { - FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); - Diagnostics = diagnostics ?? Array.Empty(); - Version = version; + builder.AppendLine(); + builder.AppendLine(); + builder.Append("Source: "); + + if (!string.IsNullOrWhiteSpace(source)) + builder.Append(source.Trim()); + else + builder.Append("Lua language server"); + + if (!string.IsNullOrWhiteSpace(code)) + { + builder.Append(" ("); + builder.Append(code.Trim()); + builder.Append(')'); + } } - public string FilePath { get; } - public IReadOnlyList Diagnostics { get; } - public int Version { get; } + return builder.ToString(); } -} \ No newline at end of file +} + +internal sealed class LuaPublishedDiagnostics(string filePath, IReadOnlyList diagnostics, int version) +{ + public string FilePath { get; } = filePath; + public IReadOnlyList Diagnostics { get; } = diagnostics ?? []; + public int Version { get; } = version; +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index 49086f5d89..9f36f35310 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -9,433 +11,451 @@ using TombLib.Scripting.Lua.Services; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider { - internal sealed class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider - { - private readonly string _workspaceRootDirectoryPath; - private readonly LuaLanguageServerClient _client; - private readonly LuaIntellisenseDocumentManager _documents = new(); - private readonly SemaphoreSlim _startLock = new(1, 1); + private readonly string _workspaceRootDirectoryPath; + private readonly LuaLanguageServerClient? _client; + private readonly LuaIntellisenseDocumentManager _documents = new(); + private readonly SemaphoreSlim _startLock = new(1, 1); - private bool _isDisposed; - private bool _startupSucceeded; + private bool _isDisposed; + private bool _startupSucceeded; - public bool IsAvailable => !_isDisposed && _client is not null; - public event Action> DiagnosticsUpdated; - public event Action> SemanticTokensUpdated; + public bool IsAvailable => !_isDisposed && _client is not null; - public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string serverExecutablePath) - { - _workspaceRootDirectoryPath = workspaceRootDirectoryPath is null - ? throw new ArgumentNullException(nameof(workspaceRootDirectoryPath)) - : LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); + public event Action>? DiagnosticsUpdated; - if (!string.IsNullOrWhiteSpace(serverExecutablePath)) - { - _client = new LuaLanguageServerClient(_workspaceRootDirectoryPath, serverExecutablePath, BuildLuaSettings); - _client.DiagnosticsPublished += HandleDiagnosticsPublished; - } - } + public event Action>? SemanticTokensUpdated; - public IReadOnlyList GetDiagnostics(string filePath) + public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string? serverExecutablePath) + { + _workspaceRootDirectoryPath = workspaceRootDirectoryPath is null + ? throw new ArgumentNullException(nameof(workspaceRootDirectoryPath)) + : LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); + + if (!string.IsNullOrWhiteSpace(serverExecutablePath)) { - if (_isDisposed) - return Array.Empty(); + _client = new LuaLanguageServerClient(_workspaceRootDirectoryPath, serverExecutablePath, BuildLuaSettings); + _client.DiagnosticsPublished += HandleDiagnosticsPublished; + } + } - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) - return Array.Empty(); + public IReadOnlyList GetDiagnostics(string filePath) + { + if (_isDisposed) + return []; - return _documents.GetDiagnostics(normalizedFilePath); - } + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return []; - public IReadOnlyList GetSemanticTokens(string filePath) - { - if (_isDisposed) - return Array.Empty(); + return _documents.GetDiagnostics(normalizedFilePath); + } - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) - return Array.Empty(); + public IReadOnlyList GetSemanticTokens(string filePath) + { + if (_isDisposed) + return []; - return _documents.GetSemanticTokens(normalizedFilePath); - } + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return []; - public void OpenDocument(string filePath, string content) - => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document open"); + return _documents.GetSemanticTokens(normalizedFilePath); + } - public void UpdateDocument(string filePath, string content) - => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document change"); + public void OpenDocument(string filePath, string content) + => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document open"); - public void CloseDocument(string filePath) - { - if (_isDisposed || _client is null || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) - return; + public void UpdateDocument(string filePath, string content) + => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document change"); - if (!_documents.TryClose(normalizedFilePath, out LuaDocumentSnapshot document)) - return; + public void CloseDocument(string filePath) + { + if (_isDisposed || _client is null || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return; - ObserveBackgroundTask(CloseDocumentAsync(document, CancellationToken.None), "Document close"); - } + if (!_documents.TryClose(normalizedFilePath, out LuaDocumentSnapshot? document)) + return; + + ObserveBackgroundTask(CloseDocumentAsync(document, CancellationToken.None), "Document close"); + } - public async Task> GetCompletionItemsAsync(string filePath, string content, - int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) + public async Task> GetCompletionItemsAsync(string filePath, string content, + int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) + { + LuaLanguageServerClient? client = _client; + + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || client is null + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) { - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) + return []; + } + + JsonElement response = await client.SendRequestAsync("textDocument/completion", + new { - return Array.Empty(); - } + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column }, + context = BuildCompletionContext(triggerCharacter) + }, cancellationToken).ConfigureAwait(false); - JsonElement response = await _client.SendRequestAsync("textDocument/completion", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column }, - context = BuildCompletionContext(triggerCharacter) - }, cancellationToken).ConfigureAwait(false); + IReadOnlyList itemElements = LuaLanguageServerResponseParser.ExtractCompletionItems(response); - IReadOnlyList itemElements = LuaLanguageServerResponseParser.ExtractCompletionItems(response); + if (itemElements.Count == 0) + return []; - if (itemElements.Count == 0) - return Array.Empty(); + return LuaLanguageServerResponseParser.ParseCompletionItems(itemElements, BuildCompletionItemResolveCallback); + } - return LuaLanguageServerResponseParser.ParseCompletionItems(itemElements, BuildCompletionItemResolveCallback); - } + private static object BuildCompletionContext(char? triggerCharacter) + => triggerCharacter is null + ? new { triggerKind = 1 } + : new { triggerKind = 2, triggerCharacter = triggerCharacter.ToString() }; - private static object BuildCompletionContext(char? triggerCharacter) - => triggerCharacter is null - ? new { triggerKind = 1 } - : new { triggerKind = 2, triggerCharacter = triggerCharacter.ToString() }; + private Func>? BuildCompletionItemResolveCallback(JsonElement itemElement, int itemIndex) + { + if (_client is null || !_client.SupportsCompletionResolve || !LuaLanguageServerResponseParser.CompletionItemNeedsResolve(itemElement)) + return null; - private Func> BuildCompletionItemResolveCallback(JsonElement itemElement, int itemIndex) - { - if (_client is null || !_client.SupportsCompletionResolve || !LuaLanguageServerResponseParser.CompletionItemNeedsResolve(itemElement)) - return null; + return cancellationToken => ResolveCompletionItemAsync(itemElement, itemIndex, cancellationToken); + } - return cancellationToken => ResolveCompletionItemAsync(itemElement, itemIndex, cancellationToken); - } + private async Task ResolveCompletionItemAsync(JsonElement itemElement, int itemIndex, CancellationToken cancellationToken) + { + LuaCompletionItem unresolvedItem = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, itemIndex) + ?? throw new InvalidOperationException("Completion item payload is missing a label."); + + if (_client is null || !_client.SupportsCompletionResolve) + return unresolvedItem; - private async Task ResolveCompletionItemAsync(JsonElement itemElement, int itemIndex, CancellationToken cancellationToken) + try { - LuaCompletionItem unresolvedItem = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, itemIndex); + LuaLanguageServerClient? client = _client; - if (_client is null || !_client.SupportsCompletionResolve) + if (client is null) return unresolvedItem; - try - { - JsonElement resolvedItem = await _client.SendRequestAsync("completionItem/resolve", itemElement, cancellationToken).ConfigureAwait(false); - - if (resolvedItem.ValueKind == JsonValueKind.Object) - { - LuaCompletionItem parsedItem = LuaLanguageServerResponseParser.ParseCompletionItem(resolvedItem, itemIndex); + JsonElement resolvedItem = await client.SendRequestAsync("completionItem/resolve", itemElement, cancellationToken).ConfigureAwait(false); - if (parsedItem is not null) - return parsedItem; - } - } - catch (OperationCanceledException) - { - throw; - } - catch + if (resolvedItem.ValueKind == JsonValueKind.Object) { - // Ignore - } + LuaCompletionItem? parsedItem = LuaLanguageServerResponseParser.ParseCompletionItem(resolvedItem, itemIndex); - return unresolvedItem; + if (parsedItem is not null) + return parsedItem; + } } - - public async Task GetHoverAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default) + catch (OperationCanceledException) { - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) - { - return null; - } + throw; + } + catch + { + // Ignore + } - JsonElement response = await _client.SendRequestAsync("textDocument/hover", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column } - }, cancellationToken).ConfigureAwait(false); + return unresolvedItem; + } - return LuaLanguageServerResponseParser.ParseHoverInfo(response); - } + public async Task GetHoverAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + LuaLanguageServerClient? client = _client; - public async Task GetDefinitionAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default) + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || client is null + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) { - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) + return null; + } + + JsonElement response = await client.SendRequestAsync("textDocument/hover", + new { - Debug.WriteLine($"[LuaLS] Definition request skipped because document sync failed for '{filePath}'."); - return null; - } + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column } + }, cancellationToken).ConfigureAwait(false); - JsonElement response = await _client.SendRequestAsync("textDocument/definition", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column } - }, cancellationToken).ConfigureAwait(false); + return LuaLanguageServerResponseParser.ParseHoverInfo(response); + } - return LuaLanguageServerResponseParser.ParseDefinitionLocation(response); - } + public async Task GetDefinitionAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + LuaLanguageServerClient? client = _client; - public async Task GetSignatureHelpAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default) + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || client is null + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) { - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) + Debug.WriteLine($"[LuaLS] Definition request skipped because document sync failed for '{filePath}'."); + return null; + } + + JsonElement response = await client.SendRequestAsync("textDocument/definition", + new { - return null; - } + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column } + }, cancellationToken).ConfigureAwait(false); - JsonElement response = await _client.SendRequestAsync("textDocument/signatureHelp", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column } - }, cancellationToken).ConfigureAwait(false); + return LuaLanguageServerResponseParser.ParseDefinitionLocation(response); + } - return LuaLanguageServerResponseParser.ParseSignatureHelp(response); - } + public async Task GetSignatureHelpAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + LuaLanguageServerClient? client = _client; - private async Task EnsureStartedAsync(CancellationToken cancellationToken) + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || client is null + || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) { - if (_client is null) - return false; + return null; + } - if (_startupSucceeded && _client.IsReady) - return true; + JsonElement response = await client.SendRequestAsync("textDocument/signatureHelp", + new + { + textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, + position = new { line, character = column } + }, cancellationToken).ConfigureAwait(false); - await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); + return LuaLanguageServerResponseParser.ParseSignatureHelp(response); + } - try - { - if (_startupSucceeded && _client.IsReady) - return true; + private async Task EnsureStartedAsync(CancellationToken cancellationToken) + { + if (_client is null) + return false; - if (_startupSucceeded && !_client.IsReady) - { - Debug.WriteLine("[LuaLS] Server connection dropped, restarting and reopening tracked documents."); - _documents.PrepareForRestart(); - } + if (_startupSucceeded && _client.IsReady) + return true; - _startupSucceeded = await _client.StartAsync(cancellationToken).ConfigureAwait(false); + await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); - if (!_startupSucceeded) - Debug.WriteLine("[LuaLS] Failed to start the Lua language server."); + try + { + if (_startupSucceeded && _client.IsReady) + return true; - return _startupSucceeded; - } - finally + if (_startupSucceeded && !_client.IsReady) { - _startLock.Release(); + Debug.WriteLine("[LuaLS] Server connection dropped, restarting and reopening tracked documents."); + _documents.PrepareForRestart(); } - } - private Task TrySynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) - { - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) - return Task.FromResult(false); + _startupSucceeded = await _client.StartAsync(cancellationToken).ConfigureAwait(false); - return SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken); - } + if (!_startupSucceeded) + Debug.WriteLine("[LuaLS] Failed to start the Lua language server."); - private async Task SynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) + return _startupSucceeded; + } + finally { - if (_isDisposed || string.IsNullOrWhiteSpace(filePath) || _client is null) - return false; + _startLock.Release(); + } + } - if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) - return false; + private Task TrySynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return Task.FromResult(false); - LuaDocumentSynchronizationRequest request = _documents.Synchronize(filePath, content); + return SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken); + } - if (request is null) - return true; + private async Task SynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) + { + if (_isDisposed || string.IsNullOrWhiteSpace(filePath) || _client is null) + return false; - try - { - if (request.Kind == LuaDocumentSynchronizationKind.Open) - { - await _client.SendNotificationAsync("textDocument/didOpen", - new - { - textDocument = new - { - uri = request.Document.Uri, - languageId = "lua", - version = request.Document.Version, - text = request.Document.Content - } - }, cancellationToken).ConfigureAwait(false); - } - else if (request.Kind == LuaDocumentSynchronizationKind.Change) - { - await _client.SendNotificationAsync("textDocument/didChange", - new - { - textDocument = new - { - uri = request.Document.Uri, - version = request.Document.Version - }, - contentChanges = new[] - { - new { text = request.Document.Content } - } - }, cancellationToken).ConfigureAwait(false); - } - - await RefreshSemanticTokensAsync(request.Document, cancellationToken).ConfigureAwait(false); - return true; - } - catch (OperationCanceledException) - { - throw; - } - catch (IOException) - { - return false; - } - catch (ObjectDisposedException) - { - return false; - } - } + if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) + return false; - private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) - { - if (_client is null || document is null || _client.SemanticTokenTypes.Count == 0) - return; + LuaDocumentSynchronizationRequest? request = _documents.Synchronize(filePath, content); + + if (request is null) + return true; - try + try + { + if (request.Kind == LuaDocumentSynchronizationKind.Open) { - JsonElement response = await _client.SendRequestAsync("textDocument/semanticTokens/range", + await _client.SendNotificationAsync("textDocument/didOpen", new { - textDocument = new { uri = document.Uri }, - range = BuildDocumentRange(document.Content) + textDocument = new + { + uri = request.Document.Uri, + languageId = "lua", + version = request.Document.Version, + text = request.Document.Content + } }, cancellationToken).ConfigureAwait(false); - - IReadOnlyList semanticTokens = LuaLanguageServerSemanticTokensParser.Parse( - response, - document, - _client.SemanticTokenTypes, - _client.SemanticTokenModifiers); - - if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, semanticTokens)) - return; - - SemanticTokensUpdated?.Invoke(document.FilePath, semanticTokens); } - catch + else if (request.Kind == LuaDocumentSynchronizationKind.Change) { - // Ignore semantic token failures and fall back to TextMate syntax highlighting. + await _client.SendNotificationAsync("textDocument/didChange", + new + { + textDocument = new + { + uri = request.Document.Uri, + version = request.Document.Version + }, + contentChanges = new[] + { + new { text = request.Document.Content } + } + }, cancellationToken).ConfigureAwait(false); } - } - private static object BuildDocumentRange(string content) + await RefreshSemanticTokensAsync(request.Document, cancellationToken).ConfigureAwait(false); + return true; + } + catch (OperationCanceledException) { - string normalizedContent = (content ?? string.Empty) - .Replace("\r\n", "\n", StringComparison.Ordinal) - .Replace('\r', '\n'); - - string[] lines = normalizedContent.Split('\n'); - int endLine = Math.Max(0, lines.Length - 1); - int endCharacter = lines.Length == 0 ? 0 : lines[endLine].Length; - - return new - { - start = new { line = 0, character = 0 }, - end = new { line = endLine, character = endCharacter } - }; + throw; + } + catch (IOException) + { + return false; } + catch (ObjectDisposedException) + { + return false; + } + } - private async Task CloseDocumentAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) + private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) + { + if (_client is null || _client.SemanticTokenTypes.Count == 0) + return; + + try { - if (_client is null) - return; + JsonElement response = await _client.SendRequestAsync("textDocument/semanticTokens/range", + new + { + textDocument = new { uri = document.Uri }, + range = BuildDocumentRange(document.Content) + }, cancellationToken).ConfigureAwait(false); - try - { - if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) - return; + IReadOnlyList semanticTokens = LuaLanguageServerSemanticTokensParser.Parse( + response, + document, + _client.SemanticTokenTypes, + _client.SemanticTokenModifiers); - await _client.SendNotificationAsync("textDocument/didClose", - new { textDocument = new { uri = document.Uri } }, cancellationToken).ConfigureAwait(false); - } - catch - { - // Ignore best-effort close failures. - } + if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, semanticTokens)) + return; + + SemanticTokensUpdated?.Invoke(document.FilePath, semanticTokens); } + catch + { + // Ignore semantic token failures and fall back to TextMate syntax highlighting. + } + } - private object BuildLuaSettings() - => LuaLanguageServerSettingsFactory.Create(_workspaceRootDirectoryPath); + private static object BuildDocumentRange(string? content) + { + string normalizedContent = (content ?? string.Empty) + .Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n'); - private void HandleDiagnosticsPublished(JsonElement parameters) - { - if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters, out string filePath)) - { - Debug.WriteLine("[LuaLS] Diagnostics could not be matched to a local file path."); - return; - } + string[] lines = normalizedContent.Split('\n'); + int endLine = Math.Max(0, lines.Length - 1); + int endCharacter = lines.Length == 0 ? 0 : lines[endLine].Length; - LuaDocumentSnapshot document = _documents.GetDocumentSnapshot(filePath); + return new + { + start = new { line = 0, character = 0 }, + end = new { line = endLine, character = endCharacter } + }; + } - if (!LuaLanguageServerDiagnosticsParser.TryParse(parameters, filePath, - document?.Content, document?.Version ?? 0, out LuaPublishedDiagnostics publishedDiagnostics)) - { - Debug.WriteLine($"[LuaLS] Diagnostics payload could not be parsed for '{filePath}'."); - return; - } + private async Task CloseDocumentAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) + { + if (_client is null) + return; - if (!_documents.TryStoreDiagnostics(publishedDiagnostics)) + try + { + if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) return; - DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); + await _client.SendNotificationAsync("textDocument/didClose", + new { textDocument = new { uri = document.Uri } }, cancellationToken).ConfigureAwait(false); } + catch + { + // Ignore best-effort close failures. + } + } - private static void ObserveBackgroundTask(Task task, string operation) - => _ = ObserveBackgroundTaskAsync(task, operation); + private object BuildLuaSettings() + => LuaLanguageServerSettingsFactory.Create(_workspaceRootDirectoryPath); - private static async Task ObserveBackgroundTaskAsync(Task task, string operation) + private void HandleDiagnosticsPublished(JsonElement parameters) + { + if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters, out string filePath)) { - try - { - await task.ConfigureAwait(false); - } - catch (OperationCanceledException) - { - } - catch (IOException) - { - } - catch (ObjectDisposedException) - { - } - catch (Exception exception) - { - Debug.WriteLine($"[LuaLS] {operation} failed: {exception}"); - } + Debug.WriteLine("[LuaLS] Diagnostics could not be matched to a local file path."); + return; } - public void Dispose() + LuaDocumentSnapshot? document = _documents.GetDocumentSnapshot(filePath); + + if (!LuaLanguageServerDiagnosticsParser.TryParse(parameters, filePath, + document?.Content, document?.Version ?? 0, out LuaPublishedDiagnostics? publishedDiagnostics)) { - if (_isDisposed) - return; + Debug.WriteLine($"[LuaLS] Diagnostics payload could not be parsed for '{filePath}'."); + return; + } + + if (!_documents.TryStoreDiagnostics(publishedDiagnostics)) + return; - _isDisposed = true; - if (_client is not null) - _client.DiagnosticsPublished -= HandleDiagnosticsPublished; - _startLock.Dispose(); - _client?.Dispose(); + DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); + } + + private static void ObserveBackgroundTask(Task task, string operation) + => _ = ObserveBackgroundTaskAsync(task, operation); + + private static async Task ObserveBackgroundTaskAsync(Task task, string operation) + { + try + { + await task.ConfigureAwait(false); + } + catch (OperationCanceledException) + { } + catch (IOException) + { } + catch (ObjectDisposedException) + { } + catch (Exception exception) + { + Debug.WriteLine($"[LuaLS] {operation} failed: {exception}"); } } -} \ No newline at end of file + + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + + if (_client is not null) + _client.DiagnosticsPublished -= HandleDiagnosticsPublished; + + _startLock.Dispose(); + _client?.Dispose(); + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs index 58c73878b8..137cbcd6b2 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs @@ -1,18 +1,23 @@ +#nullable enable + using System.IO; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static class LuaLanguageServerLocator { - internal static class LuaLanguageServerLocator - { - private const string ExecutableFileName = "lua-language-server.exe"; + private const string ExecutableFileName = "lua-language-server.exe"; - public static string ResolveExecutablePath() - { - string bundledExecutablePath = Path.Combine(DefaultPaths.TIDEDirectory, "LuaLS", "bin", ExecutableFileName); + /// + /// Resolves the bundled Lua language server executable when it is installed with TombIDE. + /// + /// The bundled executable path, or when it is unavailable. + public static string? ResolveExecutablePath() + { + string bundledExecutablePath = Path.Combine(DefaultPaths.TIDEDirectory, "LuaLS", "bin", ExecutableFileName); - return !string.IsNullOrWhiteSpace(bundledExecutablePath) && File.Exists(bundledExecutablePath) - ? bundledExecutablePath - : null; - } + return !string.IsNullOrWhiteSpace(bundledExecutablePath) && File.Exists(bundledExecutablePath) + ? bundledExecutablePath + : null; } -} \ No newline at end of file +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs index c46991b421..f7ad81e540 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs @@ -1,83 +1,110 @@ +#nullable enable + using System; using System.IO; using System.Text.Json; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static class LuaLanguageServerPathHelper { - internal static class LuaLanguageServerPathHelper + /// + /// Converts a local file path into a normalized file URI for LuaLS requests. + /// + /// The local file path to convert. + /// The absolute file URI. + public static string CreateFileUri(string filePath) + => new Uri(NormalizeLocalPath(filePath)).AbsoluteUri; + + /// + /// Normalizes a local path into the absolute form used by the language server. + /// + /// The path to normalize. + /// The normalized absolute path. + public static string NormalizeLocalPath(string filePath) { - public static string CreateFileUri(string filePath) - => new Uri(NormalizeLocalPath(filePath)).AbsoluteUri; + if (string.IsNullOrWhiteSpace(filePath)) + throw new ArgumentException("File path must not be empty.", nameof(filePath)); - public static string NormalizeLocalPath(string filePath) + string sanitizedFilePath = filePath.Replace('/', Path.DirectorySeparatorChar); + return Path.GetFullPath(sanitizedFilePath); + } + + public static string NormalizeLocalPath(Uri uri) + { + string localPath = uri.LocalPath; + + // On Windows, Uri.LocalPath may produce "/C:/..." which needs the leading slash trimmed. + if (Path.DirectorySeparatorChar == '\\' + && localPath.Length >= 3 + && localPath[0] == '/' + && char.IsLetter(localPath[1]) + && localPath[2] == ':') { - if (string.IsNullOrWhiteSpace(filePath)) - throw new ArgumentException("File path must not be empty.", nameof(filePath)); + localPath = localPath[1..]; + } + + return NormalizeLocalPath(localPath); + } + + /// + /// Attempts to normalize a local path without throwing for invalid input. + /// + /// The path to normalize. + /// The normalized absolute path when successful. + /// when normalization succeeded; otherwise, . + public static bool TryNormalizeLocalPath(string filePath, out string normalizedFilePath) + { + normalizedFilePath = string.Empty; + + if (string.IsNullOrWhiteSpace(filePath)) + return false; - string sanitizedFilePath = filePath.Replace('/', Path.DirectorySeparatorChar); - return Path.GetFullPath(sanitizedFilePath); + try + { + normalizedFilePath = NormalizeLocalPath(filePath); + return true; } + catch + { + return false; + } + } - public static string NormalizeLocalPath(Uri uri) + /// + /// Attempts to extract and normalize a local file path from an LSP payload. + /// + /// The JSON payload containing the document URI. + /// The normalized local file path when successful. + /// when a local file path was resolved; otherwise, . + public static bool TryGetFilePath(JsonElement parameters, out string filePath) + { + filePath = string.Empty; + + if (parameters.ValueKind != JsonValueKind.Object + || !parameters.TryGetProperty("uri", out JsonElement uriElement)) { - if (uri is null) - throw new ArgumentNullException(nameof(uri)); - - string localPath = uri.LocalPath; - - // On Windows, Uri.LocalPath may produce "/C:/..." which needs the leading slash trimmed. - if (Path.DirectorySeparatorChar == '\\' - && localPath.Length >= 3 - && localPath[0] == '/' - && char.IsLetter(localPath[1]) - && localPath[2] == ':') - { - localPath = localPath[1..]; - } - - return NormalizeLocalPath(localPath); + return false; } - public static bool TryNormalizeLocalPath(string filePath, out string normalizedFilePath) + string? uriText = uriElement.GetString(); + + if (string.IsNullOrWhiteSpace(uriText) + || !Uri.TryCreate(uriText, UriKind.Absolute, out Uri? uri) + || uri is null + || !uri.IsFile) { - normalizedFilePath = null; - - if (string.IsNullOrWhiteSpace(filePath)) - return false; - - try - { - normalizedFilePath = NormalizeLocalPath(filePath); - return true; - } - catch - { - return false; - } + return false; } - public static bool TryGetFilePath(JsonElement parameters, out string filePath) + try + { + filePath = NormalizeLocalPath(uri); + return true; + } + catch { - filePath = null; - - if (parameters.ValueKind != JsonValueKind.Object - || !parameters.TryGetProperty("uri", out JsonElement uriElement) - || string.IsNullOrWhiteSpace(uriElement.GetString()) - || !Uri.TryCreate(uriElement.GetString(), UriKind.Absolute, out Uri uri) - || !uri.IsFile) - { - return false; - } - - try - { - filePath = NormalizeLocalPath(uri); - return true; - } - catch - { - return false; - } + return false; } } -} \ No newline at end of file +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs index 817b3c3cbc..d25ee1c548 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -1,5 +1,8 @@ +#nullable enable + using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text; using System.Text.Json; @@ -7,580 +10,591 @@ using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static class LuaLanguageServerResponseParser { - internal static class LuaLanguageServerResponseParser + private enum LuaLanguageServerCompletionKind { - private enum LuaLanguageServerCompletionKind - { - Text = 1, - Method = 2, - Function = 3, - Constructor = 4, - Field = 5, - Variable = 6, - Class = 7, - Interface = 8, - Module = 9, - Property = 10, - Unit = 11, - Value = 12, - Enum = 13, - Keyword = 14, - Snippet = 15, - Color = 16, - File = 17, - Reference = 18, - Folder = 19, - EnumMember = 20, - Constant = 21, - Struct = 22, - Event = 23, - Operator = 24, - TypeParameter = 25 - } + Text = 1, + Method = 2, + Function = 3, + Constructor = 4, + Field = 5, + Variable = 6, + Class = 7, + Interface = 8, + Module = 9, + Property = 10, + Unit = 11, + Value = 12, + Enum = 13, + Keyword = 14, + Snippet = 15, + Color = 16, + File = 17, + Reference = 18, + Folder = 19, + EnumMember = 20, + Constant = 21, + Struct = 22, + Event = 23, + Operator = 24, + TypeParameter = 25 + } - private readonly struct MarkupContent - { - public MarkupContent(string text, bool isMarkdown) - { - Text = text; - IsMarkdown = isMarkdown; - } + private readonly struct MarkupContent(string? text, bool isMarkdown) + { + public string Text { get; } = text ?? string.Empty; + public bool IsMarkdown { get; } = isMarkdown; + } - public string Text { get; } - public bool IsMarkdown { get; } - } + /// + /// Parses completion entries from a LuaLS completion response. + /// + public static IReadOnlyList ParseCompletionItems(JsonElement response) + => ParseCompletionItems(ExtractCompletionItems(response)); - public static IReadOnlyList ParseCompletionItems(JsonElement response) - => ParseCompletionItems(ExtractCompletionItems(response)); + public static IReadOnlyList ExtractCompletionItems(JsonElement response) + { + JsonElement itemsElement = response; - public static IReadOnlyList ExtractCompletionItems(JsonElement response) - { - JsonElement itemsElement = response; + if (response.ValueKind == JsonValueKind.Object && response.TryGetProperty("items", out JsonElement completionItemsElement)) + itemsElement = completionItemsElement; - if (response.ValueKind == JsonValueKind.Object && response.TryGetProperty("items", out JsonElement completionItemsElement)) - itemsElement = completionItemsElement; + if (itemsElement.ValueKind != JsonValueKind.Array) + return []; - if (itemsElement.ValueKind != JsonValueKind.Array) - return Array.Empty(); + var itemElements = new List(); - var itemElements = new List(); + foreach (JsonElement itemElement in itemsElement.EnumerateArray()) + itemElements.Add(itemElement.Clone()); - foreach (JsonElement itemElement in itemsElement.EnumerateArray()) - itemElements.Add(itemElement.Clone()); + return itemElements; + } - return itemElements; - } + public static IReadOnlyList ParseCompletionItems(IEnumerable itemElements, + Func>?>? resolveFactory = null) + { + var items = new List(); + int itemIndex = 0; - public static IReadOnlyList ParseCompletionItems(IEnumerable itemElements, - Func>> resolveFactory = null) + foreach (JsonElement itemElement in itemElements) { - var items = new List(); - int itemIndex = 0; + LuaCompletionItem? item = ParseCompletionItem(itemElement, itemIndex, resolveFactory?.Invoke(itemElement, itemIndex)); - foreach (JsonElement itemElement in itemElements) - { - LuaCompletionItem item = ParseCompletionItem(itemElement, itemIndex, resolveFactory?.Invoke(itemElement, itemIndex)); + if (item is not null) + items.Add(item); - if (item is not null) - items.Add(item); + itemIndex++; + } - itemIndex++; - } + return [.. items + .GroupBy(item => $"{item.Label}\0{item.InsertText}", StringComparer.OrdinalIgnoreCase) + .Select(group => group.First())]; + } - return items - .GroupBy(item => $"{item.Label}\0{item.InsertText}", StringComparer.OrdinalIgnoreCase) - .Select(group => group.First()) - .ToList(); - } + public static bool CompletionItemNeedsResolve(JsonElement itemElement) + => string.IsNullOrWhiteSpace(BuildCompletionDetail(itemElement)) + || string.IsNullOrWhiteSpace(BuildCompletionDescription(itemElement).Text); - public static bool CompletionItemNeedsResolve(JsonElement itemElement) - => string.IsNullOrWhiteSpace(BuildCompletionDetail(itemElement)) - || string.IsNullOrWhiteSpace(BuildCompletionDescription(itemElement).Text); + public static LuaCompletionItem? ParseCompletionItem(JsonElement itemElement, int itemIndex, + Func>? resolveAsync = null) + { + if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) + return null; - public static LuaCompletionItem ParseCompletionItem(JsonElement itemElement, int itemIndex, - Func> resolveAsync = null) - { - if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) - return null; + string? label = labelElement.GetString(); - string label = labelElement.GetString(); - string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) - && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) - ? newTextElement.GetString() - : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) - ? insertTextElement.GetString() - : label; + if (string.IsNullOrWhiteSpace(label)) + return null; - if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) - && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) - { - insertText = StripSnippetPlaceholders(insertText); - } + string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) + && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) + ? newTextElement.GetString() ?? label + : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) + ? insertTextElement.GetString() ?? label + : label; - string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) - ? filterTextElement.GetString() - : label; - - LuaLanguageServerCompletionKind completionKind = TryReadCompletionKind(itemElement, out LuaLanguageServerCompletionKind parsedCompletionKind) - ? parsedCompletionKind - : LuaLanguageServerCompletionKind.Text; - - string detail = BuildCompletionDetail(itemElement); - MarkupContent description = BuildCompletionDescription(itemElement); - string searchableDescription = NormalizeMarkupText(description.Text); - - return new LuaCompletionItem( - label, - insertText, - detail, - description.Text, - filterText, - BuildCompletionPriority(itemElement, detail, searchableDescription, itemIndex), - BuildCompletionIconKind(completionKind, detail), - description.IsMarkdown, - resolveAsync); + if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) + && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) + { + insertText = StripSnippetPlaceholders(insertText); } - private static double BuildCompletionPriority(JsonElement itemElement, string detail, string description, int itemIndex) - { - const double preselectedBonus = 1000000.0; - const double responseOrderWeight = 100000.0; - const double localScopeBonus = 20000.0; - const double upvalueOrParameterBonus = 15000.0; - const double variableKindBonus = 10000.0; - const double fieldOrPropertyKindBonus = 9000.0; - const double methodOrFunctionKindBonus = 7000.0; - const double keywordKindPenalty = -5000.0; - - double priority = responseOrderWeight - itemIndex; - string searchableText = CombineCompletionText(detail, description); - - if (itemElement.TryGetProperty("preselect", out JsonElement preselectElement) - && preselectElement.ValueKind == JsonValueKind.True) - { - priority += preselectedBonus; - } + string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) + ? filterTextElement.GetString() ?? label + : label; + + LuaLanguageServerCompletionKind completionKind = TryReadCompletionKind(itemElement, out LuaLanguageServerCompletionKind parsedCompletionKind) + ? parsedCompletionKind + : LuaLanguageServerCompletionKind.Text; + + string? detail = BuildCompletionDetail(itemElement); + MarkupContent description = BuildCompletionDescription(itemElement); + string? searchableDescription = NormalizeMarkupText(description.Text); + + return new LuaCompletionItem( + label, + insertText, + detail, + description.Text, + filterText, + BuildCompletionPriority(itemElement, detail, searchableDescription, itemIndex), + BuildCompletionIconKind(completionKind, detail), + description.IsMarkdown, + resolveAsync); + } - if (itemElement.TryGetProperty("kind", out JsonElement kindElement) - && kindElement.TryGetInt32(out int completionKind)) - { - priority += completionKind switch - { - (int)LuaLanguageServerCompletionKind.Variable => variableKindBonus, - (int)LuaLanguageServerCompletionKind.Field => fieldOrPropertyKindBonus, - (int)LuaLanguageServerCompletionKind.Property => fieldOrPropertyKindBonus, - (int)LuaLanguageServerCompletionKind.Method => methodOrFunctionKindBonus, - (int)LuaLanguageServerCompletionKind.Function => methodOrFunctionKindBonus, - (int)LuaLanguageServerCompletionKind.Keyword => keywordKindPenalty, - _ => 0.0 - }; - } + private static double BuildCompletionPriority(JsonElement itemElement, string? detail, string? description, int itemIndex) + { + const double preselectedBonus = 1000000.0; + const double responseOrderWeight = 100000.0; + const double localScopeBonus = 20000.0; + const double upvalueOrParameterBonus = 15000.0; + const double variableKindBonus = 10000.0; + const double fieldOrPropertyKindBonus = 9000.0; + const double methodOrFunctionKindBonus = 7000.0; + const double keywordKindPenalty = -5000.0; + + double priority = responseOrderWeight - itemIndex; + string? searchableText = CombineCompletionText(detail, description); + + if (itemElement.TryGetProperty("preselect", out JsonElement preselectElement) + && preselectElement.ValueKind == JsonValueKind.True) + { + priority += preselectedBonus; + } - if (!string.IsNullOrWhiteSpace(searchableText)) + if (itemElement.TryGetProperty("kind", out JsonElement kindElement) + && kindElement.TryGetInt32(out int completionKind)) + { + priority += completionKind switch { - if (CompletionTextContains(searchableText, "local")) - priority += localScopeBonus; - - if (CompletionTextContains(searchableText, "upvalue") - || CompletionTextContains(searchableText, "parameter")) - { - priority += upvalueOrParameterBonus; - } - } - - return priority; + (int)LuaLanguageServerCompletionKind.Variable => variableKindBonus, + (int)LuaLanguageServerCompletionKind.Field => fieldOrPropertyKindBonus, + (int)LuaLanguageServerCompletionKind.Property => fieldOrPropertyKindBonus, + (int)LuaLanguageServerCompletionKind.Method => methodOrFunctionKindBonus, + (int)LuaLanguageServerCompletionKind.Function => methodOrFunctionKindBonus, + (int)LuaLanguageServerCompletionKind.Keyword => keywordKindPenalty, + _ => 0.0 + }; } - private static bool TryReadCompletionKind(JsonElement itemElement, out LuaLanguageServerCompletionKind kind) + if (!string.IsNullOrWhiteSpace(searchableText)) { - kind = LuaLanguageServerCompletionKind.Text; + if (CompletionTextContains(searchableText, "local")) + priority += localScopeBonus; - if (!itemElement.TryGetProperty("kind", out JsonElement kindElement) - || !kindElement.TryGetInt32(out int rawKind) - || !Enum.IsDefined(typeof(LuaLanguageServerCompletionKind), rawKind)) + if (CompletionTextContains(searchableText, "upvalue") + || CompletionTextContains(searchableText, "parameter")) { - return false; + priority += upvalueOrParameterBonus; } - - kind = (LuaLanguageServerCompletionKind)rawKind; - return true; } - private static LuaCompletionIconKind BuildCompletionIconKind(LuaLanguageServerCompletionKind kind, string detail) - { - if (CompletionTextContains(detail, "parameter")) - return LuaCompletionIconKind.Parameter; + return priority; + } - if (CompletionTextContains(detail, "module") || CompletionTextContains(detail, "namespace")) - return LuaCompletionIconKind.Namespace; + private static bool TryReadCompletionKind(JsonElement itemElement, out LuaLanguageServerCompletionKind kind) + { + kind = LuaLanguageServerCompletionKind.Text; - if (CompletionTextContains(detail, "method") || CompletionTextContains(detail, "function")) - return LuaCompletionIconKind.Method; + if (!itemElement.TryGetProperty("kind", out JsonElement kindElement) + || !kindElement.TryGetInt32(out int rawKind) + || !Enum.IsDefined(typeof(LuaLanguageServerCompletionKind), rawKind)) + { + return false; + } - if (CompletionTextContains(detail, "field")) - return LuaCompletionIconKind.Field; + kind = (LuaLanguageServerCompletionKind)rawKind; + return true; + } - if (CompletionTextContains(detail, "property") || CompletionTextContains(detail, "global") - || CompletionTextContains(detail, "default library")) - { - return LuaCompletionIconKind.Property; - } + private static LuaCompletionIconKind BuildCompletionIconKind(LuaLanguageServerCompletionKind kind, string? detail) + { + if (CompletionTextContains(detail, "parameter")) + return LuaCompletionIconKind.Parameter; - if (CompletionTextContains(detail, "constant")) - return LuaCompletionIconKind.Constant; + if (CompletionTextContains(detail, "module") || CompletionTextContains(detail, "namespace")) + return LuaCompletionIconKind.Namespace; - if (CompletionTextContains(detail, "keyword")) - return LuaCompletionIconKind.Keyword; + if (CompletionTextContains(detail, "method") || CompletionTextContains(detail, "function")) + return LuaCompletionIconKind.Method; - if (CompletionTextContains(detail, "class") || CompletionTextContains(detail, "interface") - || CompletionTextContains(detail, "enum") || CompletionTextContains(detail, "struct")) - { - return LuaCompletionIconKind.Class; - } + if (CompletionTextContains(detail, "field")) + return LuaCompletionIconKind.Field; - return kind switch - { - LuaLanguageServerCompletionKind.Method => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Function => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Constructor => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Field => LuaCompletionIconKind.Field, - LuaLanguageServerCompletionKind.Variable => LuaCompletionIconKind.Variable, - LuaLanguageServerCompletionKind.Class => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Interface => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Module => LuaCompletionIconKind.Namespace, - LuaLanguageServerCompletionKind.Property => LuaCompletionIconKind.Property, - LuaLanguageServerCompletionKind.Value => LuaCompletionIconKind.Variable, - LuaLanguageServerCompletionKind.Enum => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Keyword => LuaCompletionIconKind.Keyword, - LuaLanguageServerCompletionKind.Snippet => LuaCompletionIconKind.Keyword, - LuaLanguageServerCompletionKind.File => LuaCompletionIconKind.File, - LuaLanguageServerCompletionKind.Reference => LuaCompletionIconKind.Variable, - LuaLanguageServerCompletionKind.Folder => LuaCompletionIconKind.Folder, - LuaLanguageServerCompletionKind.EnumMember => LuaCompletionIconKind.Constant, - LuaLanguageServerCompletionKind.Constant => LuaCompletionIconKind.Constant, - LuaLanguageServerCompletionKind.Struct => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Event => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Operator => LuaCompletionIconKind.Keyword, - LuaLanguageServerCompletionKind.TypeParameter => LuaCompletionIconKind.Class, - _ => LuaCompletionIconKind.Misc - }; + if (CompletionTextContains(detail, "property") || CompletionTextContains(detail, "global") + || CompletionTextContains(detail, "default library")) + { + return LuaCompletionIconKind.Property; } - public static LuaHoverInfo ParseHoverInfo(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) - return null; + if (CompletionTextContains(detail, "constant")) + return LuaCompletionIconKind.Constant; - MarkupContent hoverContent = ExtractMarkupContent(contentsElement); + if (CompletionTextContains(detail, "keyword")) + return LuaCompletionIconKind.Keyword; - return string.IsNullOrWhiteSpace(hoverContent.Text) - ? null - : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); + if (CompletionTextContains(detail, "class") || CompletionTextContains(detail, "interface") + || CompletionTextContains(detail, "enum") || CompletionTextContains(detail, "struct")) + { + return LuaCompletionIconKind.Class; } - public static LuaDefinitionLocation ParseDefinitionLocation(JsonElement response) + return kind switch { - JsonElement definitionElement = response; + LuaLanguageServerCompletionKind.Method => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Function => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Constructor => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Field => LuaCompletionIconKind.Field, + LuaLanguageServerCompletionKind.Variable => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Class => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Interface => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Module => LuaCompletionIconKind.Namespace, + LuaLanguageServerCompletionKind.Property => LuaCompletionIconKind.Property, + LuaLanguageServerCompletionKind.Value => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Enum => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Keyword => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.Snippet => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.File => LuaCompletionIconKind.File, + LuaLanguageServerCompletionKind.Reference => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Folder => LuaCompletionIconKind.Folder, + LuaLanguageServerCompletionKind.EnumMember => LuaCompletionIconKind.Constant, + LuaLanguageServerCompletionKind.Constant => LuaCompletionIconKind.Constant, + LuaLanguageServerCompletionKind.Struct => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Event => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Operator => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.TypeParameter => LuaCompletionIconKind.Class, + _ => LuaCompletionIconKind.Misc + }; + } - if (response.ValueKind == JsonValueKind.Array) - { - definitionElement = response.EnumerateArray().FirstOrDefault(); + /// + /// Parses hover content from a LuaLS hover response. + /// + public static LuaHoverInfo? ParseHoverInfo(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) + return null; - if (definitionElement.ValueKind == JsonValueKind.Undefined) - return null; - } + MarkupContent hoverContent = ExtractMarkupContent(contentsElement); - if (definitionElement.ValueKind != JsonValueKind.Object) - return null; + return string.IsNullOrWhiteSpace(hoverContent.Text) + ? null + : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); + } - string uri = definitionElement.TryGetProperty("targetUri", out JsonElement targetUriElement) - ? targetUriElement.GetString() - : definitionElement.TryGetProperty("uri", out JsonElement uriElement) - ? uriElement.GetString() - : null; + /// + /// Parses a definition location from a LuaLS definition response. + /// + public static LuaDefinitionLocation? ParseDefinitionLocation(JsonElement response) + { + JsonElement definitionElement = response; - if (string.IsNullOrWhiteSpace(uri) || !Uri.TryCreate(uri, UriKind.Absolute, out Uri parsedUri) || !parsedUri.IsFile) - return null; + if (response.ValueKind == JsonValueKind.Array) + { + definitionElement = response.EnumerateArray().FirstOrDefault(); - JsonElement startElement = definitionElement.TryGetProperty("targetSelectionRange", out JsonElement targetSelectionRangeElement) - && targetSelectionRangeElement.TryGetProperty("start", out JsonElement targetSelectionStartElement) - ? targetSelectionStartElement - : definitionElement.TryGetProperty("targetRange", out JsonElement targetRangeElement) - && targetRangeElement.TryGetProperty("start", out JsonElement targetRangeStartElement) - ? targetRangeStartElement - : definitionElement.TryGetProperty("range", out JsonElement rangeElement) - && rangeElement.TryGetProperty("start", out JsonElement rangeStartElement) - ? rangeStartElement - : default; - - if (startElement.ValueKind != JsonValueKind.Object) + if (definitionElement.ValueKind == JsonValueKind.Undefined) return null; - - int lineNumber = startElement.TryGetProperty("line", out JsonElement lineElement) ? lineElement.GetInt32() + 1 : 1; - int columnNumber = startElement.TryGetProperty("character", out JsonElement characterElement) ? characterElement.GetInt32() + 1 : 1; - - return new LuaDefinitionLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), lineNumber, columnNumber); } - public static LuaSignatureInfo ParseSignatureHelp(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object - || !response.TryGetProperty("signatures", out JsonElement signaturesElement) - || signaturesElement.ValueKind != JsonValueKind.Array) - { - return null; - } - - int activeSignature = response.TryGetProperty("activeSignature", out JsonElement activeSignatureElement) - && activeSignatureElement.TryGetInt32(out int parsedActiveSignature) - ? Math.Max(0, parsedActiveSignature) - : 0; + if (definitionElement.ValueKind != JsonValueKind.Object) + return null; - int signatureIndex = 0; - JsonElement signatureElement = default; + string? uri = definitionElement.TryGetProperty("targetUri", out JsonElement targetUriElement) + ? targetUriElement.GetString() + : definitionElement.TryGetProperty("uri", out JsonElement uriElement) + ? uriElement.GetString() + : null; - foreach (JsonElement candidate in signaturesElement.EnumerateArray()) - { - if (signatureIndex == activeSignature) - { - signatureElement = candidate; - break; - } + if (string.IsNullOrWhiteSpace(uri) || !Uri.TryCreate(uri, UriKind.Absolute, out Uri? parsedUri) + || parsedUri is null || !parsedUri.IsFile) + { + return null; + } - signatureIndex++; - } + JsonElement startElement = definitionElement.TryGetProperty("targetSelectionRange", out JsonElement targetSelectionRangeElement) + && targetSelectionRangeElement.TryGetProperty("start", out JsonElement targetSelectionStartElement) + ? targetSelectionStartElement + : definitionElement.TryGetProperty("targetRange", out JsonElement targetRangeElement) + && targetRangeElement.TryGetProperty("start", out JsonElement targetRangeStartElement) + ? targetRangeStartElement + : definitionElement.TryGetProperty("range", out JsonElement rangeElement) + && rangeElement.TryGetProperty("start", out JsonElement rangeStartElement) + ? rangeStartElement + : default; - if (signatureElement.ValueKind != JsonValueKind.Object - || !signatureElement.TryGetProperty("label", out JsonElement labelElement)) - { - return null; - } + if (startElement.ValueKind != JsonValueKind.Object) + return null; - string label = labelElement.GetString(); + int lineNumber = startElement.TryGetProperty("line", out JsonElement lineElement) ? lineElement.GetInt32() + 1 : 1; + int columnNumber = startElement.TryGetProperty("character", out JsonElement characterElement) ? characterElement.GetInt32() + 1 : 1; - if (string.IsNullOrWhiteSpace(label)) - return null; + return new LuaDefinitionLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), lineNumber, columnNumber); + } - string documentation = signatureElement.TryGetProperty("documentation", out JsonElement documentationElement) - ? ExtractMarkupText(documentationElement) - : null; + /// + /// Parses signature help metadata from a LuaLS signature-help response. + /// + public static LuaSignatureInfo? ParseSignatureHelp(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object + || !response.TryGetProperty("signatures", out JsonElement signaturesElement) + || signaturesElement.ValueKind != JsonValueKind.Array) + { + return null; + } - int activeParameter = response.TryGetProperty("activeParameter", out JsonElement activeParameterElement) - && activeParameterElement.TryGetInt32(out int parsedActiveParameter) - ? Math.Max(0, parsedActiveParameter) - : signatureElement.TryGetProperty("activeParameter", out JsonElement signatureActiveParameterElement) - && signatureActiveParameterElement.TryGetInt32(out int parsedSignatureActiveParameter) - ? Math.Max(0, parsedSignatureActiveParameter) - : 0; + int activeSignature = response.TryGetProperty("activeSignature", out JsonElement activeSignatureElement) + && activeSignatureElement.TryGetInt32(out int parsedActiveSignature) + ? Math.Max(0, parsedActiveSignature) + : 0; - var parameters = new List(); + int signatureIndex = 0; + JsonElement signatureElement = default; - if (signatureElement.TryGetProperty("parameters", out JsonElement parametersElement) - && parametersElement.ValueKind == JsonValueKind.Array) + foreach (JsonElement candidate in signaturesElement.EnumerateArray()) + { + if (signatureIndex == activeSignature) { - foreach (JsonElement paramElement in parametersElement.EnumerateArray()) - { - string parameterLabel = paramElement.TryGetProperty("label", out JsonElement paramLabelElement) - ? paramLabelElement.ValueKind == JsonValueKind.String - ? paramLabelElement.GetString() - : TryExtractParameterLabel(label, paramLabelElement, out string extractedLabel) - ? extractedLabel - : null - : null; - - string parameterDocumentation = paramElement.TryGetProperty("documentation", out JsonElement parameterDocumentationElement) - ? ExtractMarkupText(parameterDocumentationElement) - : null; - - parameters.Add(new LuaParameterInfo(parameterLabel, parameterDocumentation)); - } + signatureElement = candidate; + break; } - return new LuaSignatureInfo(label, documentation, parameters, activeParameter); + signatureIndex++; } - private static string BuildCompletionDetail(JsonElement itemElement) + if (signatureElement.ValueKind != JsonValueKind.Object + || !signatureElement.TryGetProperty("label", out JsonElement labelElement)) { - if (!itemElement.TryGetProperty("detail", out JsonElement detailElement)) - return null; - - string detail = detailElement.GetString(); - return string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); + return null; } - private static MarkupContent BuildCompletionDescription(JsonElement itemElement) - { - if (!itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) - return default; + string? label = labelElement.GetString(); - MarkupContent documentation = ExtractMarkupContent(documentationElement); + if (string.IsNullOrWhiteSpace(label)) + return null; - if (string.IsNullOrWhiteSpace(documentation.Text)) - return default; + string? documentation = signatureElement.TryGetProperty("documentation", out JsonElement documentationElement) + ? ExtractMarkupText(documentationElement) + : null; - string normalizedText = documentation.IsMarkdown - ? NormalizeMarkdownText(documentation.Text) - : NormalizeMarkupText(documentation.Text); + int activeParameter = response.TryGetProperty("activeParameter", out JsonElement activeParameterElement) + && activeParameterElement.TryGetInt32(out int parsedActiveParameter) + ? Math.Max(0, parsedActiveParameter) + : signatureElement.TryGetProperty("activeParameter", out JsonElement signatureActiveParameterElement) + && signatureActiveParameterElement.TryGetInt32(out int parsedSignatureActiveParameter) + ? Math.Max(0, parsedSignatureActiveParameter) + : 0; - return string.IsNullOrWhiteSpace(normalizedText) - ? default - : new MarkupContent(normalizedText, documentation.IsMarkdown); - } + var parameters = new List(); - private static string CombineCompletionText(string detail, string description) + if (signatureElement.TryGetProperty("parameters", out JsonElement parametersElement) + && parametersElement.ValueKind == JsonValueKind.Array) { - if (string.IsNullOrWhiteSpace(detail)) - return description; + foreach (JsonElement paramElement in parametersElement.EnumerateArray()) + { + string? parameterLabel = paramElement.TryGetProperty("label", out JsonElement paramLabelElement) + ? paramLabelElement.ValueKind == JsonValueKind.String + ? paramLabelElement.GetString() + : TryExtractParameterLabel(label, paramLabelElement, out string? extractedLabel) + ? extractedLabel + : null + : null; - if (string.IsNullOrWhiteSpace(description)) - return detail; + string? parameterDocumentation = paramElement.TryGetProperty("documentation", out JsonElement parameterDocumentationElement) + ? ExtractMarkupText(parameterDocumentationElement) + : null; - return detail + Environment.NewLine + description; + parameters.Add(new LuaParameterInfo(parameterLabel ?? string.Empty, parameterDocumentation)); + } } - private static bool CompletionTextContains(string text, string token) - => !string.IsNullOrWhiteSpace(text) && text.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; + return new LuaSignatureInfo(label, documentation, parameters, activeParameter); + } - private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, out string parameterLabel) - { - parameterLabel = null; + private static string? BuildCompletionDetail(JsonElement itemElement) + { + if (!itemElement.TryGetProperty("detail", out JsonElement detailElement)) + return null; - if (string.IsNullOrEmpty(signatureLabel) - || parameterLabelElement.ValueKind != JsonValueKind.Array) - { - return false; - } + string? detail = detailElement.GetString(); + return string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); + } + + private static MarkupContent BuildCompletionDescription(JsonElement itemElement) + { + if (!itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) + return default; - JsonElement.ArrayEnumerator labelParts = parameterLabelElement.EnumerateArray(); + MarkupContent documentation = ExtractMarkupContent(documentationElement); - if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int startIndex)) - return false; + if (string.IsNullOrWhiteSpace(documentation.Text)) + return default; - if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int endIndex)) - return false; + string? normalizedText = documentation.IsMarkdown + ? NormalizeMarkdownText(documentation.Text) + : NormalizeMarkupText(documentation.Text); - startIndex = Math.Max(0, Math.Min(startIndex, signatureLabel.Length)); - endIndex = Math.Max(startIndex, Math.Min(endIndex, signatureLabel.Length)); + return string.IsNullOrWhiteSpace(normalizedText) + ? default + : new MarkupContent(normalizedText, documentation.IsMarkdown); + } - if (endIndex <= startIndex) - return false; + private static string? CombineCompletionText(string? detail, string? description) + { + if (string.IsNullOrWhiteSpace(detail)) + return description; - parameterLabel = signatureLabel[startIndex..endIndex]; - return true; - } + if (string.IsNullOrWhiteSpace(description)) + return detail; + + return detail + Environment.NewLine + description; + } - private static string ExtractMarkupText(JsonElement element) - => NormalizeMarkupText(ExtractMarkupContent(element).Text); + private static bool CompletionTextContains(string? text, string token) + => !string.IsNullOrWhiteSpace(text) && text.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; - private static MarkupContent ExtractMarkupContent(JsonElement element) + private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, + [NotNullWhen(true)] out string? parameterLabel) + { + parameterLabel = null; + + if (string.IsNullOrEmpty(signatureLabel) + || parameterLabelElement.ValueKind != JsonValueKind.Array) { - return element.ValueKind switch - { - JsonValueKind.String => new MarkupContent(element.GetString(), true), - JsonValueKind.Array => CombineMarkupContent(element.EnumerateArray().Select(ExtractMarkupContent)), - JsonValueKind.Object when element.TryGetProperty("value", out JsonElement valueElement) - && element.TryGetProperty("kind", out JsonElement kindElement) - => new MarkupContent(valueElement.GetString(), - string.Equals(kindElement.GetString(), "markdown", StringComparison.OrdinalIgnoreCase)), - JsonValueKind.Object when element.TryGetProperty("language", out JsonElement languageElement) - && element.TryGetProperty("value", out JsonElement codeValueElement) - => new MarkupContent($"```{languageElement.GetString()}\n{codeValueElement.GetString()}\n```", true), - JsonValueKind.Object when element.TryGetProperty("value", out JsonElement plainValueElement) - => new MarkupContent(plainValueElement.GetString(), false), - _ => default - }; + return false; } - private static MarkupContent CombineMarkupContent(IEnumerable items) - { - bool isMarkdown = false; - var parts = new List(); + JsonElement.ArrayEnumerator labelParts = parameterLabelElement.EnumerateArray(); - foreach (MarkupContent item in items) - { - if (string.IsNullOrWhiteSpace(item.Text)) - continue; + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int startIndex)) + return false; - parts.Add(item.Text.Trim()); - isMarkdown |= item.IsMarkdown; - } + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int endIndex)) + return false; - return parts.Count == 0 - ? default - : new MarkupContent(string.Join(Environment.NewLine + Environment.NewLine, parts), isMarkdown); - } + startIndex = Math.Max(0, Math.Min(startIndex, signatureLabel.Length)); + endIndex = Math.Max(startIndex, Math.Min(endIndex, signatureLabel.Length)); + + if (endIndex <= startIndex) + return false; + + parameterLabel = signatureLabel[startIndex..endIndex]; + return true; + } + + private static string? ExtractMarkupText(JsonElement element) + => NormalizeMarkupText(ExtractMarkupContent(element).Text); - private static string NormalizeMarkupText(string text) + private static MarkupContent ExtractMarkupContent(JsonElement element) + { + return element.ValueKind switch { - if (string.IsNullOrWhiteSpace(text)) - return null; + JsonValueKind.String => new MarkupContent(element.GetString(), true), + JsonValueKind.Array => CombineMarkupContent(element.EnumerateArray().Select(ExtractMarkupContent)), + JsonValueKind.Object when element.TryGetProperty("value", out JsonElement valueElement) + && element.TryGetProperty("kind", out JsonElement kindElement) + => new MarkupContent(valueElement.GetString(), + string.Equals(kindElement.GetString(), "markdown", StringComparison.OrdinalIgnoreCase)), + JsonValueKind.Object when element.TryGetProperty("language", out JsonElement languageElement) + && element.TryGetProperty("value", out JsonElement codeValueElement) + => new MarkupContent($"```{languageElement.GetString()}\n{codeValueElement.GetString()}\n```", true), + JsonValueKind.Object when element.TryGetProperty("value", out JsonElement plainValueElement) + => new MarkupContent(plainValueElement.GetString(), false), + _ => default + }; + } - string normalized = text - .Replace("```lua", string.Empty, StringComparison.OrdinalIgnoreCase) - .Replace("```", string.Empty, StringComparison.Ordinal) - .Replace("`", string.Empty, StringComparison.Ordinal) - .Replace("\r", string.Empty, StringComparison.Ordinal) - .Trim(); + private static MarkupContent CombineMarkupContent(IEnumerable items) + { + bool isMarkdown = false; + var parts = new List(); - string[] lines = normalized - .Split('\n') - .Select(line => line.TrimEnd()) - .ToArray(); + foreach (MarkupContent item in items) + { + if (string.IsNullOrWhiteSpace(item.Text)) + continue; - return string.Join(Environment.NewLine, lines).Trim(); + parts.Add(item.Text.Trim()); + isMarkdown |= item.IsMarkdown; } - private static string NormalizeMarkdownText(string text) - => string.IsNullOrWhiteSpace(text) - ? null - : text.Replace("\r\n", "\n", StringComparison.Ordinal) - .Replace('\r', '\n') - .Trim(); + return parts.Count == 0 + ? default + : new MarkupContent(string.Join(Environment.NewLine + Environment.NewLine, parts), isMarkdown); + } - private static string StripSnippetPlaceholders(string snippet) - { - if (string.IsNullOrWhiteSpace(snippet)) - return snippet; + private static string? NormalizeMarkupText(string? text) + { + if (string.IsNullOrWhiteSpace(text)) + return null; - var builder = new StringBuilder(snippet.Length); - int index = 0; + string normalized = text + .Replace("```lua", string.Empty, StringComparison.OrdinalIgnoreCase) + .Replace("```", string.Empty, StringComparison.Ordinal) + .Replace("`", string.Empty, StringComparison.Ordinal) + .Replace("\r", string.Empty, StringComparison.Ordinal) + .Trim(); - while (index < snippet.Length) - { - if (snippet[index] == '$') - { - if (index + 1 < snippet.Length && snippet[index + 1] == '{') - { - int endIndex = snippet.IndexOf('}', index + 2); + string[] lines = [.. normalized + .Split('\n') + .Select(line => line.TrimEnd())]; + + return string.Join(Environment.NewLine, lines).Trim(); + } - if (endIndex > index) - { - string placeholder = snippet[(index + 2)..endIndex]; - int separatorIndex = placeholder.IndexOf(':'); + private static string? NormalizeMarkdownText(string? text) + => string.IsNullOrWhiteSpace(text) + ? null + : text.Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n') + .Trim(); - if (separatorIndex >= 0 && separatorIndex < placeholder.Length - 1) - builder.Append(placeholder[(separatorIndex + 1)..]); + private static string StripSnippetPlaceholders(string snippet) + { + if (string.IsNullOrWhiteSpace(snippet)) + return snippet; - index = endIndex + 1; - continue; - } - } + var builder = new StringBuilder(snippet.Length); + int index = 0; - index++; + while (index < snippet.Length) + { + if (snippet[index] == '$') + { + if (index + 1 < snippet.Length && snippet[index + 1] == '{') + { + int endIndex = snippet.IndexOf('}', index + 2); + + if (endIndex > index) + { + string placeholder = snippet[(index + 2)..endIndex]; + int separatorIndex = placeholder.IndexOf(':'); - while (index < snippet.Length && char.IsDigit(snippet[index])) - index++; + if (separatorIndex >= 0 && separatorIndex < placeholder.Length - 1) + builder.Append(placeholder[(separatorIndex + 1)..]); - continue; + index = endIndex + 1; + continue; + } } - builder.Append(snippet[index]); index++; + + while (index < snippet.Length && char.IsDigit(snippet[index])) + index++; + + continue; } - return builder.ToString(); + builder.Append(snippet[index]); + index++; } + + return builder.ToString(); } -} \ No newline at end of file +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs index 2b4cf78ac4..cb1b6a8845 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs @@ -1,89 +1,93 @@ +#nullable enable + using System; using System.Collections.Generic; using System.Text.Json; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static class LuaLanguageServerSemanticTokensParser { - internal static class LuaLanguageServerSemanticTokensParser + /// + /// Decodes the LuaLS semantic token payload for a synchronized document snapshot. + /// + public static IReadOnlyList Parse(JsonElement response, LuaDocumentSnapshot? document, + IReadOnlyList? tokenTypes, IReadOnlyList? tokenModifiers) { - public static IReadOnlyList Parse(JsonElement response, LuaDocumentSnapshot document, - IReadOnlyList tokenTypes, IReadOnlyList tokenModifiers) + if (document is null || tokenTypes is null || tokenTypes.Count == 0) + return []; + + if (!response.TryGetProperty("data", out JsonElement dataElement) || dataElement.ValueKind != JsonValueKind.Array) + return []; + + string[] lines = NormalizeLineEndings(document.Content).Split('\n'); + var semanticTokens = new List(); + var rawData = new List(); + + foreach (JsonElement item in dataElement.EnumerateArray()) { - if (document is null || tokenTypes is null || tokenTypes.Count == 0) - return Array.Empty(); - - if (!response.TryGetProperty("data", out JsonElement dataElement) || dataElement.ValueKind != JsonValueKind.Array) - return Array.Empty(); - - string[] lines = NormalizeLineEndings(document.Content).Split('\n'); - var semanticTokens = new List(); - var rawData = new List(); - - foreach (JsonElement item in dataElement.EnumerateArray()) - { - if (item.TryGetInt32(out int value)) - rawData.Add(value); - } - - int line = 0; - int character = 0; - - for (int i = 0; i + 4 < rawData.Count; i += 5) - { - int deltaLine = rawData[i]; - int deltaCharacter = rawData[i + 1]; - int length = rawData[i + 2]; - int tokenTypeIndex = rawData[i + 3]; - int modifierMask = rawData[i + 4]; - - line += deltaLine; - - if (deltaLine == 0) - character += deltaCharacter; - else - character = deltaCharacter; - - if (line < 0 || line >= lines.Length || tokenTypeIndex < 0 || tokenTypeIndex >= tokenTypes.Count) - continue; - - int lineLength = lines[line].Length; - int safeCharacter = Math.Max(0, Math.Min(character, lineLength)); - int safeLength = Math.Max(0, Math.Min(length, lineLength - safeCharacter)); - - if (safeLength == 0) - continue; - - semanticTokens.Add(new LuaSemanticToken( - line, - safeCharacter, - safeLength, - tokenTypes[tokenTypeIndex], - DecodeModifiers(modifierMask, tokenModifiers))); - } - - return semanticTokens; + if (item.TryGetInt32(out int value)) + rawData.Add(value); } - private static IReadOnlyList DecodeModifiers(int modifierMask, IReadOnlyList tokenModifiers) + int line = 0; + int character = 0; + + for (int i = 0; i + 4 < rawData.Count; i += 5) { - if (modifierMask == 0 || tokenModifiers is null || tokenModifiers.Count == 0) - return Array.Empty(); + int deltaLine = rawData[i]; + int deltaCharacter = rawData[i + 1]; + int length = rawData[i + 2]; + int tokenTypeIndex = rawData[i + 3]; + int modifierMask = rawData[i + 4]; + + line += deltaLine; + + if (deltaLine == 0) + character += deltaCharacter; + else + character = deltaCharacter; + + if (line < 0 || line >= lines.Length || tokenTypeIndex < 0 || tokenTypeIndex >= tokenTypes.Count) + continue; + + int lineLength = lines[line].Length; + int safeCharacter = Math.Max(0, Math.Min(character, lineLength)); + int safeLength = Math.Max(0, Math.Min(length, lineLength - safeCharacter)); + + if (safeLength == 0) + continue; + + semanticTokens.Add(new LuaSemanticToken( + line, + safeCharacter, + safeLength, + tokenTypes[tokenTypeIndex], + DecodeModifiers(modifierMask, tokenModifiers))); + } + + return semanticTokens; + } - var modifiers = new List(); + private static IReadOnlyList DecodeModifiers(int modifierMask, IReadOnlyList? tokenModifiers) + { + if (modifierMask == 0 || tokenModifiers is null || tokenModifiers.Count == 0) + return []; - for (int bitIndex = 0; bitIndex < tokenModifiers.Count; bitIndex++) - { - if ((modifierMask & (1 << bitIndex)) != 0) - modifiers.Add(tokenModifiers[bitIndex]); - } + var modifiers = new List(); - return modifiers; + for (int bitIndex = 0; bitIndex < tokenModifiers.Count; bitIndex++) + { + if ((modifierMask & (1 << bitIndex)) != 0) + modifiers.Add(tokenModifiers[bitIndex]); } - private static string NormalizeLineEndings(string content) - => (content ?? string.Empty) - .Replace("\r\n", "\n", StringComparison.Ordinal) - .Replace('\r', '\n'); + return modifiers; } -} \ No newline at end of file + + private static string NormalizeLineEndings(string? content) + => (content ?? string.Empty) + .Replace("\r\n", "\n", StringComparison.Ordinal) + .Replace('\r', '\n'); +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs index fadb330646..3c3a772edd 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs @@ -1,51 +1,56 @@ -using System; +#nullable enable + using System.IO; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static class LuaLanguageServerSettingsFactory { - internal static class LuaLanguageServerSettingsFactory + /// + /// Builds the Lua language server settings payload for the active script workspace. + /// + /// The root directory of the current Lua script workspace. + /// An anonymous settings object serialized into the LuaLS configuration request. + public static object Create(string workspaceRootDirectoryPath) { - public static object Create(string workspaceRootDirectoryPath) - { - string apiDirectory = Path.Combine(workspaceRootDirectoryPath, ".API"); - string[] library = Directory.Exists(apiDirectory) - ? new[] { Path.GetFullPath(apiDirectory) } - : Array.Empty(); + string apiDirectory = Path.Combine(workspaceRootDirectoryPath, ".API"); + string[] library = Directory.Exists(apiDirectory) + ? [Path.GetFullPath(apiDirectory)] + : []; - return new + return new + { + Lua = new { - Lua = new + runtime = new + { + version = "Lua 5.4" + }, + workspace = new + { + checkThirdParty = false, + library + }, + completion = new + { + callSnippet = "Disable" + }, + semantic = new + { + enable = true, + annotation = true, + variable = true, + keyword = false + }, + diagnostics = new + { + disable = new[] { "duplicate-set-field" } + }, + telemetry = new { - runtime = new - { - version = "Lua 5.4" - }, - workspace = new - { - checkThirdParty = false, - library - }, - completion = new - { - callSnippet = "Disable" - }, - semantic = new - { - enable = true, - annotation = true, - variable = true, - keyword = false - }, - diagnostics = new - { - disable = new[] { "duplicate-set-field" } - }, - telemetry = new - { - enable = false - } + enable = false } - }; - } + } + }; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs b/TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs index aac16969dc..d34753098b 100644 --- a/TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs +++ b/TombLib/TombLib.Scripting.Lua/Properties/InternalsVisibleTo.cs @@ -1,3 +1,3 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("TombLib.Test")] \ No newline at end of file +[assembly: InternalsVisibleTo("TombLib.Test")] diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs index 9b596ad089..feee858900 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs @@ -74,4 +74,4 @@ private int GetSafeLineNumberForOffset(int offset) int safeOffset = Math.Max(0, Math.Min(offset, _document.TextLength)); return _document.GetLineByOffset(safeOffset).LineNumber; } -} \ No newline at end of file +} From b107dbe38350d96958cf640dfa8a149dd6405968 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Wed, 22 Apr 2026 23:01:47 +0100 Subject: [PATCH 21/34] Progress report --- AGENTS.md | 116 ++-- .../LuaStudio.Intellisense.cs | 23 +- TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs | 8 +- .../Properties/InternalsVisibleTo.cs | 3 + .../ILuaLanguageServerClient.cs | 25 + .../LuaIntellisense/LuaDocumentLineOffsets.cs | 90 +++ .../LuaIntellisense/LuaDocumentSnapshot.cs | 11 + .../LuaDocumentSynchronizationKind.cs | 9 + .../LuaDocumentSynchronizationRequest.cs | 24 + .../LuaIncrementalEditCalculator.cs | 81 +++ .../LuaIntellisenseDocumentManager.cs | 174 ++++-- .../LuaLanguageServerClient.Protocol.cs | 220 +++++++ .../LuaLanguageServerClient.Transport.cs | 377 ++++++++++++ .../LuaLanguageServerClient.cs | 563 ++++++------------ .../LuaLanguageServerDiagnosticsParser.cs | 112 ++-- ...ageServerIntellisenseProvider.Documents.cs | 280 +++++++++ ...uageServerIntellisenseProvider.Requests.cs | 163 +++++ ...rverIntellisenseProvider.SemanticTokens.cs | 204 +++++++ .../LuaLanguageServerIntellisenseProvider.cs | 435 ++++---------- .../LuaLanguageServerLocator.cs | 5 +- ...LanguageServerResponseParser.Completion.cs | 384 ++++++++++++ ...LanguageServerResponseParser.Navigation.cs | 95 +++ ...guageServerResponseParser.SignatureHelp.cs | 125 ++++ .../LuaLanguageServerResponseParser.cs | 533 +---------------- ...LanguageServerSemanticTokensDeltaParser.cs | 210 +++++++ .../LuaLanguageServerSemanticTokensParser.cs | 72 +-- .../LuaLanguageServerSettingsFactory.cs | 10 +- .../LuaIntellisense/LuaProcessJobObject.cs | 166 ++++++ .../LuaPublishedDiagnostics.cs | 13 + .../LuaWorkspaceFileWatcher.cs | 208 +++++++ .../LuaSemanticTokensColorizer.cs | 167 +++--- .../LuaEditor.Completion.cs | 77 ++- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 41 +- .../LuaEditor.Intellisense.cs | 7 +- .../LuaEditor.Navigation.cs | 12 +- .../LuaEditor.SemanticHighlighting.cs | 4 +- .../LuaEditor.SignatureHelp.cs | 109 ++-- TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 3 + .../Objects/LuaCompletionData.cs | 22 +- .../Objects/LuaCompletionIconFactory.cs | 20 +- .../Objects/LuaCompletionItem.cs | 10 +- .../Objects/LuaDefinitionLocation.cs | 2 +- .../Objects/LuaHoverInfo.cs | 4 +- .../Objects/LuaSignatureInfo.cs | 4 +- .../Resources/LuaThemeBrushSet.cs | 86 +-- .../Resources/LuaThemeRepository.cs | 24 +- .../TombLib.Scripting.Lua.csproj | 11 +- .../Utils/LuaDocumentLineParserStateCache.cs | 4 +- .../Utils/LuaEditorInteractionRules.cs | 13 +- .../Utils/LuaLineParser.cs | 45 +- .../Utils/TombEngineLanguageScriptService.cs | 60 +- .../LuaEditorInteractionRulesTests.cs | 15 +- .../LuaIncrementalEditCalculatorTests.cs | 122 ++++ .../LuaLanguageServerClientTests.cs | 378 ++++++++++++ ...LuaLanguageServerDiagnosticsParserTests.cs | 67 +++ ...LanguageServerIntellisenseProviderTests.cs | 314 ++++++++++ .../LuaLanguageServerResponseParserTests.cs | 62 ++ TombLib/TombLib.Test/LuaLineParserTests.cs | 9 +- .../LuaThemeConfigurationTests.cs | 5 +- TombLib/TombLib.Test/TombLib.Test.csproj | 1 + 60 files changed, 4624 insertions(+), 1813 deletions(-) create mode 100644 TombIDE/TombIDE.ScriptingStudio/Properties/InternalsVisibleTo.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationRequest.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Navigation.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.SignatureHelp.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs create mode 100644 TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs create mode 100644 TombLib/TombLib.Test/LuaLanguageServerClientTests.cs create mode 100644 TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs create mode 100644 TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs create mode 100644 TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs diff --git a/AGENTS.md b/AGENTS.md index 8284c7fe6a..cbf364b206 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ ## General Project Information -- Language: **C# targeting .NET 8** (desktop application). +- Language: **C# targeting .NET 8** (desktop application). - This is a level editor suite for a family of 3D game engines used in the classic Tomb Raider series. - Level formats are grid-based, room-based, and portal-based. - A room is a spatial container for level geometry and game entities. @@ -10,21 +10,43 @@ ## General Guidelines +### Files and Namespaces + - Files must use Windows line endings. Only standard ASCII symbols are allowed; do not use Unicode symbols. -- `using` directives are grouped and sorted as follows: `DarkUI` namespaces first, then `System` namespaces, followed by third-party and local namespaces. -- Namespace declarations and type definitions should place the opening brace on a new line. -- Prefer grouping all feature-related functionality within a self-contained module or modules. Avoid creating large code blocks over 10–15 lines in existing modules; instead, offload code to helper functions. -- Avoid duplicating and copypasting code. Implement helper methods instead, whenever similar code is used within a given module, class or feature scope. +- Every document should end with a trailing newline. +- `using` directives and namespace declarations should always be sorted alphabetically. +- Remove unused `using` statements. +- Prefer importing namespaces over fully qualifying framework types when there is no ambiguity. Remove redundant qualifiers such as `System.StringComparison` and use `StringComparison` directly when no namespace conflict exists. +- Prefer file-scoped namespaces where a file contains a single namespace and no language constraint prevents it. If a block-scoped namespace is still required, place the opening brace on a new line and sort multiple namespace declarations alphabetically. + +### Nullability + +- Each refactor should enable nullable reference types for the touched code. Add `#nullable enabled` at the top of the file only when the project does not already enable nullables, and update the touched code to use nullable annotations and checks correctly. +- Always use `is null` / `is not null` rather than `== null` / `!= null`. +- Prefer nullability attributes and helpers such as `[NotNullWhen]`, `[MemberNotNull]`, `[MaybeNullWhen]` and related annotations when they improve flow analysis and keep the API clear. +- Avoid the null-forgiving operator (`!`) where possible. Prefer flow analysis, null checks, annotations and helper methods instead, and use `!` only when it is truly necessary to express a proven invariant the compiler cannot infer. + +### Architecture and Composition + +- Keep feature-related functionality within self-contained modules. Avoid large code blocks over 10-15 lines in existing modules; move that logic into helpers or dedicated types. +- Always look for opportunities to de-duplicate code and fix duplication where suitable. Prefer shared helpers or extracted modules when similar code appears within a module, class or feature scope. +- Prefer modern .NET and C# conventions when project-specific guidance does not require something else. +- Design new code with service-based composition in mind. Favor dependency injection seams, and use the temporary `TombLib.WPF` service locator only in code paths that already depend on it. +- Keep vertical slice architecture in mind when choosing where new features, helpers and dependencies should live. ## Formatting -- **Indentation** is four spaces; tabs are not used. +### Indentation + +- Indentation uses four spaces; tabs are not used. -- **Braces**: - - Always use braces for multi-statement blocks. - - Do not use braces for single-statement blocks, unless they are within multiple `else if` conditions where surrounding statements are multi-line. - - - Opening curly brace `{` for structures, classes and methods should be on the next line, not on the same line: +### Braces + +- Always use braces for multi-statement blocks. +- Single-line conditions should not use braces when the entire `if` / `else if` / `else` chain stays single-line. +- Multi-line conditions or multi-line bodies must always use braces. +- If any branch in an `if` / `else if` / `else` chain uses braces, all sibling branches should use braces as well. +- Opening curly brace `{` for structures, classes and methods should be on the next line, not on the same line: ```csharp public class Foo @@ -39,27 +61,29 @@ } ``` - - Anonymous delegates and lambdas should keep the brace on the same line: - `delegate () { ... }` or `() => { ... }`. - -- **Line breaks and spacing**: - - A blank line separates logically distinct groups of members (fields, constructors, public methods, private helpers, etc.). - - Spaces around binary operators (`=`, `+`, `==`, etc.) and after commas. - - A single space follows keyword `if`/`for`/`while` before the opening parenthesis. - - Expressions may be broken into multiple lines and aligned with the previous line's indentation level to improve readability. - - However, chained LINQ method calls, lambdas or function/method arguments should not be broken into multiple lines, unless they reach more than 150 symbols in length. - - - Do not collapse early exits or single-statement conditions into a single line: - - Bad example: - ```csharp - if (condition) return; - ``` - Do this instead: - ```csharp - if (condition) - return; - ``` +- Anonymous delegates and lambdas should keep the brace on the same line: `delegate () { ... }` or `() => { ... }`. + +### Line Breaks and Spacing + +- A blank line separates logically distinct groups of members (fields, constructors, public methods, private helpers, etc.). +- Within method bodies, use a blank line between logically distinct statements and before a control-flow block that starts a new step. +- Avoid whitespace-only lines or dead indentation; blank lines should be truly blank. +- Spaces around binary operators (`=`, `+`, `==`, etc.) and after commas. +- A single space follows keyword `if` / `for` / `while` before the opening parenthesis. +- Expressions may be broken into multiple lines and aligned with the previous line's indentation level to improve readability. +- Chained LINQ method calls, lambdas or function arguments should stay on one line unless they exceed roughly 150 characters. +- Do not collapse early exits or single-statement conditions into one line. + + Bad example: + ```csharp + if (condition) return; + ``` + + Do this instead: + ```csharp + if (condition) + return; + ``` ## Naming @@ -75,40 +99,54 @@ - Fields are generally declared as `public` or `private readonly` depending on usage; expose state via properties where appropriate. - `var` type should be preferred where possible, when the right-hand type is evident from the initializer. -- Explicit typing should be only used when it is required by logic or compiler, or when type name is shorter than 6 symbols (e.g. `int`, `bool`, `float`). +- Explicit typing should only be used when it is required by logic or compiler, or when the type name is shorter than 6 symbols (e.g. `int`, `bool`, `float`). - For floating-point numbers, always use `f` postfix and decimal, even if value is not fractional (e.g. `2.0f`). +- Consider `record` or `record struct` when value semantics, immutability, or concise data-carrier behavior make them a better fit than a class or struct. +- Prefer expression-bodied members for methods or properties whose implementation is a single readable line. +- Prefer collection expressions (`[]`, `[item]`, `[..items]`) over `Array.Empty()`, explicit array or list construction, or simple `.ToArray()` / `.ToList()` materialization when the target type supports them and the result stays clear. ## Control Flow and Syntax - Avoid excessive condition nesting and use early exits / breaks where possible. - LINQ and lambda expressions are used for collections (`FirstOrDefault`, `Where`, `Any`, etc.). +- Use pattern matching where it keeps the code clearer or removes redundant casts, temporary variables or branching. +- Under nullable-aware code, avoid throwing `ArgumentNullException` for non-nullable parameters when the guard adds no meaningful value. +- When an exception type exposes helper APIs such as `ArgumentNullException.ThrowIfNull`, prefer those helpers over manual `if` blocks when the behavior stays clear. - Exception and error handling is done with `try`/`catch`, and caught exceptions are logged with [NLog](https://nlog-project.org/) where appropriate. -- Warnings must also be logged by NLog, if cause for the incorrect behaviour is user action. +- Warnings caused by user action should also be logged through NLog. ## Comments - When comments appear they are single-line `//`. Block comments (`/* ... */`) are rare. - Comments are sparse. Code relies on meaningful names rather than inline documentation. -- Do not use `` if surrounding code and/or module isn't already using it. Only add `` for non-private methods with high complexity. -- If module or function implements complex functionality, a brief description (2-3 lines) may be added in front of it, separated by a blank line from the function body. +- Add XML documentation to classes where it clarifies intent, and to public methods and public properties by default. Use XML documentation for private members only when the behavior is complex enough that names alone are not sufficient. +- If a module or function implements complex functionality, use brief section comments to split long methods into smaller, digestible steps. - All descriptive comments should end with a full stop (`.`). ## Code Grouping -- Large methods should group related actions together, separated by blank lines. +- Large methods should group related actions together, separated by blank lines and short section comments when they cannot be broken apart further. - Constants and static helpers that are used several times should appear at the top of a class. - Constants that are used only within a scope of a method, should be declared within this method. - One-liner lambdas may be grouped together, if they share similar meaning or functionality. +- Prefer one top-level type per file when practical. Keep multiple classes, enums, records or interfaces in the same file only when they are strictly coupled. +- When a class grows too large in size or scope, split it into smaller partial classes organized by responsibility. Use partial classes only when the responsibilities still belong to the same type; otherwise extract a dedicated helper, service or type instead. +- Avoid one-line wrapper methods unless they remove duplication, enforce a policy, or provide meaning beyond a direct redirect. +- Do not keep generic helper methods inside the same feature class. First check whether a suitable shared helper already exists elsewhere in the codebase; otherwise extract the helper into the most suitable shared library project or dedicated module. +- If a helper method is broad in scope, such as a general WPF helper like `FindAncestor()`, first verify whether an equivalent already exists. If not, place it in the narrowest suitable shared library among `TombLib`, `TombLib.Scripting`, `TombLib.WPF` and `DarkUI.WPF` rather than adding it to a feature-local helper class. ## User Interface Implementation - For WinForms-based workflows, maintain the existing Visual Studio module pair for each control or unit: `.cs` and `.Designer.cs`. - For existing WinForms-based `DarkUI` controls and containers, prefer to use existing WinForms-based `DarkUI` controls. -- For new controls and containers with complex logic, or where WinForms may not perform fast enough, prefer `DarkUI.WPF` framework. Use `GeometryIOSettingsWindow` as a reference. +- For new WPF views and view models, use `GeometryIOSettingsWindow` as the reference for structure, localization and service usage patterns. +- When writing WPF UI, prioritize localization and the existing localization infrastructure from `TombLib.WPF`. +- Creating new generic WPF controls should be delegated to `DarkUI.WPF`. +- For new controls and containers with complex logic, or where WinForms may not perform fast enough, prefer `DarkUI.WPF`. - Use `CommunityToolkit` functionality where possible. ## Performance - For 3D rendering controls, prefer more performant approaches and locally cache frequently used data within the function scope whenever possible. - Avoid scenarios where bulk data updates may cause event floods, as the project relies heavily on event subscriptions across multiple controls and sub-controls. -- Use `Parallel` for bulk operations to maximize performance. Avoid using it in thread-unsafe contexts or when operating on serial data sets. \ No newline at end of file +- Use `Parallel` for bulk operations to maximize performance. Avoid using it in thread-unsafe contexts or when operating on serial data sets. diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index e841b40774..518e2377fd 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -1,13 +1,12 @@ #nullable enable using ICSharpCode.AvalonEdit.Document; +using NLog; using System; using System.Collections.Generic; using System.IO; using System.Windows.Forms; using TombIDE.ScriptingStudio.Services.LuaIntellisense; -using TombIDE.Shared; -using TombIDE.Shared.SharedClasses; using TombLib.Scripting.Bases; using TombLib.Scripting.Lua; using TombLib.Scripting.Lua.Objects; @@ -18,6 +17,8 @@ namespace TombIDE.ScriptingStudio; public sealed partial class LuaStudio { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private readonly ILuaIntellisenseProvider _intellisenseProvider; private void HookLuaIntellisense() @@ -41,9 +42,23 @@ private void DisposeLuaIntellisense() private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() { - TENApiService.InjectTENApi(IDE.Instance.Project, IDE.Instance.Project.GetCurrentEngineVersion()); - string? executablePath = LuaLanguageServerLocator.ResolveExecutablePath(); + + if (string.IsNullOrWhiteSpace(executablePath)) + { + // LuaLS is shipped with TombIDE; if the bundled binary is missing the user has no way + // of knowing why diagnostics, completion and definition lookups silently stop working. + // Log a warning and surface a single non-blocking notification so the failure is visible. + Log.Warn("Bundled Lua language server was not found; Lua IntelliSense (diagnostics, completion, hover, go-to-definition) will be unavailable for this session."); + DarkUI.Forms.DarkMessageBox.Show(this, + "The bundled Lua language server (LuaLS) could not be located.\n\n" + + "Lua IntelliSense - including diagnostics, completion, hover and go-to-definition - will be unavailable for this session.\n\n" + + "Reinstall TombIDE to restore the bundled language server.", + "Lua IntelliSense unavailable", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + } + return new LuaLanguageServerIntellisenseProvider(ScriptRootDirectoryPath, executablePath); } diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs index 235ec63f45..e2f2cea762 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs @@ -73,7 +73,7 @@ protected override void OnIDEEventRaised(IIDEEvent obj) } } - private bool IsSilentAction(IIDEEvent obj) + private static bool IsSilentAction(IIDEEvent obj) => obj is IDE.ScriptEditor_AppendScriptEvent || obj is IDE.ScriptEditor_ScriptPresenceCheckEvent || obj is IDE.ScriptEditor_StringPresenceCheckEvent @@ -101,7 +101,7 @@ private void IDEEvent_HandleSilentActions(IIDEEvent obj) EndSilentScriptAction(cachedTab, true, false, false); } - else if (obj is IDE.ScriptEditor_ScriptPresenceCheckEvent scrpce) + else if (obj is IDE.ScriptEditor_ScriptPresenceCheckEvent) { IDE.Instance.ScriptDefined = true; // TEMP !!! } @@ -302,11 +302,11 @@ protected override void HandleDocumentCommands(UICommand command) { case UICommand.GoToDefinition: if (CurrentEditor is LuaEditor luaEditor) - luaEditor.NavigateToDefinitionAtCaretAsync(); + _ = luaEditor.NavigateToDefinitionAtCaretAsync(); break; case UICommand.LuaBasics: - string url = "https://github.com/MontyTRC89/TombEngine/wiki/Basics-of-Lua-Programming"; + const string url = "https://github.com/MontyTRC89/TombEngine/wiki/Basics-of-Lua-Programming"; var process = new ProcessStartInfo { diff --git a/TombIDE/TombIDE.ScriptingStudio/Properties/InternalsVisibleTo.cs b/TombIDE/TombIDE.ScriptingStudio/Properties/InternalsVisibleTo.cs new file mode 100644 index 0000000000..d34753098b --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Properties/InternalsVisibleTo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("TombLib.Test")] diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs new file mode 100644 index 0000000000..dca780dc08 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs @@ -0,0 +1,25 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal interface ILuaLanguageServerClient : IDisposable +{ + bool IsReady { get; } + IReadOnlyList SemanticTokenTypes { get; } + IReadOnlyList SemanticTokenModifiers { get; } + bool SupportsCompletionResolve { get; } + bool SupportsSemanticTokensDelta { get; } + + event Action? DiagnosticsPublished; + event Action? SemanticTokensRefreshRequested; + + Task StartAsync(CancellationToken cancellationToken); + Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken); + Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken); +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs new file mode 100644 index 0000000000..35c87cbe93 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs @@ -0,0 +1,90 @@ +#nullable enable + +using System; +using System.Collections.Generic; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Provides a precomputed table of line start offsets and lengths for a Lua document content string. +/// This avoids allocating heavyweight TextDocument instances when parsing LSP payloads such as +/// diagnostics and semantic tokens, which only need to translate between line/character and document offsets. +/// Both \r\n and lone \r are treated as line breaks for parity with LSP positions. +/// +internal sealed class LuaDocumentLineOffsets +{ + private readonly string _content; + private readonly int[] _lineStartOffsets; + private readonly int[] _lineLengths; + + private LuaDocumentLineOffsets(string content, int[] lineStartOffsets, int[] lineLengths) + { + _content = content; + _lineStartOffsets = lineStartOffsets; + _lineLengths = lineLengths; + } + + public int LineCount => _lineLengths.Length; + public int TextLength => _content.Length; + + public int GetLineLength(int lineIndex) => _lineLengths[lineIndex]; + public int GetLineStartOffset(int lineIndex) => _lineStartOffsets[lineIndex]; + + /// + /// Returns the offset within the document for the supplied zero-based line and character indices, + /// clamping the character index to the line length. + /// + public int GetOffset(int lineIndex, int character) + { + int safeLine = Math.Clamp(lineIndex, 0, _lineLengths.Length - 1); + int safeCharacter = Math.Clamp(character, 0, _lineLengths[safeLine]); + return _lineStartOffsets[safeLine] + safeCharacter; + } + + public string GetLineText(int lineIndex) + { + int safeLine = Math.Clamp(lineIndex, 0, _lineLengths.Length - 1); + return _content.Substring(_lineStartOffsets[safeLine], _lineLengths[safeLine]); + } + + /// + /// Builds the offset table from the given content in a single pass, avoiding the large intermediate + /// allocations of . + /// + public static LuaDocumentLineOffsets Build(string? content) + { + string text = content ?? string.Empty; + + if (text.Length == 0) + return new LuaDocumentLineOffsets(text, [0], [0]); + + var startOffsets = new List(64) { 0 }; + var lengths = new List(64); + int currentStart = 0; + + for (int i = 0; i < text.Length; i++) + { + char c = text[i]; + + if (c == '\r') + { + lengths.Add(i - currentStart); + + if (i + 1 < text.Length && text[i + 1] == '\n') + i++; + + currentStart = i + 1; + startOffsets.Add(currentStart); + } + else if (c == '\n') + { + lengths.Add(i - currentStart); + currentStart = i + 1; + startOffsets.Add(currentStart); + } + } + + lengths.Add(text.Length - currentStart); + return new LuaDocumentLineOffsets(text, [.. startOffsets], [.. lengths]); + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs new file mode 100644 index 0000000000..f9319ce6f1 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs @@ -0,0 +1,11 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed class LuaDocumentSnapshot(string filePath, string uri, string? content, int version) +{ + public string FilePath { get; } = filePath; + public string Uri { get; } = uri; + public string Content { get; } = content ?? string.Empty; + public int Version { get; } = version; +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs new file mode 100644 index 0000000000..5537702dd1 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs @@ -0,0 +1,9 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal enum LuaDocumentSynchronizationKind +{ + Open, + Change +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationRequest.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationRequest.cs new file mode 100644 index 0000000000..f6d635a32a --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationRequest.cs @@ -0,0 +1,24 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Lightweight value-type carrier for an in-flight LuaLS document synchronization request. Returned +/// from as a nullable so the per-keystroke +/// path does not allocate a heap instance for every character. +/// +internal readonly record struct LuaDocumentSynchronizationRequest( + LuaDocumentSynchronizationKind Kind, + LuaDocumentSnapshot Document, + LuaDocumentChangeRange? ChangeRange = null); + +/// +/// Describes a single incremental `textDocument/didChange` range edit computed from the difference +/// between the previously-synced and newly-synced document contents. +/// +internal readonly record struct LuaDocumentChangeRange( + int StartLine, + int StartCharacter, + int EndLine, + int EndCharacter, + string Text); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs new file mode 100644 index 0000000000..94100bf667 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs @@ -0,0 +1,81 @@ +#nullable enable + +using System; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Computes a minimal single-range edit that transforms oldText into newText using a +/// common-prefix / common-suffix scan. The result is suitable for an LSP `textDocument/didChange` +/// incremental notification: a server applying the returned range and replacement text to the old +/// content reproduces the new content byte-for-byte. +/// +internal static class LuaIncrementalEditCalculator +{ + public static LuaDocumentChangeRange Compute(string oldText, string newText, LuaDocumentLineOffsets oldOffsets) + { + oldText ??= string.Empty; + newText ??= string.Empty; + + int prefixLength = ComputeCommonPrefixLength(oldText, newText); + int suffixLength = ComputeCommonSuffixLength(oldText, newText, prefixLength); + + int oldEnd = oldText.Length - suffixLength; + int newEnd = newText.Length - suffixLength; + + string replacement = newEnd > prefixLength ? newText[prefixLength..newEnd] : string.Empty; + + (int startLine, int startCharacter) = OffsetToPosition(oldOffsets, prefixLength); + (int endLine, int endCharacter) = OffsetToPosition(oldOffsets, oldEnd); + + return new LuaDocumentChangeRange(startLine, startCharacter, endLine, endCharacter, replacement); + } + + private static int ComputeCommonPrefixLength(string a, string b) + { + int max = Math.Min(a.Length, b.Length); + int i = 0; + + while (i < max && a[i] == b[i]) + i++; + + return i; + } + + private static int ComputeCommonSuffixLength(string a, string b, int prefixLength) + { + int max = Math.Min(a.Length, b.Length) - prefixLength; + int i = 0; + + while (i < max && a[a.Length - 1 - i] == b[b.Length - 1 - i]) + i++; + + return i; + } + + private static (int Line, int Character) OffsetToPosition(LuaDocumentLineOffsets offsets, int offset) + { + int lineCount = offsets.LineCount; + + if (lineCount == 0) + return (0, 0); + + // Binary search across line start offsets. + int low = 0; + int high = lineCount - 1; + + while (low < high) + { + int mid = (low + high + 1) >>> 1; + + if (offsets.GetLineStartOffset(mid) <= offset) + low = mid; + else + high = mid - 1; + } + + int lineStart = offsets.GetLineStartOffset(low); + int character = Math.Max(0, offset - lineStart); + return (low, character); + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs index 8e2bb6f406..784d4a9b17 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs @@ -14,40 +14,45 @@ private sealed class DocumentState { public required string FilePath { get; init; } public required string Uri { get; init; } - public string? Content { get; set; } + public string Content { get; set; } = string.Empty; public int Version { get; set; } public bool IsOpen { get; set; } + + // Number of editor tabs that currently consider this document open. The provider only sends + // `textDocument/didClose` to LuaLS when this count returns to zero, so closing one tab while + // another tab still shows the same file does not strip diagnostics or semantic tokens from + // the surviving editor. + public int OpenReferenceCount { get; set; } + + public IReadOnlyList Diagnostics { get; set; } = []; + public int DiagnosticsVersion { get; set; } + + public IReadOnlyList SemanticTokens { get; set; } = []; + public int SemanticTokensVersion { get; set; } + + // Last raw `data` payload returned by `textDocument/semanticTokens/full(/delta)` for this + // file, kept around so an incoming delta `edits` payload can be applied without forcing the + // server to resend the entire token stream. + public int[]? SemanticTokensData { get; set; } + public string? SemanticTokensResultId { get; set; } } private readonly object _syncRoot = new(); - private readonly Dictionary _documents = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary> _diagnosticsByFilePath = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _diagnosticsVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary> _semanticTokensByFilePath = new(StringComparer.OrdinalIgnoreCase); - private readonly Dictionary _semanticTokensVersionByFilePath = new(StringComparer.OrdinalIgnoreCase); public IReadOnlyList GetDiagnostics(string filePath) { lock (_syncRoot) - { - return _diagnosticsByFilePath.TryGetValue(filePath, out IReadOnlyList? diagnostics) - ? diagnostics - : []; - } + return _documents.TryGetValue(filePath, out DocumentState? state) ? state.Diagnostics : []; } public IReadOnlyList GetSemanticTokens(string filePath) { lock (_syncRoot) - { - return _semanticTokensByFilePath.TryGetValue(filePath, out IReadOnlyList? semanticTokens) - ? semanticTokens - : []; - } + return _documents.TryGetValue(filePath, out DocumentState? state) ? state.SemanticTokens : []; } - public LuaDocumentSynchronizationRequest? Synchronize(string filePath, string content) + public LuaDocumentSynchronizationRequest? Synchronize(string filePath, string? content, bool acquireOpenReference = false) { string safeContent = content ?? string.Empty; @@ -61,13 +66,17 @@ public IReadOnlyList GetSemanticTokens(string filePath) Uri = LuaLanguageServerPathHelper.CreateFileUri(filePath), Content = safeContent, Version = 1, - IsOpen = true + IsOpen = true, + OpenReferenceCount = acquireOpenReference ? 1 : 0 }; _documents[filePath] = state; return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, CreateSnapshot(state)); } + if (acquireOpenReference) + state.OpenReferenceCount++; + if (!state.IsOpen) { state.Content = safeContent; @@ -78,15 +87,24 @@ public IReadOnlyList GetSemanticTokens(string filePath) if (!string.Equals(state.Content, safeContent, StringComparison.Ordinal)) { + string previousContent = state.Content; state.Content = safeContent; state.Version++; - return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Change, CreateSnapshot(state)); + + LuaDocumentLineOffsets previousOffsets = LuaDocumentLineOffsets.Build(previousContent); + LuaDocumentChangeRange changeRange = LuaIncrementalEditCalculator.Compute(previousContent, safeContent, previousOffsets); + return new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Change, CreateSnapshot(state), changeRange); } return null; } } + /// + /// Releases one open reference for . The document is only fully + /// removed (and a `didClose` snapshot returned) once the reference count drops to zero, + /// so multiple editor tabs sharing the same file do not invalidate each other on close. + /// public bool TryClose(string filePath, [NotNullWhen(true)] out LuaDocumentSnapshot? document) { lock (_syncRoot) @@ -97,21 +115,37 @@ public bool TryClose(string filePath, [NotNullWhen(true)] out LuaDocumentSnapsho return false; } - state.IsOpen = false; + if (state.OpenReferenceCount > 0) + state.OpenReferenceCount--; + + if (state.OpenReferenceCount > 0) + { + document = null; + return false; + } + document = CreateSnapshot(state); + _documents.Remove(filePath); return true; } } - public void PrepareForRestart() + public IReadOnlyList PrepareForRestart() { lock (_syncRoot) { + var documentsToReopen = new List(); + foreach (DocumentState state in _documents.Values) { - if (state.IsOpen) - state.IsOpen = false; + if (!state.IsOpen) + continue; + + documentsToReopen.Add(CreateSnapshot(state)); + state.IsOpen = false; } + + return documentsToReopen; } } @@ -125,21 +159,36 @@ public void PrepareForRestart() } } - public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) + public IReadOnlyList GetOpenDocuments() { lock (_syncRoot) { - if (publishedDiagnostics.Version > 0 - && _diagnosticsVersionByFilePath.TryGetValue(publishedDiagnostics.FilePath, out int currentVersion) - && publishedDiagnostics.Version < currentVersion) + var documents = new List(); + + foreach (DocumentState state in _documents.Values) { - return false; + if (state.IsOpen) + documents.Add(CreateSnapshot(state)); } + return documents; + } + } + + public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) + { + lock (_syncRoot) + { + if (!_documents.TryGetValue(publishedDiagnostics.FilePath, out DocumentState? state)) + return false; + + if (IsStaleVersion(state.DiagnosticsVersion, publishedDiagnostics.Version)) + return false; + if (publishedDiagnostics.Version > 0) - _diagnosticsVersionByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Version; + state.DiagnosticsVersion = publishedDiagnostics.Version; - _diagnosticsByFilePath[publishedDiagnostics.FilePath] = publishedDiagnostics.Diagnostics; + state.Diagnostics = publishedDiagnostics.Diagnostics; return true; } } @@ -148,41 +197,54 @@ public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList 0 - && _semanticTokensVersionByFilePath.TryGetValue(filePath, out int currentVersion) - && version < currentVersion) - { + if (!_documents.TryGetValue(filePath, out DocumentState? state)) + return false; + + if (IsStaleVersion(state.SemanticTokensVersion, version)) return false; - } if (version > 0) - _semanticTokensVersionByFilePath[filePath] = version; + state.SemanticTokensVersion = version; - _semanticTokensByFilePath[filePath] = semanticTokens ?? []; + state.SemanticTokens = semanticTokens ?? []; return true; } } - private static LuaDocumentSnapshot CreateSnapshot(DocumentState state) - => new(state.FilePath, state.Uri, state.Content, state.Version); -} + /// + /// Returns the cached semantic-tokens delta state for , if any. + /// Used by the provider to send `semanticTokens/full/delta` requests with the previous result id. + /// + public (string? PreviousResultId, int[]? PreviousData) GetSemanticTokensDeltaState(string filePath) + { + lock (_syncRoot) + { + if (!_documents.TryGetValue(filePath, out DocumentState? state)) + return (null, null); -internal enum LuaDocumentSynchronizationKind -{ - Open, - Change -} + return (state.SemanticTokensResultId, state.SemanticTokensData); + } + } -internal sealed class LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind kind, LuaDocumentSnapshot document) -{ - public LuaDocumentSynchronizationKind Kind { get; } = kind; - public LuaDocumentSnapshot Document { get; } = document ?? throw new ArgumentNullException(nameof(document)); -} + /// + /// Stores the raw `data` payload returned by `semanticTokens/full(/delta)` along with the + /// associated `resultId`, so subsequent requests can ask LuaLS for incremental edits. + /// + public void StoreSemanticTokensDeltaState(string filePath, string? resultId, int[]? data) + { + lock (_syncRoot) + { + if (!_documents.TryGetValue(filePath, out DocumentState? state)) + return; -internal sealed class LuaDocumentSnapshot(string filePath, string uri, string? content, int version) -{ - public string FilePath { get; } = filePath; - public string Uri { get; } = uri; - public string Content { get; } = content ?? string.Empty; - public int Version { get; } = version; + state.SemanticTokensResultId = resultId; + state.SemanticTokensData = data; + } + } + + private static bool IsStaleVersion(int currentVersion, int incomingVersion) + => incomingVersion > 0 && currentVersion > 0 && incomingVersion < currentVersion; + + private static LuaDocumentSnapshot CreateSnapshot(DocumentState state) + => new(state.FilePath, state.Uri, state.Content, state.Version); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs new file mode 100644 index 0000000000..3571de212d --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs @@ -0,0 +1,220 @@ +#nullable enable + +using System; +using System.Buffers; +using System.Buffers.Text; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed partial class LuaLanguageServerClient +{ + private Task SendNotificationCoreAsync(string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) + => WriteMessageAsync(new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken, allowDisposed); + + private async Task SendRequestCoreAsync(string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) + { + ThrowIfDisposed(allowDisposed); + + long requestId = Interlocked.Increment(ref _requestId); + var responseSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + if (!_pendingRequests.TryAdd(requestId, responseSource)) + throw new InvalidOperationException("Unable to track a new language server request."); + + await using var registration = cancellationToken.Register(() => responseSource.TrySetCanceled(cancellationToken)); + + try + { + await WriteMessageAsync(new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken, allowDisposed).ConfigureAwait(false); + return await responseSource.Task.ConfigureAwait(false); + } + catch (OperationCanceledException) + { + SendCancelNotification(requestId); + throw; + } + finally + { + _pendingRequests.TryRemove(requestId, out _); + } + } + + private void SendCancelNotification(long requestId) + { + if (_isDisposed || _outputStream is null) + return; + + Task.Run(async () => + { + try + { + await WriteMessageAsync(new { jsonrpc = "2.0", method = "$/cancelRequest", @params = new { id = requestId } }, CancellationToken.None, allowDisposed: true).ConfigureAwait(false); + } + catch + { + // Best-effort: cancellation notifications are advisory. + } + }); + } + + private async Task HandleServerRequestAsync(JsonElement idElement, string method, JsonElement parameters) + { + switch (method) + { + case "workspace/configuration": + await WriteResponseAsync(idElement, BuildConfigurationResponse(parameters)).ConfigureAwait(false); + return; + + case "workspace/workspaceFolders": + await WriteResponseAsync(idElement, BuildWorkspaceFolderResponse()).ConfigureAwait(false); + return; + + case "workspace/semanticTokens/refresh": + try + { + SemanticTokensRefreshRequested?.Invoke(); + } + catch (Exception exception) + { + Log.Warn(exception, "Lua semantic-tokens refresh request handler threw; acknowledging the request anyway."); + } + + await WriteResponseAsync(idElement, result: null).ConfigureAwait(false); + return; + + case "client/registerCapability": + case "client/unregisterCapability": + case "window/workDoneProgress/create": + // Acknowledge with a successful empty result so the server can proceed. + await WriteResponseAsync(idElement, result: null).ConfigureAwait(false); + return; + + default: + // Reply with JSON-RPC "Method Not Found" (-32601) for everything else so the server does not block on us. + await WriteErrorResponseAsync(idElement, code: -32601, message: $"Method '{method}' is not supported by the client.").ConfigureAwait(false); + return; + } + } + + private Task WriteResponseAsync(JsonElement idElement, object? result) + => WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None, allowDisposed: true); + + private Task WriteErrorResponseAsync(JsonElement idElement, int code, string message) + => WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, error = new { code, message } }, CancellationToken.None, allowDisposed: true); + + private object[] BuildConfigurationResponse(JsonElement parameters) + { + if (!parameters.TryGetProperty("items", out JsonElement itemsElement) || itemsElement.ValueKind != JsonValueKind.Array) + return []; + + JsonElement settingsElement = JsonSerializer.SerializeToElement(_settingsProvider()); + JsonElement luaElement = settingsElement.GetProperty("Lua"); + + var results = new List(); + + foreach (JsonElement item in itemsElement.EnumerateArray()) + { + string? section = item.TryGetProperty("section", out JsonElement sectionElement) + ? sectionElement.GetString() + : null; + + results.Add(GetConfigurationSection(settingsElement, luaElement, section)); + } + + return [.. results]; + } + + private static object GetConfigurationSection(JsonElement settingsElement, JsonElement luaElement, string? section) + { + if (string.IsNullOrWhiteSpace(section)) + return settingsElement.Clone(); + + if (section.Equals("Lua", StringComparison.OrdinalIgnoreCase)) + return luaElement.Clone(); + + if (section.StartsWith("Lua.", StringComparison.OrdinalIgnoreCase)) + { + JsonElement nestedSection = luaElement; + string[] parts = section[4..].Split('.'); + + foreach (string part in parts) + { + if (!nestedSection.TryGetProperty(part, out JsonElement nextSection)) + return new { }; + + nestedSection = nextSection; + } + + return nestedSection.Clone(); + } + + return new { }; + } + + private object[] BuildWorkspaceFolderResponse() => + [ + new + { + uri = LuaLanguageServerPathHelper.CreateFileUri(_workspaceRootDirectoryPath), + name = Path.GetFileName(_workspaceRootDirectoryPath) + } + ]; + + private async Task WriteMessageAsync(object payload, CancellationToken cancellationToken, bool allowDisposed) + { + ThrowIfDisposed(allowDisposed); + + if (_outputStream is null) + throw new IOException("The Lua language server output stream is not available."); + + byte[] payloadBytes = JsonSerializer.SerializeToUtf8Bytes(payload); + + // Header layout: "Content-Length: \r\n\r\n". Worst-case digits fit comfortably in 32 bytes. + const int HeaderReserve = 64; + byte[] frameBuffer = ArrayPool.Shared.Rent(HeaderReserve + payloadBytes.Length); + int headerLength = WriteContentLengthHeader(frameBuffer, payloadBytes.Length); + int frameLength = headerLength + payloadBytes.Length; + + try + { + Buffer.BlockCopy(payloadBytes, 0, frameBuffer, headerLength, payloadBytes.Length); + + await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + + try + { + await _outputStream.WriteAsync(frameBuffer.AsMemory(0, frameLength), cancellationToken).ConfigureAwait(false); + await _outputStream.FlushAsync(cancellationToken).ConfigureAwait(false); + } + finally + { + _writeLock.Release(); + } + } + finally + { + ArrayPool.Shared.Return(frameBuffer); + } + } + + private static int WriteContentLengthHeader(Span destination, int payloadLength) + { + ReadOnlySpan prefix = "Content-Length: "u8; + ReadOnlySpan terminator = "\r\n\r\n"u8; + + prefix.CopyTo(destination); + int position = prefix.Length; + + if (!Utf8Formatter.TryFormat(payloadLength, destination[position..], out int digitsWritten)) + throw new InvalidOperationException("Failed to encode the LSP Content-Length header."); + + position += digitsWritten; + terminator.CopyTo(destination[position..]); + return position + terminator.Length; + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs new file mode 100644 index 0000000000..332e7bea0b --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs @@ -0,0 +1,377 @@ +#nullable enable + +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Channels; +using System.Threading.Tasks; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed partial class LuaLanguageServerClient +{ + private async Task ReadLoopAsync() + { + Exception? failure = null; + + try + { + while (!_isDisposed) + { + int? contentLengthValue = await ReadHeadersAsync().ConfigureAwait(false); + + if (contentLengthValue is null || !TryAcceptPayloadSize(contentLengthValue.Value, out int contentLength)) + break; + + byte[]? payloadBytes = await ReadPayloadAsync(contentLength).ConfigureAwait(false); + + if (payloadBytes is null) + break; + + using JsonDocument document = JsonDocument.Parse(payloadBytes); + await HandleMessageAsync(document.RootElement).ConfigureAwait(false); + } + } + catch (Exception exception) + { + failure = exception; + } + finally + { + IsReady = false; + + if (!_pendingRequests.IsEmpty) + FailPendingRequests(failure ?? new IOException("The Lua language server connection was closed.")); + } + } + + private async Task ReadStandardErrorLoopAsync() + { + try + { + while (!_isDisposed) + { + Process? process = _process; + + if (process is null || process.HasExited) + break; + + string? line = await process.StandardError.ReadLineAsync(_lifetimeCts.Token).ConfigureAwait(false); + + if (line is null) + break; + + if (!string.IsNullOrWhiteSpace(line)) + Log.Debug("[LuaLS stderr] {Line}", line); + } + } + catch (OperationCanceledException) + { } + catch + { + // Ignore stderr read failures. + } + } + + private async Task ReadHeadersAsync() + { + while (true) + { + int headerTerminatorIndex = FindHeaderTerminatorIndex(); + + if (headerTerminatorIndex >= 0) + return ConsumeHeaders(headerTerminatorIndex); + + if (!await ReadIntoReceiveBufferAsync().ConfigureAwait(false)) + return null; + } + } + + private int? ConsumeHeaders(int headerTerminatorIndex) + { + string headerText = Encoding.ASCII.GetString(_receiveBuffer, 0, headerTerminatorIndex); + ConsumeReceiveBuffer(headerTerminatorIndex + HeaderTerminator.Length); + return ExtractContentLength(headerText); + } + + private static int? ExtractContentLength(string headerText) + { + foreach (string line in headerText.Split(["\r\n"], StringSplitOptions.RemoveEmptyEntries)) + { + int separatorIndex = line.IndexOf(':'); + + if (separatorIndex <= 0) + continue; + + ReadOnlySpan key = line.AsSpan(0, separatorIndex).Trim(); + + if (!key.Equals("Content-Length".AsSpan(), StringComparison.OrdinalIgnoreCase)) + continue; + + ReadOnlySpan value = line.AsSpan(separatorIndex + 1).Trim(); + + if (int.TryParse(value, out int parsedContentLength) && parsedContentLength > 0) + return parsedContentLength; + + return null; + } + + return null; + } + + private int FindHeaderTerminatorIndex() + => new ReadOnlySpan(_receiveBuffer, 0, _receiveBufferCount).IndexOf(HeaderTerminator); + + private async Task ReadIntoReceiveBufferAsync() + { + if (_inputStream is null) + return false; + + EnsureReceiveBufferCapacity(_receiveBufferCount + ReceiveChunkSize); + + int bytesAvailable = _receiveBuffer.Length - _receiveBufferCount; + int bytesRead = await _inputStream + .ReadAsync(_receiveBuffer.AsMemory(_receiveBufferCount, bytesAvailable), _lifetimeCts.Token) + .ConfigureAwait(false); + + if (bytesRead == 0) + return false; + + _receiveBufferCount += bytesRead; + return true; + } + + private void EnsureReceiveBufferCapacity(int requiredCapacity) + { + if (_receiveBuffer.Length >= requiredCapacity) + return; + + int newCapacity = Math.Max(ReceiveChunkSize, _receiveBuffer.Length); + + while (newCapacity < requiredCapacity) + newCapacity *= 2; + + byte[] newBuffer = ArrayPool.Shared.Rent(newCapacity); + + if (_receiveBufferCount > 0) + Buffer.BlockCopy(_receiveBuffer, 0, newBuffer, 0, _receiveBufferCount); + + ReturnReceiveBuffer(); + _receiveBuffer = newBuffer; + } + + private void ReturnReceiveBuffer() + { + if (_receiveBuffer.Length == 0) + return; + + ArrayPool.Shared.Return(_receiveBuffer, clearArray: false); + _receiveBuffer = []; + } + + private void ConsumeReceiveBuffer(int bytesToConsume) + { + int remainingBytes = _receiveBufferCount - bytesToConsume; + + if (remainingBytes > 0) + Buffer.BlockCopy(_receiveBuffer, bytesToConsume, _receiveBuffer, 0, remainingBytes); + + _receiveBufferCount = Math.Max(0, remainingBytes); + } + + private async Task ReadPayloadAsync(int contentLength) + { + if (_inputStream is null) + return null; + + byte[] payloadBytes = new byte[contentLength]; + int totalBytesRead = 0; + + if (_receiveBufferCount > 0) + { + int bufferedBytesToCopy = Math.Min(contentLength, _receiveBufferCount); + Buffer.BlockCopy(_receiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); + ConsumeReceiveBuffer(bufferedBytesToCopy); + totalBytesRead = bufferedBytesToCopy; + } + + while (totalBytesRead < contentLength) + { + int bytesRead = await _inputStream + .ReadAsync(payloadBytes.AsMemory(totalBytesRead, contentLength - totalBytesRead), _lifetimeCts.Token) + .ConfigureAwait(false); + + if (bytesRead == 0) + return null; + + totalBytesRead += bytesRead; + } + + return payloadBytes; + } + + private async Task HandleMessageAsync(JsonElement message) + { + bool hasId = message.TryGetProperty("id", out JsonElement idElement); + bool hasMethod = message.TryGetProperty("method", out JsonElement methodElement); + + if (hasId && !hasMethod) + { + HandleServerResponse(idElement, message); + return; + } + + if (!hasMethod) + return; + + string? method = methodElement.GetString(); + + if (string.IsNullOrWhiteSpace(method)) + return; + + JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) + ? paramsElement.Clone() + : default; + + if (hasId) + await HandleServerRequestAsync(idElement.Clone(), method, parameters).ConfigureAwait(false); + else + HandleServerNotification(method, parameters); + } + + private void HandleServerResponse(JsonElement idElement, JsonElement message) + { + if (!idElement.TryGetInt64(out long requestId)) + return; + + if (!_pendingRequests.TryGetValue(requestId, out TaskCompletionSource? responseSource)) + { + Log.Debug("Received Lua language server response with no matching pending request (id={RequestId}).", requestId); + return; + } + + if (message.TryGetProperty("error", out JsonElement errorElement)) + { + string messageText = errorElement.TryGetProperty("message", out JsonElement errorMessageElement) + ? errorMessageElement.GetString() ?? "Lua language server request failed." + : "Lua language server request failed."; + + responseSource.TrySetException(new InvalidOperationException(messageText)); + return; + } + + if (message.TryGetProperty("result", out JsonElement resultElement)) + responseSource.TrySetResult(resultElement.Clone()); + else + responseSource.TrySetResult(default); + } + + private void HandleServerNotification(string method, JsonElement parameters) + { + switch (method) + { + case "textDocument/publishDiagnostics": + RaiseDiagnosticsPublished(parameters); + return; + + case "window/logMessage": + case "window/showMessage": + LogServerMessage(method, parameters); + return; + + case "telemetry/event": + case "$/progress": + return; + } + } + + private void RaiseDiagnosticsPublished(JsonElement parameters) + { + // Stash only the newest diagnostics payload per file and wake the pump if it is idle. + // Parameters were already cloned by the dispatcher in HandleMessageAsync. + _pendingDiagnostics[GetDiagnosticsQueueKey(parameters)] = parameters; + _diagnosticsSignal.Writer.TryWrite(true); + } + + private async Task PumpDiagnosticsAsync() + { + ChannelReader reader = _diagnosticsSignal.Reader; + + try + { + while (await reader.WaitToReadAsync(_lifetimeCts.Token).ConfigureAwait(false)) + { + while (reader.TryRead(out _)) + { } + + while (!_pendingDiagnostics.IsEmpty) + { + KeyValuePair[] pendingDiagnostics = [.. _pendingDiagnostics]; + + for (int i = 0; i < pendingDiagnostics.Length; i++) + { + if (!_pendingDiagnostics.TryRemove(pendingDiagnostics[i].Key, out JsonElement parameters)) + continue; + + try + { + DiagnosticsPublished?.Invoke(parameters); + } + catch (Exception exception) + { + Log.Warn(exception, "Lua diagnostics handler threw; the diagnostics pump is being kept alive."); + } + } + } + } + } + catch (OperationCanceledException) + { + // Expected on dispose. + } + } + + private string GetDiagnosticsQueueKey(JsonElement parameters) + { + if (parameters.ValueKind == JsonValueKind.Object + && parameters.TryGetProperty("uri", out JsonElement uriElement) + && uriElement.ValueKind == JsonValueKind.String) + { + string? uri = uriElement.GetString(); + + if (!string.IsNullOrWhiteSpace(uri)) + return uri; + } + + return "diagnostics:" + Interlocked.Increment(ref _diagnosticsFallbackSequence); + } + + private static void LogServerMessage(string method, JsonElement parameters) + { + if (parameters.ValueKind != JsonValueKind.Object) + return; + + string? messageText = parameters.TryGetProperty("message", out JsonElement messageElement) + ? messageElement.GetString() + : null; + + if (string.IsNullOrWhiteSpace(messageText)) + return; + + int messageType = parameters.TryGetProperty("type", out JsonElement typeElement) + && typeElement.TryGetInt32(out int parsedType) ? parsedType : 4; + + switch (messageType) + { + case 1: Log.Error("[LuaLS {Method}] {Message}", method, messageText); break; + case 2: Log.Warn("[LuaLS {Method}] {Message}", method, messageText); break; + case 3: Log.Info("[LuaLS {Method}] {Message}", method, messageText); break; + default: Log.Debug("[LuaLS {Method}] {Message}", method, messageText); break; + } + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index a372d9ec2e..3d0b4516f5 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -1,20 +1,25 @@ #nullable enable +using NLog; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Text; using System.Text.Json; using System.Threading; +using System.Threading.Channels; using System.Threading.Tasks; namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; -internal sealed class LuaLanguageServerClient : IDisposable +internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private const int ReceiveChunkSize = 4096; + private const int MaxPayloadByteCount = 64 * 1024 * 1024; // 64 MiB safety cap for inbound LSP payloads. + private static readonly TimeSpan DisposeWaitTimeout = TimeSpan.FromSeconds(3); private static readonly byte[] HeaderTerminator = [(byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n']; private readonly string _workspaceRootDirectoryPath; @@ -23,7 +28,23 @@ internal sealed class LuaLanguageServerClient : IDisposable private readonly SemaphoreSlim _startLock = new(1, 1); private readonly SemaphoreSlim _writeLock = new(1, 1); + private readonly CancellationTokenSource _lifetimeCts = new(); private readonly ConcurrentDictionary> _pendingRequests = new(); + private readonly ConcurrentDictionary _pendingDiagnostics = new(StringComparer.OrdinalIgnoreCase); + + // Diagnostics arrive on the LSP read loop and are stored as the latest payload per file URI. + // A bounded single-slot channel acts only as a wake signal for the pump, so bursty notifications + // for the same file collapse to one queued wake-up instead of building an unbounded backlog. + private readonly Channel _diagnosticsSignal = Channel.CreateBounded( + new BoundedChannelOptions(1) + { + SingleReader = true, + SingleWriter = true, + AllowSynchronousContinuations = false, + FullMode = BoundedChannelFullMode.DropWrite + }); + + private Task? _diagnosticsPumpTask; private static readonly string[] SupportedSemanticTokenTypes = [ @@ -40,7 +61,9 @@ internal sealed class LuaLanguageServerClient : IDisposable ]; private long _requestId; - private bool _isDisposed; + private long _diagnosticsFallbackSequence; + private volatile bool _isDisposed; + private volatile bool _isReady; private Process? _process; private Stream? _inputStream; @@ -52,13 +75,21 @@ internal sealed class LuaLanguageServerClient : IDisposable private string[] _semanticTokenTypes = []; private string[] _semanticTokenModifiers = []; private bool _supportsCompletionResolve; + private bool _supportsSemanticTokensDelta; + + public bool IsReady + { + get => _isReady; + private set => _isReady = value; + } - public bool IsReady { get; private set; } public IReadOnlyList SemanticTokenTypes => _semanticTokenTypes; public IReadOnlyList SemanticTokenModifiers => _semanticTokenModifiers; public bool SupportsCompletionResolve => _supportsCompletionResolve; + public bool SupportsSemanticTokensDelta => _supportsSemanticTokensDelta; public event Action? DiagnosticsPublished; + public event Action? SemanticTokensRefreshRequested; public LuaLanguageServerClient(string workspaceRootDirectoryPath, string serverExecutablePath, Func settingsProvider) { @@ -79,7 +110,7 @@ public async Task StartAsync(CancellationToken cancellationToken) if (IsReady) return true; - ThrowIfDisposed(); + ThrowIfDisposed(allowDisposed: false); ResetProcessState(); var startInfo = new ProcessStartInfo @@ -99,11 +130,15 @@ public async Task StartAsync(CancellationToken cancellationToken) if (!_process.Start()) return false; + if (OperatingSystem.IsWindows()) + LuaProcessJobObject.TryAssignProcess(_process); + _inputStream = _process.StandardOutput.BaseStream; _outputStream = _process.StandardInput.BaseStream; _readLoopTask = Task.Run(ReadLoopAsync, CancellationToken.None); _stderrLoopTask = Task.Run(ReadStandardErrorLoopAsync, CancellationToken.None); + _diagnosticsPumpTask ??= Task.Run(PumpDiagnosticsAsync, CancellationToken.None); using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); @@ -118,8 +153,16 @@ public async Task StartAsync(CancellationToken cancellationToken) return true; } - catch + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { + await DisposeProcessAsync().ConfigureAwait(false); + throw; + } + catch (Exception exception) + { + Log.Warn(exception, "Failed to start the Lua language server (executable='{Executable}', workspace='{Workspace}').", + _serverExecutablePath, _workspaceRootDirectoryPath); + await DisposeProcessAsync().ConfigureAwait(false); return false; } @@ -130,30 +173,10 @@ public async Task StartAsync(CancellationToken cancellationToken) } public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) - => WriteMessageAsync(new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken); + => SendNotificationCoreAsync(method, parameters, cancellationToken, allowDisposed: false); - public async Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) - { - ThrowIfDisposed(); - - long requestId = Interlocked.Increment(ref _requestId); - var responseSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - if (!_pendingRequests.TryAdd(requestId, responseSource)) - throw new InvalidOperationException("Unable to track a new language server request."); - - await using var registration = cancellationToken.Register(() => responseSource.TrySetCanceled(cancellationToken)); - - try - { - await WriteMessageAsync(new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken).ConfigureAwait(false); - return await responseSource.Task.ConfigureAwait(false); - } - finally - { - _pendingRequests.TryRemove(requestId, out _); - } - } + public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) + => SendRequestCoreAsync(method, parameters, cancellationToken, allowDisposed: false); private object BuildInitializeParams() => new { @@ -162,15 +185,19 @@ public async Task SendRequestAsync(string method, object parameters { changeConfiguration = true, viewDocument = true, - trustByClient = true, - useSemanticByRange = true + // Do NOT set trustByClient = true: LuaLS uses that flag to skip the user prompt before + // loading workspace-supplied plugins (runtime.plugin in .luarc.json). TombIDE has no + // equivalent workspace-trust gate, so leaving the prompt enabled keeps malicious or + // accidental third-party Lua scripts from being executed silently inside the host process. + trustByClient = false, + useSemanticByRange = false }, - rootUri = CreateFileUri(_workspaceRootDirectoryPath), + rootUri = LuaLanguageServerPathHelper.CreateFileUri(_workspaceRootDirectoryPath), workspaceFolders = new[] { new { - uri = CreateFileUri(_workspaceRootDirectoryPath), + uri = LuaLanguageServerPathHelper.CreateFileUri(_workspaceRootDirectoryPath), name = Path.GetFileName(_workspaceRootDirectoryPath) } }, @@ -179,7 +206,8 @@ public async Task SendRequestAsync(string method, object parameters workspace = new { workspaceFolders = true, - configuration = true + configuration = true, + didChangeWatchedFiles = new { dynamicRegistration = false } }, textDocument = new { @@ -189,7 +217,8 @@ public async Task SendRequestAsync(string method, object parameters completionItem = new { snippetSupport = false, - documentationFormat = new[] { "plaintext", "markdown" }, + // Prefer markdown so the editor's MdXaml renderer can show formatted documentation. + documentationFormat = new[] { "markdown", "plaintext" }, resolveSupport = new { properties = new[] { "detail", "documentation" } @@ -198,7 +227,7 @@ public async Task SendRequestAsync(string method, object parameters }, hover = new { - contentFormat = new[] { "plaintext", "markdown" } + contentFormat = new[] { "markdown", "plaintext" } }, definition = new { @@ -212,7 +241,7 @@ public async Task SendRequestAsync(string method, object parameters { signatureInformation = new { - documentationFormat = new[] { "plaintext", "markdown" }, + documentationFormat = new[] { "markdown", "plaintext" }, parameterInformation = new { labelOffsetSupport = true @@ -224,7 +253,8 @@ public async Task SendRequestAsync(string method, object parameters { requests = new { - range = true + range = false, + full = new { delta = true } }, tokenTypes = SupportedSemanticTokenTypes, tokenModifiers = SupportedSemanticTokenModifiers, @@ -240,23 +270,32 @@ public async Task SendRequestAsync(string method, object parameters private void CaptureServerCapabilities(JsonElement initializeResponse) { _supportsCompletionResolve = false; + _supportsSemanticTokensDelta = false; _semanticTokenTypes = []; _semanticTokenModifiers = []; - if (initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities) - && capabilities.TryGetProperty("completionProvider", out JsonElement completionProvider) + if (!initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities)) + return; + + if (capabilities.TryGetProperty("completionProvider", out JsonElement completionProvider) && completionProvider.TryGetProperty("resolveProvider", out JsonElement resolveProvider)) { _supportsCompletionResolve = resolveProvider.ValueKind == JsonValueKind.True; } - if (!initializeResponse.TryGetProperty("capabilities", out capabilities) - || !capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider) - || !semanticTokensProvider.TryGetProperty("legend", out JsonElement legend)) - { + if (!capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider)) return; + + if (semanticTokensProvider.TryGetProperty("full", out JsonElement fullElement)) + { + _supportsSemanticTokensDelta = fullElement.ValueKind == JsonValueKind.Object + && fullElement.TryGetProperty("delta", out JsonElement deltaElement) + && deltaElement.ValueKind == JsonValueKind.True; } + if (!semanticTokensProvider.TryGetProperty("legend", out JsonElement legend)) + return; + _semanticTokenTypes = ReadStringArray(legend, "tokenTypes"); _semanticTokenModifiers = ReadStringArray(legend, "tokenModifiers"); } @@ -282,417 +321,132 @@ private static string[] ReadStringArray(JsonElement parent, string propertyName) return [.. values]; } - private async Task ReadLoopAsync() + private void Process_Exited(object? sender, EventArgs e) { - try - { - while (!_isDisposed) - { - Dictionary? headers = await ReadHeadersAsync().ConfigureAwait(false); - - if (headers is null || !headers.TryGetValue("Content-Length", out string? contentLengthValue) - || string.IsNullOrWhiteSpace(contentLengthValue) - || !int.TryParse(contentLengthValue, out int contentLength) || contentLength <= 0) - { - break; - } + IsReady = false; - byte[]? payloadBytes = await ReadPayloadAsync(contentLength).ConfigureAwait(false); + int? exitCode = TryReadProcessExitCode(sender as Process ?? _process); - if (payloadBytes is null) - break; + if (!_isDisposed) + Log.Warn("Lua language server process exited unexpectedly{ExitCodeSuffix}.", exitCode is not null ? $" with code {exitCode.Value}" : string.Empty); - using JsonDocument document = JsonDocument.Parse(payloadBytes); - await HandleMessageAsync(document.RootElement).ConfigureAwait(false); - } - } - catch (Exception exception) - { - FailPendingRequests(exception); - } - finally - { - IsReady = false; - } + FailPendingRequests(new IOException("The Lua language server process exited unexpectedly.")); } - private async Task ReadStandardErrorLoopAsync() + private static int? TryReadProcessExitCode(Process? process) { - try - { - while (!_isDisposed) - { - Process? process = _process; - - if (process is null || process.HasExited) - break; - - string? line = await process.StandardError.ReadLineAsync().ConfigureAwait(false); - - if (line is null) - break; + if (process is null) + return null; - if (!string.IsNullOrWhiteSpace(line)) - Debug.WriteLine($"[LuaLS stderr] {line}"); - } - } - catch + try { - // Ignore stderr read failures. + return process.HasExited ? process.ExitCode : null; } - } - - private async Task?> ReadHeadersAsync() - { - while (true) + catch (InvalidOperationException) { - int headerTerminatorIndex = FindHeaderTerminatorIndex(); - - if (headerTerminatorIndex >= 0) - return ConsumeHeaders(headerTerminatorIndex); - - if (!await ReadIntoReceiveBufferAsync().ConfigureAwait(false)) - return null; + // Includes ObjectDisposedException; the process state is no longer accessible. + return null; } } - private Dictionary ConsumeHeaders(int headerTerminatorIndex) - { - string headerText = Encoding.ASCII.GetString(_receiveBuffer, 0, headerTerminatorIndex); - ConsumeReceiveBuffer(headerTerminatorIndex + HeaderTerminator.Length); - return ParseHeaders(headerText); - } - - private static Dictionary ParseHeaders(string headerText) + private static bool TryAcceptPayloadSize(int parsedContentLength, out int contentLength) { - var headers = new Dictionary(StringComparer.OrdinalIgnoreCase); - - foreach (string line in headerText.Split(["\r\n"], StringSplitOptions.RemoveEmptyEntries)) - { - int separatorIndex = line.IndexOf(':'); - - if (separatorIndex <= 0) - continue; - - string key = line[..separatorIndex].Trim(); - headers[key] = line[(separatorIndex + 1)..].Trim(); - } + contentLength = 0; - return headers; - } - - private int FindHeaderTerminatorIndex() - => new ReadOnlySpan(_receiveBuffer, 0, _receiveBufferCount).IndexOf(HeaderTerminator); - - private async Task ReadIntoReceiveBufferAsync() - { - if (_inputStream is null) + if (parsedContentLength <= 0) return false; - EnsureReceiveBufferCapacity(_receiveBufferCount + ReceiveChunkSize); - - int bytesToRead = Math.Min(ReceiveChunkSize, _receiveBuffer.Length - _receiveBufferCount); - int bytesRead = await _inputStream - .ReadAsync(_receiveBuffer.AsMemory(_receiveBufferCount, bytesToRead)) - .ConfigureAwait(false); - - if (bytesRead == 0) + if (parsedContentLength > MaxPayloadByteCount) + { + Log.Warn("Refusing Lua language server payload of {Bytes} bytes (cap is {Cap}).", parsedContentLength, MaxPayloadByteCount); return false; + } - _receiveBufferCount += bytesRead; + contentLength = parsedContentLength; return true; } - private void EnsureReceiveBufferCapacity(int requiredCapacity) - { - if (_receiveBuffer.Length >= requiredCapacity) - return; - - int newCapacity = Math.Max(ReceiveChunkSize, _receiveBuffer.Length); - - while (newCapacity < requiredCapacity) - newCapacity *= 2; - - Array.Resize(ref _receiveBuffer, newCapacity); - } - - private void ConsumeReceiveBuffer(int bytesToConsume) + private void FailPendingRequests(Exception exception) { - int remainingBytes = _receiveBufferCount - bytesToConsume; - - if (remainingBytes > 0) - Buffer.BlockCopy(_receiveBuffer, bytesToConsume, _receiveBuffer, 0, remainingBytes); - - _receiveBufferCount = Math.Max(0, remainingBytes); + foreach (KeyValuePair> pendingRequest in _pendingRequests) + pendingRequest.Value.TrySetException(exception); } - private async Task ReadPayloadAsync(int contentLength) + private async Task DisposeProcessAsync() { - if (_inputStream is null) - return null; - - byte[] payloadBytes = new byte[contentLength]; - int totalBytesRead = 0; - - if (_receiveBufferCount > 0) - { - int bufferedBytesToCopy = Math.Min(contentLength, _receiveBufferCount); - Buffer.BlockCopy(_receiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); - ConsumeReceiveBuffer(bufferedBytesToCopy); - totalBytesRead = bufferedBytesToCopy; - } - - while (totalBytesRead < contentLength) - { - int bytesRead = await _inputStream - .ReadAsync(payloadBytes.AsMemory(totalBytesRead, contentLength - totalBytesRead)) - .ConfigureAwait(false); + Task? readLoopTask = _readLoopTask; + Task? stderrLoopTask = _stderrLoopTask; - if (bytesRead == 0) - return null; - - totalBytesRead += bytesRead; - } - - return payloadBytes; - } - - private async Task HandleMessageAsync(JsonElement message) - { - if (message.TryGetProperty("id", out JsonElement idElement)) + try { - if (message.TryGetProperty("method", out JsonElement methodElement)) + if (_process is not null && !_process.HasExited) { - string? method = methodElement.GetString(); - - if (string.IsNullOrWhiteSpace(method)) - return; + await TrySendShutdownAsync().ConfigureAwait(false); + await TrySendExitNotificationAsync().ConfigureAwait(false); - JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) - ? paramsElement.Clone() - : default; - - await HandleServerRequestAsync(idElement.Clone(), method, parameters).ConfigureAwait(false); - } - else - { - HandleServerResponse(idElement, message); + if (!_process.HasExited) + _process.Kill(true); } } - else if (message.TryGetProperty("method", out JsonElement notificationMethodElement)) - { - string? method = notificationMethodElement.GetString(); - - if (string.IsNullOrWhiteSpace(method)) - return; - - JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) - ? paramsElement.Clone() - : default; - - HandleServerNotification(method, parameters); - } - } - - private void HandleServerResponse(JsonElement idElement, JsonElement message) - { - if (!idElement.TryGetInt64(out long requestId) || !_pendingRequests.TryGetValue(requestId, out TaskCompletionSource? responseSource)) - return; - - if (message.TryGetProperty("error", out JsonElement errorElement)) - { - string messageText = errorElement.TryGetProperty("message", out JsonElement errorMessageElement) - ? errorMessageElement.GetString() ?? "Lua language server request failed." - : "Lua language server request failed."; - - responseSource.TrySetException(new InvalidOperationException(messageText)); - return; - } - - if (message.TryGetProperty("result", out JsonElement resultElement)) - responseSource.TrySetResult(resultElement.Clone()); - else - responseSource.TrySetResult(default); - } - - private async Task HandleServerRequestAsync(JsonElement idElement, string method, JsonElement parameters) - { - object? result = method switch - { - "workspace/configuration" => BuildConfigurationResponse(parameters), - "workspace/workspaceFolders" => BuildWorkspaceFolderResponse(), - "client/registerCapability" => null, - "window/workDoneProgress/create" => null, - _ => null - }; - - await WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None).ConfigureAwait(false); - } - - private object[] BuildConfigurationResponse(JsonElement parameters) - { - if (!parameters.TryGetProperty("items", out JsonElement itemsElement) || itemsElement.ValueKind != JsonValueKind.Array) - return []; - - JsonElement settingsElement = JsonSerializer.SerializeToElement(_settingsProvider()); - JsonElement luaElement = settingsElement.GetProperty("Lua"); - - var results = new List(); - - foreach (JsonElement item in itemsElement.EnumerateArray()) - { - string? section = item.TryGetProperty("section", out JsonElement sectionElement) - ? sectionElement.GetString() - : null; - - results.Add(GetConfigurationSection(settingsElement, luaElement, section)); - } - - return [.. results]; - } - - private static object GetConfigurationSection(JsonElement settingsElement, JsonElement luaElement, string? section) - { - if (string.IsNullOrWhiteSpace(section)) - return settingsElement.Clone(); - - if (section.Equals("Lua", StringComparison.OrdinalIgnoreCase)) - return luaElement.Clone(); - - if (section.StartsWith("Lua.", StringComparison.OrdinalIgnoreCase)) + catch { - JsonElement nestedSection = luaElement; - string[] parts = section[4..].Split('.'); - - foreach (string part in parts) - { - if (!nestedSection.TryGetProperty(part, out JsonElement nextSection)) - return new { }; - - nestedSection = nextSection; - } - - return nestedSection.Clone(); + // Ignore process disposal failures. } - - return new { }; - } - - private object[] BuildWorkspaceFolderResponse() => - [ - new + finally { - uri = CreateFileUri(_workspaceRootDirectoryPath), - name = Path.GetFileName(_workspaceRootDirectoryPath) + ResetProcessState(); + IsReady = false; } - ]; - private void HandleServerNotification(string method, JsonElement parameters) - { - switch (method) - { - case "textDocument/publishDiagnostics": - DiagnosticsPublished?.Invoke(parameters); - return; - - case "window/logMessage": - case "window/showMessage": - case "telemetry/event": - case "$/progress": - return; - } + await WaitForBackgroundLoopsAsync(readLoopTask, stderrLoopTask, _diagnosticsPumpTask).ConfigureAwait(false); } - private async Task WriteMessageAsync(object payload, CancellationToken cancellationToken) + private async Task TrySendShutdownAsync() { - ThrowIfDisposed(); - - if (_outputStream is null) - throw new IOException("The Lua language server output stream is not available."); - - byte[] payloadBytes = JsonSerializer.SerializeToUtf8Bytes(payload); - byte[] headerBytes = Encoding.ASCII.GetBytes($"Content-Length: {payloadBytes.Length}\r\n\r\n"); - - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); + using var shutdownTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); try { - await _outputStream.WriteAsync(headerBytes.AsMemory(0, headerBytes.Length), cancellationToken).ConfigureAwait(false); - await _outputStream.WriteAsync(payloadBytes.AsMemory(0, payloadBytes.Length), cancellationToken).ConfigureAwait(false); - await _outputStream.FlushAsync(cancellationToken).ConfigureAwait(false); + await SendRequestCoreAsync("shutdown", new { }, shutdownTimeout.Token, allowDisposed: true).ConfigureAwait(false); } - finally + catch { - _writeLock.Release(); + // Ignore shutdown failures. } } - private void Process_Exited(object? sender, EventArgs e) + private async Task TrySendExitNotificationAsync() { - int? exitCode = null; + using var exitTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); try { - if (_process is not null && _process.HasExited) - exitCode = _process.ExitCode; + await SendNotificationCoreAsync("exit", new { }, exitTimeout.Token, allowDisposed: true).ConfigureAwait(false); } catch { - // Ignore exit-code access failures. + // Ignore exit notification failures. } - - IsReady = false; - - if (!_isDisposed) - Debug.WriteLine($"[LuaLS] Process exited unexpectedly{(exitCode is not null ? $" with code {exitCode.Value}" : string.Empty)}."); - - FailPendingRequests(new IOException("The Lua language server process exited unexpectedly.")); } - private void FailPendingRequests(Exception exception) + private static async Task WaitForBackgroundLoopsAsync(Task? readLoopTask, Task? stderrLoopTask, Task? diagnosticsPumpTask) { - foreach (KeyValuePair> pendingRequest in _pendingRequests) - pendingRequest.Value.TrySetException(exception); - } + Task combined = Task.WhenAll( + readLoopTask ?? Task.CompletedTask, + stderrLoopTask ?? Task.CompletedTask, + diagnosticsPumpTask ?? Task.CompletedTask); - private async Task DisposeProcessAsync() - { try { - if (_process is not null && !_process.HasExited) - { - using var shutdownTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); - - try - { - await SendRequestAsync("shutdown", new { }, shutdownTimeout.Token).ConfigureAwait(false); - } - catch - { - // Ignore shutdown failures. - } - - try - { - await SendNotificationAsync("exit", new { }, shutdownTimeout.Token).ConfigureAwait(false); - } - catch - { - // Ignore exit notification failures. - } - - if (!_process.HasExited) - _process.Kill(true); - } + await combined.WaitAsync(DisposeWaitTimeout).ConfigureAwait(false); } - catch + catch (TimeoutException) { - // Ignore process disposal failures. + Log.Warn("Lua language server background loops did not complete within the dispose timeout."); } - finally + catch { - ResetProcessState(); - IsReady = false; + // Ignore loop completion failures during disposal. } } @@ -722,7 +476,7 @@ private void ResetProcessState() _inputStream = null; _outputStream = null; _process = null; - _receiveBuffer = []; + ReturnReceiveBuffer(); _receiveBufferCount = 0; _readLoopTask = null; _stderrLoopTask = null; @@ -731,11 +485,11 @@ private void ResetProcessState() _semanticTokenModifiers = []; } - private void ThrowIfDisposed() - => ObjectDisposedException.ThrowIf(_isDisposed, nameof(LuaLanguageServerClient)); - - private static string CreateFileUri(string path) - => new Uri(Path.GetFullPath(path)).AbsoluteUri; + private void ThrowIfDisposed(bool allowDisposed) + { + if (!allowDisposed) + ObjectDisposedException.ThrowIf(_isDisposed, nameof(LuaLanguageServerClient)); + } public void Dispose() { @@ -744,9 +498,28 @@ public void Dispose() _isDisposed = true; FailPendingRequests(new ObjectDisposedException(nameof(LuaLanguageServerClient))); + _diagnosticsSignal.Writer.TryComplete(); + + try + { + _lifetimeCts.Cancel(); + } + catch (ObjectDisposedException) + { } - DisposeProcessAsync().GetAwaiter().GetResult(); + try + { + // DisposeProcessAsync also waits for the read/stderr loops, so by the time it returns no + // background task should still be holding the write semaphore. We then release the locks. + if (!DisposeProcessAsync().Wait(DisposeWaitTimeout)) + Log.Warn("Disposing Lua language server timed out; abandoning background tasks."); + } + catch (AggregateException exception) + { + Log.Warn(exception.Flatten(), "Disposing Lua language server raised exceptions."); + } + _lifetimeCts.Dispose(); _startLock.Dispose(); _writeLock.Dispose(); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs index af0f79d4b9..c54da83d02 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs @@ -1,10 +1,8 @@ #nullable enable -using ICSharpCode.AvalonEdit.Document; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.IO; using System.Linq; using System.Text; using System.Text.Json; @@ -18,7 +16,7 @@ internal static class LuaLanguageServerDiagnosticsParser /// Parses a LuaLS diagnostics notification into editor diagnostics for a tracked document. /// public static bool TryParse(JsonElement parameters, string filePath, - string? documentContent, int documentVersion, [NotNullWhen(true)] out LuaPublishedDiagnostics? publishedDiagnostics) + string documentContent, int documentVersion, [NotNullWhen(true)] out LuaPublishedDiagnostics? publishedDiagnostics) { publishedDiagnostics = null; @@ -35,43 +33,24 @@ public static bool TryParse(JsonElement parameters, string filePath, diagnosticsVersion = parsedVersion; } - if (diagnosticsVersion > 0 && documentVersion > 0 && diagnosticsVersion > documentVersion) + if (diagnosticsVersion > 0 && documentVersion > 0 && diagnosticsVersion != documentVersion) return false; - IReadOnlyList diagnostics = Array.Empty(); - string resolvedContent = ResolveDocumentContent(filePath, documentContent); + IReadOnlyList diagnostics = []; if (parameters.TryGetProperty("diagnostics", out JsonElement diagnosticsElement) && diagnosticsElement.ValueKind == JsonValueKind.Array) { - diagnostics = BuildDiagnostics(resolvedContent, diagnosticsElement); + diagnostics = BuildDiagnostics(documentContent, diagnosticsElement); } publishedDiagnostics = new LuaPublishedDiagnostics(filePath, diagnostics, diagnosticsVersion); return true; } - private static string ResolveDocumentContent(string filePath, string? documentContent) - { - if (!string.IsNullOrEmpty(documentContent)) - return documentContent; - - if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) - return string.Empty; - - try - { - return File.ReadAllText(filePath); - } - catch - { - return string.Empty; - } - } - private static IReadOnlyList BuildDiagnostics(string content, JsonElement diagnosticsElement) { - var document = new TextDocument(content); + LuaDocumentLineOffsets lineOffsets = LuaDocumentLineOffsets.Build(content); var diagnostics = new List(); foreach (JsonElement diagnosticElement in diagnosticsElement.EnumerateArray()) @@ -81,7 +60,7 @@ private static IReadOnlyList BuildDiagnostics(string conte if (severity > TextEditorDiagnosticSeverity.Warning) continue; - if (!TryCreateDiagnostic(document, diagnosticElement, severity, out TextEditorDiagnostic? diagnostic)) + if (!TryCreateDiagnostic(lineOffsets, diagnosticElement, severity, out TextEditorDiagnostic? diagnostic)) continue; diagnostics.Add(diagnostic); @@ -92,12 +71,12 @@ private static IReadOnlyList BuildDiagnostics(string conte .ThenBy(diagnostic => diagnostic.Severity)]; } - private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagnosticElement, + private static bool TryCreateDiagnostic(LuaDocumentLineOffsets lineOffsets, JsonElement diagnosticElement, TextEditorDiagnosticSeverity severity, [NotNullWhen(true)] out TextEditorDiagnostic? diagnostic) { diagnostic = null; - if (document.LineCount == 0 + if (lineOffsets.LineCount == 0 || !diagnosticElement.TryGetProperty("range", out JsonElement rangeElement) || !rangeElement.TryGetProperty("start", out JsonElement startElement) || startElement.ValueKind != JsonValueKind.Object @@ -107,7 +86,7 @@ private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagn return false; } - lineIndex = Math.Max(0, Math.Min(lineIndex, document.LineCount - 1)); + lineIndex = Math.Max(0, Math.Min(lineIndex, lineOffsets.LineCount - 1)); int startCharacter = startElement.TryGetProperty("character", out JsonElement characterElement) && characterElement.TryGetInt32(out int character) @@ -122,7 +101,7 @@ private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagn && endElement.TryGetProperty("line", out JsonElement endLineElement) && endLineElement.TryGetInt32(out int rawEndLineIndex)) { - endLineIndex = Math.Max(lineIndex, Math.Min(rawEndLineIndex, document.LineCount - 1)); + endLineIndex = Math.Max(lineIndex, Math.Min(rawEndLineIndex, lineOffsets.LineCount - 1)); if (endElement.TryGetProperty("character", out JsonElement endCharacterElement) && endCharacterElement.TryGetInt32(out int endCharacterValue)) @@ -131,7 +110,7 @@ private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagn } } - if (!TryGetDiagnosticOffsets(document, lineIndex, startCharacter, endLineIndex, endCharacter, + if (!TryGetDiagnosticOffsets(lineOffsets, lineIndex, startCharacter, endLineIndex, endCharacter, out int startOffset, out int endOffset)) { return false; @@ -141,35 +120,34 @@ private static bool TryCreateDiagnostic(TextDocument document, JsonElement diagn return true; } - private static bool TryGetDiagnosticOffsets(TextDocument document, + private static bool TryGetDiagnosticOffsets(LuaDocumentLineOffsets lineOffsets, int startLineIndex, int startCharacter, int endLineIndex, int endCharacter, out int startOffset, out int endOffset) { startOffset = 0; endOffset = 0; - if (document.LineCount == 0) + if (lineOffsets.LineCount == 0) return false; - DocumentLine startLine = document.GetLineByNumber(startLineIndex + 1); - DocumentLine endLine = document.GetLineByNumber(endLineIndex + 1); - startOffset = startLine.Offset + Math.Max(0, Math.Min(startCharacter, startLine.Length)); - endOffset = endLine.Offset + Math.Max(0, Math.Min(endCharacter, endLine.Length)); + startOffset = lineOffsets.GetOffset(startLineIndex, startCharacter); + endOffset = lineOffsets.GetOffset(endLineIndex, endCharacter); if (endOffset > startOffset) return true; - string lineText = document.GetText(startLine); + string lineText = lineOffsets.GetLineText(startLineIndex); + int lineStartOffset = lineOffsets.GetLineStartOffset(startLineIndex); if (string.IsNullOrEmpty(lineText)) - return false; + return TryGetEmptyLineFallbackOffsets(lineOffsets, startLineIndex, out startOffset, out endOffset); int safeCharacter = Math.Max(0, Math.Min(startCharacter, Math.Max(0, lineText.Length - 1))); if (TryGetWordBounds(lineText, safeCharacter, out int wordStart, out int wordEnd)) { - startOffset = startLine.Offset + wordStart; - endOffset = startLine.Offset + wordEnd; + startOffset = lineStartOffset + wordStart; + endOffset = lineStartOffset + wordEnd; return endOffset > startOffset; } @@ -184,16 +162,47 @@ private static bool TryGetDiagnosticOffsets(TextDocument document, if (trimmedEnd > trimmedStart) { - startOffset = startLine.Offset + trimmedStart; - endOffset = startLine.Offset + trimmedEnd; + startOffset = lineStartOffset + trimmedStart; + endOffset = lineStartOffset + trimmedEnd; return true; } - startOffset = startLine.Offset + safeCharacter; - endOffset = Math.Min(startOffset + 1, document.TextLength); + startOffset = lineStartOffset + safeCharacter; + endOffset = Math.Min(startOffset + 1, lineOffsets.TextLength); return endOffset > startOffset; } + private static bool TryGetEmptyLineFallbackOffsets(LuaDocumentLineOffsets lineOffsets, int lineIndex, + out int startOffset, out int endOffset) + { + startOffset = 0; + endOffset = 0; + + for (int nextLineIndex = lineIndex + 1; nextLineIndex < lineOffsets.LineCount; nextLineIndex++) + { + if (lineOffsets.GetLineLength(nextLineIndex) == 0) + continue; + + startOffset = lineOffsets.GetLineStartOffset(nextLineIndex); + endOffset = Math.Min(startOffset + 1, lineOffsets.TextLength); + return endOffset > startOffset; + } + + for (int previousLineIndex = lineIndex - 1; previousLineIndex >= 0; previousLineIndex--) + { + int previousLineLength = lineOffsets.GetLineLength(previousLineIndex); + + if (previousLineLength == 0) + continue; + + startOffset = lineOffsets.GetLineStartOffset(previousLineIndex) + previousLineLength - 1; + endOffset = Math.Min(startOffset + 1, lineOffsets.TextLength); + return endOffset > startOffset; + } + + return false; + } + private static bool TryGetWordBounds(string lineText, int index, out int wordStart, out int wordEnd) { wordStart = 0; @@ -231,11 +240,13 @@ private static bool IsDiagnosticSegmentCharacter(char c) => char.IsLetterOrDigit(c) || c == '_' || c == '.' || c == ':' || c == '\'' || c == '"'; private static TextEditorDiagnosticSeverity GetDiagnosticSeverity(JsonElement diagnosticElement) - => diagnosticElement.TryGetProperty("severity", out JsonElement severityElement) + { + return diagnosticElement.TryGetProperty("severity", out JsonElement severityElement) && severityElement.TryGetInt32(out int severity) && severity > 0 ? (TextEditorDiagnosticSeverity)severity : TextEditorDiagnosticSeverity.Warning; + } private static string BuildDiagnosticMessage(JsonElement diagnosticElement, TextEditorDiagnosticSeverity severity) { @@ -285,10 +296,3 @@ private static string BuildDiagnosticMessage(JsonElement diagnosticElement, Text return builder.ToString(); } } - -internal sealed class LuaPublishedDiagnostics(string filePath, IReadOnlyList diagnostics, int version) -{ - public string FilePath { get; } = filePath; - public IReadOnlyList Diagnostics { get; } = diagnostics ?? []; - public int Version { get; } = version; -} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs new file mode 100644 index 0000000000..298c32c64b --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs @@ -0,0 +1,280 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed partial class LuaLanguageServerIntellisenseProvider +{ + private Task EnqueueDocumentOperationAsync( + Func> operation, + CancellationToken cancellationToken) + { + var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + lock (_documentOperationSyncRoot) + { + Task previousOperation = _queuedDocumentOperation; + _queuedDocumentOperation = RunQueuedDocumentOperationAsync(previousOperation, operation, completionSource, cancellationToken); + } + + return completionSource.Task; + } + + private static async Task RunQueuedDocumentOperationAsync(Task previousOperation, + Func> operation, + TaskCompletionSource completionSource, + CancellationToken cancellationToken) + { + try + { + await WaitForQueuedDocumentOperationAsync(previousOperation).ConfigureAwait(false); + TResult result = await operation(cancellationToken).ConfigureAwait(false); + completionSource.TrySetResult(result); + } + catch (OperationCanceledException exception) when (exception.CancellationToken == cancellationToken) + { + completionSource.TrySetCanceled(cancellationToken); + } + catch (Exception exception) + { + completionSource.TrySetException(exception); + } + } + + private static async Task WaitForQueuedDocumentOperationAsync(Task previousOperation) + { + try + { + await previousOperation.ConfigureAwait(false); + } + catch + { } + } + + private Task TrySynchronizeDocumentAsync(string filePath, string content, + bool acquireOpenReference, bool refreshSemanticTokens, CancellationToken cancellationToken) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return Task.FromResult(false); + + return SynchronizeDocumentAsync(normalizedFilePath, content, acquireOpenReference, refreshSemanticTokens, cancellationToken); + } + + private async Task SynchronizeDocumentAsync(string filePath, string content, + bool acquireOpenReference, bool refreshSemanticTokens, CancellationToken cancellationToken) + { + if (_isDisposed || string.IsNullOrWhiteSpace(filePath) || _client is null) + return false; + + try + { + (bool success, LuaDocumentSnapshot? document) = await EnqueueDocumentOperationAsync( + token => SynchronizeDocumentCoreAsync(filePath, content, acquireOpenReference, token), + cancellationToken).ConfigureAwait(false); + + if (!success) + return false; + + if (refreshSemanticTokens && document is not null) + await RefreshSemanticTokensAsync(document, cancellationToken).ConfigureAwait(false); + + return true; + } + catch (OperationCanceledException) + { + throw; + } + catch (IOException) + { + return false; + } + catch (ObjectDisposedException) + { + return false; + } + } + + private async Task<(bool Success, LuaDocumentSnapshot? Document)> SynchronizeDocumentCoreAsync( + string filePath, + string content, + bool acquireOpenReference, + CancellationToken cancellationToken) + { + if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) + return (false, null); + + LuaDocumentSynchronizationRequest? request = _documents.Synchronize(filePath, content, acquireOpenReference); + + if (request is not { } pendingRequest) + return (true, null); + + await SendDocumentSynchronizationNotificationAsync(pendingRequest, cancellationToken).ConfigureAwait(false); + return (true, pendingRequest.Document); + } + + private async Task ReopenTrackedDocumentsAsync(IReadOnlyList documents, CancellationToken cancellationToken) + { + for (int i = 0; i < documents.Count; i++) + { + LuaDocumentSnapshot document = documents[i]; + LuaDocumentSynchronizationRequest? request = _documents.Synchronize(document.FilePath, document.Content); + + if (request is not { } pendingRequest) + continue; + + try + { + await SendDocumentSynchronizationNotificationAsync(pendingRequest, cancellationToken).ConfigureAwait(false); + await RefreshSemanticTokensAsync(pendingRequest.Document, cancellationToken).ConfigureAwait(false); + } + catch (IOException) + { + return false; + } + catch (ObjectDisposedException) + { + return false; + } + } + + return true; + } + + private async Task SendDocumentSynchronizationNotificationAsync(LuaDocumentSynchronizationRequest request, CancellationToken cancellationToken) + { + if (_client is null) + return; + + if (request.Kind == LuaDocumentSynchronizationKind.Open) + { + await _client.SendNotificationAsync("textDocument/didOpen", + new + { + textDocument = new + { + uri = request.Document.Uri, + languageId = "lua", + version = request.Document.Version, + text = request.Document.Content + } + }, cancellationToken).ConfigureAwait(false); + } + else if (request.Kind == LuaDocumentSynchronizationKind.Change) + { + object contentChange = request.ChangeRange is { } changeRange + ? new + { + range = new + { + start = new { line = changeRange.StartLine, character = changeRange.StartCharacter }, + end = new { line = changeRange.EndLine, character = changeRange.EndCharacter } + }, + text = changeRange.Text + } + : new { text = request.Document.Content }; + + await _client.SendNotificationAsync("textDocument/didChange", + new + { + textDocument = new + { + uri = request.Document.Uri, + version = request.Document.Version + }, + contentChanges = new[] { contentChange } + }, cancellationToken).ConfigureAwait(false); + } + } + + private async Task CloseDocumentAsync(string filePath, CancellationToken cancellationToken) + { + if (_client is null) + return; + + try + { + await EnqueueDocumentOperationAsync( + async token => + { + if (!_documents.TryClose(filePath, out LuaDocumentSnapshot? document)) + return false; + + // The document just dropped its last open reference; cancel any in-flight + // semantic-token request for it now that no editor will display the result. + CancelSemanticTokenRequest(filePath); + + // Only forward the close notification if the server is already running. + // Starting the server just to send didClose would be wasteful and can race with disposal. + if (!_startupSucceeded || !_client.IsReady) + return false; + + await _client.SendNotificationAsync("textDocument/didClose", + new { textDocument = new { uri = document.Uri } }, token).ConfigureAwait(false); + + return true; + }, + cancellationToken).ConfigureAwait(false); + } + catch + { + // Ignore best-effort close failures. + } + } + + private void HandleDiagnosticsPublished(JsonElement parameters) + { + if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters, out string filePath)) + { + Log.Debug("Lua diagnostics could not be matched to a local file path."); + return; + } + + LuaDocumentSnapshot? document = _documents.GetDocumentSnapshot(filePath); + + // Diagnostics for documents we have never opened are ignored: there is no editor to render them on, + // and reading the file from disk on the LSP read loop just to discard the result is wasteful. + if (document is null) + return; + + if (!LuaLanguageServerDiagnosticsParser.TryParse(parameters, filePath, + document.Content, document.Version, out LuaPublishedDiagnostics? publishedDiagnostics)) + { + Log.Debug("Lua diagnostics payload could not be parsed for '{FilePath}'.", filePath); + return; + } + + if (!_documents.TryStoreDiagnostics(publishedDiagnostics)) + return; + + DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); + } + + private static void ObserveBackgroundTask(Task task, string operation) + => _ = ObserveBackgroundTaskAsync(task, operation); + + private static async Task ObserveBackgroundTaskAsync(Task task, string operation) + { + try + { + await task.ConfigureAwait(false); + } + catch (OperationCanceledException) + { } + catch (IOException exception) + { + Log.Debug(exception, "Lua language server background operation '{Operation}' failed with a transport error.", operation); + } + catch (ObjectDisposedException) + { } + catch (Exception exception) + { + Log.Warn(exception, "Lua language server background operation '{Operation}' failed.", operation); + } + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs new file mode 100644 index 0000000000..43b4a2b423 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs @@ -0,0 +1,163 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed partial class LuaLanguageServerIntellisenseProvider +{ + public async Task> GetCompletionItemsAsync(string filePath, string content, + int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) + { + return await SendPositionRequestAsync( + filePath, content, line, column, "textDocument/completion", + (textDocument, position) => new + { + textDocument, + position, + context = BuildCompletionContext(triggerCharacter) + }, + response => + { + IReadOnlyList itemElements = LuaLanguageServerResponseParser.ExtractCompletionItems(response); + + return itemElements.Count > 0 + ? LuaLanguageServerResponseParser.ParseCompletionItems(itemElements, BuildCompletionItemResolveCallback) + : []; + }, + defaultValue: [], + cancellationToken).ConfigureAwait(false); + } + + public Task GetHoverAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + return SendPositionRequestAsync( + filePath, content, line, column, "textDocument/hover", + static (textDocument, position) => new { textDocument, position }, + LuaLanguageServerResponseParser.ParseHoverInfo, + defaultValue: null, + cancellationToken); + } + + public Task GetDefinitionAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + return SendPositionRequestAsync( + filePath, content, line, column, "textDocument/definition", + static (textDocument, position) => new { textDocument, position }, + LuaLanguageServerResponseParser.ParseDefinitionLocation, + defaultValue: null, + cancellationToken); + } + + public Task GetSignatureHelpAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + return SendPositionRequestAsync( + filePath, content, line, column, "textDocument/signatureHelp", + static (textDocument, position) => new { textDocument, position }, + LuaLanguageServerResponseParser.ParseSignatureHelp, + defaultValue: null, + cancellationToken); + } + + private static object BuildCompletionContext(char? triggerCharacter) + { + return triggerCharacter is null + ? new { triggerKind = 1 } + : new { triggerKind = 2, triggerCharacter = triggerCharacter.ToString() }; + } + + private Func>? BuildCompletionItemResolveCallback(LuaCompletionItem unresolvedItem, JsonElement itemElement, int itemIndex) + { + if (_client is null || !_client.SupportsCompletionResolve) + return null; + + return cancellationToken => ResolveCompletionItemAsync(unresolvedItem, itemElement, itemIndex, cancellationToken); + } + + private async Task ResolveCompletionItemAsync(LuaCompletionItem unresolvedItem, JsonElement itemElement, int itemIndex, CancellationToken cancellationToken) + { + ILuaLanguageServerClient? client = _client; + + if (client is null || !client.SupportsCompletionResolve) + return unresolvedItem; + + try + { + JsonElement resolvedItem = await SendBoundedRequestAsync(client, "completionItem/resolve", itemElement, cancellationToken).ConfigureAwait(false); + + if (resolvedItem.ValueKind == JsonValueKind.Object) + { + LuaCompletionItem? parsedItem = LuaLanguageServerResponseParser.ParseCompletionItem(resolvedItem, itemIndex); + + if (parsedItem is not null) + return parsedItem; + } + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception exception) + { + Log.Warn(exception, "Failed to resolve Lua completion item '{Label}'; falling back to the unresolved item.", unresolvedItem.Label); + } + + return unresolvedItem; + } + + private async Task SendPositionRequestAsync( + string filePath, string content, int line, int column, + string method, + Func buildParameters, + Func parseResponse, + TResult defaultValue, + CancellationToken cancellationToken) + { + ILuaLanguageServerClient? client = _client; + + if (client is null + || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + // Request-driven sync paths (completion / hover / definition / signature) intentionally + // skip the semantic-token refresh: typing a single identifier character can otherwise turn + // into didChange + completion + semanticTokens/full per keystroke, which is the dominant + // performance regression observed during normal editing. UpdateDocument (TextChangedDelayed) + // remains the single owner of post-edit semantic-token refresh. + || !await SynchronizeDocumentAsync(normalizedFilePath, content, + acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false)) + { + return defaultValue; + } + + object textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }; + object position = new { line, character = column }; + + JsonElement response = await SendBoundedRequestAsync(client, method, + buildParameters(textDocument, position), cancellationToken).ConfigureAwait(false); + + return parseResponse(response); + } + + private static async Task SendBoundedRequestAsync(ILuaLanguageServerClient client, string method, object parameters, CancellationToken cancellationToken) + { + using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + timeoutCts.CancelAfter(RequestTimeout); + + try + { + return await client.SendRequestAsync(method, parameters, timeoutCts.Token).ConfigureAwait(false); + } + catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) + { + Log.Debug("Lua language server request '{Method}' timed out after {Timeout}s.", method, RequestTimeout.TotalSeconds); + return default; + } + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs new file mode 100644 index 0000000000..4e41ea6764 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs @@ -0,0 +1,204 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed partial class LuaLanguageServerIntellisenseProvider +{ + private void HandleSemanticTokensRefreshRequested() + => ObserveBackgroundTask(RefreshTrackedSemanticTokensAsync(CancellationToken.None), "Semantic tokens refresh"); + + private async Task RefreshTrackedSemanticTokensAsync(CancellationToken cancellationToken) + { + if (_isDisposed || _client is null || _client.SemanticTokenTypes.Count == 0) + return; + + IReadOnlyList documents = _documents.GetOpenDocuments(); + + for (int i = 0; i < documents.Count; i++) + await RefreshSemanticTokensAsync(documents[i], cancellationToken).ConfigureAwait(false); + } + + private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) + { + if (_client is null || _client.SemanticTokenTypes.Count == 0) + return; + + CancellationToken effectiveToken = ReplaceSemanticTokenRequest(document.FilePath, cancellationToken, out CancellationTokenSource? linkedSource); + + try + { + (string? previousResultId, int[]? previousData) = _documents.GetSemanticTokensDeltaState(document.FilePath); + bool useDelta = _client.SupportsSemanticTokensDelta && previousResultId is not null && previousData is not null; + + string method = useDelta ? "textDocument/semanticTokens/full/delta" : "textDocument/semanticTokens/full"; + object parameters = useDelta + ? new { textDocument = new { uri = document.Uri }, previousResultId } + : new { textDocument = new { uri = document.Uri } }; + + JsonElement response = await SendBoundedRequestAsync(_client, method, parameters, effectiveToken).ConfigureAwait(false); + + if (response.ValueKind == JsonValueKind.Undefined) + return; + + (IReadOnlyList semanticTokens, int[]? newData, string? newResultId) = + DecodeSemanticTokensResponse(response, document, previousData, useDelta); + + _documents.StoreSemanticTokensDeltaState(document.FilePath, newResultId, newData); + + if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, semanticTokens)) + return; + + SemanticTokensUpdated?.Invoke(document.FilePath, semanticTokens); + } + catch (OperationCanceledException) when (effectiveToken.IsCancellationRequested && !cancellationToken.IsCancellationRequested) + { + // A newer document version superseded this request. + } + catch (OperationCanceledException) + { + throw; + } + catch (IOException exception) + { + Log.Debug(exception, "Lua semantic tokens request failed for '{FilePath}' due to a transport error; falling back to TextMate highlighting until the next sync.", + document.FilePath); + } + catch (ObjectDisposedException) + { + // The client was torn down between scheduling and dispatch. + } + catch (Exception exception) + { + Log.Warn(exception, "Lua semantic tokens request failed for '{FilePath}'; falling back to TextMate highlighting.", + document.FilePath); + } + finally + { + ClearSemanticTokenRequest(document.FilePath, linkedSource); + } + } + + private (IReadOnlyList Tokens, int[]? Data, string? ResultId) DecodeSemanticTokensResponse( + JsonElement response, LuaDocumentSnapshot document, int[]? previousData, bool deltaWasRequested) + { + if (_client is null) + return ([], null, null); + + if (deltaWasRequested) + { + LuaSemanticTokensDeltaResponse delta = LuaLanguageServerSemanticTokensDeltaParser.Parse(response); + + if (delta.Edits is { } edits && previousData is not null) + { + int[]? patchedData = LuaLanguageServerSemanticTokensDeltaParser.ApplyEdits(previousData, edits); + + if (patchedData is not null) + { + IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( + patchedData, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); + return (tokens, patchedData, delta.ResultId); + } + + Log.Debug("Lua semantic-tokens delta edits could not be applied for '{FilePath}'; falling back to a full reparse.", document.FilePath); + } + + if (delta.Data is { } fullData) + { + IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( + fullData, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); + + return (tokens, fullData, delta.ResultId); + } + + return ([], previousData, delta.ResultId); + } + + LuaSemanticTokensDeltaResponse fullResponse = LuaLanguageServerSemanticTokensDeltaParser.Parse(response); + + if (fullResponse.Data is { } data) + { + IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( + data, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); + + return (tokens, data, fullResponse.ResultId); + } + + // Legacy code path: parser returns the typed token list without exposing the raw int stream. + IReadOnlyList legacyTokens = LuaLanguageServerSemanticTokensParser.Parse( + response, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); + + return (legacyTokens, null, fullResponse.ResultId); + } + + private CancellationToken ReplaceSemanticTokenRequest(string filePath, CancellationToken cancellationToken, out CancellationTokenSource? linkedSource) + { + var freshSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + CancellationTokenSource? previousSource = null; + + _semanticTokenRequests.AddOrUpdate( + filePath, + freshSource, + (_, existing) => + { + previousSource = existing; + return freshSource; + }); + + CancelAndDispose(previousSource); + + linkedSource = freshSource; + return freshSource.Token; + } + + private void ClearSemanticTokenRequest(string filePath, CancellationTokenSource? linkedSource) + { + if (linkedSource is null) + return; + + _semanticTokenRequests.TryRemove(new KeyValuePair(filePath, linkedSource)); + linkedSource.Dispose(); + } + + private void CancelSemanticTokenRequest(string filePath) + { + if (_semanticTokenRequests.TryRemove(filePath, out CancellationTokenSource? source)) + CancelAndDispose(source); + } + + private void CancelAllSemanticTokenRequests() + { + if (_semanticTokenRequests.IsEmpty) + return; + + foreach (KeyValuePair entry in _semanticTokenRequests) + { + if (_semanticTokenRequests.TryRemove(entry.Key, out CancellationTokenSource? source)) + CancelAndDispose(source); + } + } + + private static void CancelAndDispose(CancellationTokenSource? source) + { + if (source is null) + return; + + try + { + source.Cancel(); + } + catch (ObjectDisposedException) + { } + finally + { + source.Dispose(); + } + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index 9f36f35310..34b6469491 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -1,10 +1,9 @@ #nullable enable +using NLog; using System; +using System.Collections.Concurrent; using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; @@ -13,35 +12,58 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; -internal sealed class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider +internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10); + private const int HardStartupFailureThreshold = 3; + private readonly string _workspaceRootDirectoryPath; - private readonly LuaLanguageServerClient? _client; + private readonly ILuaLanguageServerClient? _client; private readonly LuaIntellisenseDocumentManager _documents = new(); + private readonly object _documentOperationSyncRoot = new(); + private readonly ConcurrentDictionary _semanticTokenRequests = new(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _startLock = new(1, 1); + private LuaWorkspaceFileWatcher? _workspaceFileWatcher; + private Task _queuedDocumentOperation = Task.CompletedTask; - private bool _isDisposed; private bool _startupSucceeded; + private int _consecutiveStartupFailures; + private volatile bool _isDisposed; - public bool IsAvailable => !_isDisposed && _client is not null; + public bool IsAvailable => !_isDisposed && _client is not null + && _consecutiveStartupFailures < HardStartupFailureThreshold; public event Action>? DiagnosticsUpdated; - public event Action>? SemanticTokensUpdated; public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string? serverExecutablePath) + : this(workspaceRootDirectoryPath, CreateClient(workspaceRootDirectoryPath, serverExecutablePath)) + { } + + internal LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, ILuaLanguageServerClient? client) { - _workspaceRootDirectoryPath = workspaceRootDirectoryPath is null - ? throw new ArgumentNullException(nameof(workspaceRootDirectoryPath)) - : LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); + _workspaceRootDirectoryPath = LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); + _client = client; - if (!string.IsNullOrWhiteSpace(serverExecutablePath)) + if (_client is not null) { - _client = new LuaLanguageServerClient(_workspaceRootDirectoryPath, serverExecutablePath, BuildLuaSettings); _client.DiagnosticsPublished += HandleDiagnosticsPublished; + _client.SemanticTokensRefreshRequested += HandleSemanticTokensRefreshRequested; } } + private static ILuaLanguageServerClient? CreateClient(string workspaceRootDirectoryPath, string? serverExecutablePath) + { + if (string.IsNullOrWhiteSpace(serverExecutablePath)) + return null; + + string normalizedRoot = LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); + return new LuaLanguageServerClient(normalizedRoot, serverExecutablePath, + () => LuaLanguageServerSettingsFactory.Create(normalizedRoot)); + } + public IReadOnlyList GetDiagnostics(string filePath) { if (_isDisposed) @@ -65,165 +87,19 @@ public IReadOnlyList GetSemanticTokens(string filePath) } public void OpenDocument(string filePath, string content) - => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document open"); + => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, acquireOpenReference: true, + refreshSemanticTokens: true, CancellationToken.None), "Document open"); public void UpdateDocument(string filePath, string content) - => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, CancellationToken.None), "Document change"); + => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, acquireOpenReference: false, + refreshSemanticTokens: true, CancellationToken.None), "Document change"); public void CloseDocument(string filePath) { if (_isDisposed || _client is null || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) return; - if (!_documents.TryClose(normalizedFilePath, out LuaDocumentSnapshot? document)) - return; - - ObserveBackgroundTask(CloseDocumentAsync(document, CancellationToken.None), "Document close"); - } - - public async Task> GetCompletionItemsAsync(string filePath, string content, - int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) - { - LuaLanguageServerClient? client = _client; - - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || client is null - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) - { - return []; - } - - JsonElement response = await client.SendRequestAsync("textDocument/completion", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column }, - context = BuildCompletionContext(triggerCharacter) - }, cancellationToken).ConfigureAwait(false); - - IReadOnlyList itemElements = LuaLanguageServerResponseParser.ExtractCompletionItems(response); - - if (itemElements.Count == 0) - return []; - - return LuaLanguageServerResponseParser.ParseCompletionItems(itemElements, BuildCompletionItemResolveCallback); - } - - private static object BuildCompletionContext(char? triggerCharacter) - => triggerCharacter is null - ? new { triggerKind = 1 } - : new { triggerKind = 2, triggerCharacter = triggerCharacter.ToString() }; - - private Func>? BuildCompletionItemResolveCallback(JsonElement itemElement, int itemIndex) - { - if (_client is null || !_client.SupportsCompletionResolve || !LuaLanguageServerResponseParser.CompletionItemNeedsResolve(itemElement)) - return null; - - return cancellationToken => ResolveCompletionItemAsync(itemElement, itemIndex, cancellationToken); - } - - private async Task ResolveCompletionItemAsync(JsonElement itemElement, int itemIndex, CancellationToken cancellationToken) - { - LuaCompletionItem unresolvedItem = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, itemIndex) - ?? throw new InvalidOperationException("Completion item payload is missing a label."); - - if (_client is null || !_client.SupportsCompletionResolve) - return unresolvedItem; - - try - { - LuaLanguageServerClient? client = _client; - - if (client is null) - return unresolvedItem; - - JsonElement resolvedItem = await client.SendRequestAsync("completionItem/resolve", itemElement, cancellationToken).ConfigureAwait(false); - - if (resolvedItem.ValueKind == JsonValueKind.Object) - { - LuaCompletionItem? parsedItem = LuaLanguageServerResponseParser.ParseCompletionItem(resolvedItem, itemIndex); - - if (parsedItem is not null) - return parsedItem; - } - } - catch (OperationCanceledException) - { - throw; - } - catch - { - // Ignore - } - - return unresolvedItem; - } - - public async Task GetHoverAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default) - { - LuaLanguageServerClient? client = _client; - - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || client is null - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) - { - return null; - } - - JsonElement response = await client.SendRequestAsync("textDocument/hover", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column } - }, cancellationToken).ConfigureAwait(false); - - return LuaLanguageServerResponseParser.ParseHoverInfo(response); - } - - public async Task GetDefinitionAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default) - { - LuaLanguageServerClient? client = _client; - - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || client is null - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) - { - Debug.WriteLine($"[LuaLS] Definition request skipped because document sync failed for '{filePath}'."); - return null; - } - - JsonElement response = await client.SendRequestAsync("textDocument/definition", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column } - }, cancellationToken).ConfigureAwait(false); - - return LuaLanguageServerResponseParser.ParseDefinitionLocation(response); - } - - public async Task GetSignatureHelpAsync(string filePath, string content, - int line, int column, CancellationToken cancellationToken = default) - { - LuaLanguageServerClient? client = _client; - - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || client is null - || !await SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken).ConfigureAwait(false)) - { - return null; - } - - JsonElement response = await client.SendRequestAsync("textDocument/signatureHelp", - new - { - textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }, - position = new { line, character = column } - }, cancellationToken).ConfigureAwait(false); - - return LuaLanguageServerResponseParser.ParseSignatureHelp(response); + ObserveBackgroundTask(CloseDocumentAsync(normalizedFilePath, CancellationToken.None), "Document close"); } private async Task EnsureStartedAsync(CancellationToken cancellationToken) @@ -232,216 +108,113 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) return false; if (_startupSucceeded && _client.IsReady) + { + EnsureWorkspaceFileWatcherStarted(); return true; + } await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); try { + IReadOnlyList documentsToReopen = []; + if (_startupSucceeded && _client.IsReady) + { + EnsureWorkspaceFileWatcherStarted(); return true; + } if (_startupSucceeded && !_client.IsReady) { - Debug.WriteLine("[LuaLS] Server connection dropped, restarting and reopening tracked documents."); - _documents.PrepareForRestart(); + Log.Info("Lua language server connection dropped, restarting and reopening tracked documents."); + documentsToReopen = _documents.PrepareForRestart(); } _startupSucceeded = await _client.StartAsync(cancellationToken).ConfigureAwait(false); - if (!_startupSucceeded) - Debug.WriteLine("[LuaLS] Failed to start the Lua language server."); - - return _startupSucceeded; - } - finally - { - _startLock.Release(); - } - } - - private Task TrySynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) - { - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) - return Task.FromResult(false); - - return SynchronizeDocumentAsync(normalizedFilePath, content, cancellationToken); - } - - private async Task SynchronizeDocumentAsync(string filePath, string content, CancellationToken cancellationToken) - { - if (_isDisposed || string.IsNullOrWhiteSpace(filePath) || _client is null) - return false; - - if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) - return false; - - LuaDocumentSynchronizationRequest? request = _documents.Synchronize(filePath, content); + if (_startupSucceeded && documentsToReopen.Count > 0) + { + _startupSucceeded = await ReopenTrackedDocumentsAsync(documentsToReopen, cancellationToken).ConfigureAwait(false); - if (request is null) - return true; + if (!_startupSucceeded) + Log.Warn("Failed to replay tracked documents after Lua language server restart."); + } - try - { - if (request.Kind == LuaDocumentSynchronizationKind.Open) + if (_startupSucceeded) { - await _client.SendNotificationAsync("textDocument/didOpen", - new - { - textDocument = new - { - uri = request.Document.Uri, - languageId = "lua", - version = request.Document.Version, - text = request.Document.Content - } - }, cancellationToken).ConfigureAwait(false); + _consecutiveStartupFailures = 0; + EnsureWorkspaceFileWatcherStarted(); } - else if (request.Kind == LuaDocumentSynchronizationKind.Change) + else { - await _client.SendNotificationAsync("textDocument/didChange", - new - { - textDocument = new - { - uri = request.Document.Uri, - version = request.Document.Version - }, - contentChanges = new[] - { - new { text = request.Document.Content } - } - }, cancellationToken).ConfigureAwait(false); - } - - await RefreshSemanticTokensAsync(request.Document, cancellationToken).ConfigureAwait(false); - return true; - } - catch (OperationCanceledException) - { - throw; - } - catch (IOException) - { - return false; - } - catch (ObjectDisposedException) - { - return false; - } - } - - private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) - { - if (_client is null || _client.SemanticTokenTypes.Count == 0) - return; + _consecutiveStartupFailures++; - try - { - JsonElement response = await _client.SendRequestAsync("textDocument/semanticTokens/range", - new + if (_consecutiveStartupFailures >= HardStartupFailureThreshold) { - textDocument = new { uri = document.Uri }, - range = BuildDocumentRange(document.Content) - }, cancellationToken).ConfigureAwait(false); - - IReadOnlyList semanticTokens = LuaLanguageServerSemanticTokensParser.Parse( - response, - document, - _client.SemanticTokenTypes, - _client.SemanticTokenModifiers); - - if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, semanticTokens)) - return; + Log.Error("Lua language server failed to start {Count} times consecutively for workspace '{Workspace}'; IntelliSense is now disabled until the editor is restarted.", + _consecutiveStartupFailures, _workspaceRootDirectoryPath); + } + else + { + Log.Warn("Failed to start the Lua language server for workspace '{Workspace}' (attempt {Attempt}/{Threshold}).", + _workspaceRootDirectoryPath, _consecutiveStartupFailures, HardStartupFailureThreshold); + } + } - SemanticTokensUpdated?.Invoke(document.FilePath, semanticTokens); + return _startupSucceeded; } - catch + finally { - // Ignore semantic token failures and fall back to TextMate syntax highlighting. + _startLock.Release(); } } - private static object BuildDocumentRange(string? content) + private void EnsureWorkspaceFileWatcherStarted() { - string normalizedContent = (content ?? string.Empty) - .Replace("\r\n", "\n", StringComparison.Ordinal) - .Replace('\r', '\n'); + if (_workspaceFileWatcher is not null || _client is null || string.IsNullOrEmpty(_workspaceRootDirectoryPath)) + return; - string[] lines = normalizedContent.Split('\n'); - int endLine = Math.Max(0, lines.Length - 1); - int endCharacter = lines.Length == 0 ? 0 : lines[endLine].Length; + var watcher = new LuaWorkspaceFileWatcher(_workspaceRootDirectoryPath, DispatchWorkspaceFileChangesAsync); - return new - { - start = new { line = 0, character = 0 }, - end = new { line = endLine, character = endCharacter } - }; - } - - private async Task CloseDocumentAsync(LuaDocumentSnapshot document, CancellationToken cancellationToken) - { - if (_client is null) + if (!watcher.Start()) return; - try - { - if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) - return; - - await _client.SendNotificationAsync("textDocument/didClose", - new { textDocument = new { uri = document.Uri } }, cancellationToken).ConfigureAwait(false); - } - catch - { - // Ignore best-effort close failures. - } + _workspaceFileWatcher = watcher; } - private object BuildLuaSettings() - => LuaLanguageServerSettingsFactory.Create(_workspaceRootDirectoryPath); - - private void HandleDiagnosticsPublished(JsonElement parameters) + private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, CancellationToken cancellationToken) { - if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters, out string filePath)) - { - Debug.WriteLine("[LuaLS] Diagnostics could not be matched to a local file path."); + if (_client is null || _isDisposed || batch.Count == 0) return; - } - LuaDocumentSnapshot? document = _documents.GetDocumentSnapshot(filePath); + var changes = new List(batch.Count); - if (!LuaLanguageServerDiagnosticsParser.TryParse(parameters, filePath, - document?.Content, document?.Version ?? 0, out LuaPublishedDiagnostics? publishedDiagnostics)) + foreach ((string path, FileChangeKind kind) in batch.Entries) { - Debug.WriteLine($"[LuaLS] Diagnostics payload could not be parsed for '{filePath}'."); - return; + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(path, out string normalizedPath)) + continue; + + changes.Add(new + { + uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedPath), + type = (int)kind + }); } - if (!_documents.TryStoreDiagnostics(publishedDiagnostics)) + if (changes.Count == 0) return; - DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); - } - - private static void ObserveBackgroundTask(Task task, string operation) - => _ = ObserveBackgroundTaskAsync(task, operation); - - private static async Task ObserveBackgroundTaskAsync(Task task, string operation) - { try { - await task.ConfigureAwait(false); + await _client.SendNotificationAsync("workspace/didChangeWatchedFiles", + new { changes }, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { } - catch (IOException) - { } - catch (ObjectDisposedException) - { } catch (Exception exception) { - Debug.WriteLine($"[LuaLS] {operation} failed: {exception}"); + Log.Debug(exception, "Failed to forward workspace file changes to the Lua language server."); } } @@ -453,8 +226,24 @@ public void Dispose() _isDisposed = true; if (_client is not null) + { _client.DiagnosticsPublished -= HandleDiagnosticsPublished; + _client.SemanticTokensRefreshRequested -= HandleSemanticTokensRefreshRequested; + } + + if (_workspaceFileWatcher is not null) + { + try + { + _workspaceFileWatcher.Dispose(); + } + catch (Exception exception) + { + Log.Debug(exception, "Failed to dispose the Lua workspace file watcher."); + } + } + CancelAllSemanticTokenRequests(); _startLock.Dispose(); _client?.Dispose(); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs index 137cbcd6b2..3f4abcade1 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs @@ -15,9 +15,6 @@ internal static class LuaLanguageServerLocator public static string? ResolveExecutablePath() { string bundledExecutablePath = Path.Combine(DefaultPaths.TIDEDirectory, "LuaLS", "bin", ExecutableFileName); - - return !string.IsNullOrWhiteSpace(bundledExecutablePath) && File.Exists(bundledExecutablePath) - ? bundledExecutablePath - : null; + return File.Exists(bundledExecutablePath) ? bundledExecutablePath : null; } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs new file mode 100644 index 0000000000..9603edae33 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs @@ -0,0 +1,384 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static partial class LuaLanguageServerResponseParser +{ + // Lua identifiers are case-sensitive, so `Player` and `player` must be reported as distinct + // completion items. Use ordinal (case-sensitive) comparison everywhere completion identity + // is computed; using OrdinalIgnoreCase here would silently hide legitimate symbols. + private sealed class CompletionIdentityComparer : IEqualityComparer<(string Label, string InsertText)> + { + public static CompletionIdentityComparer Instance { get; } = new(); + + public bool Equals((string Label, string InsertText) x, (string Label, string InsertText) y) + => StringComparer.Ordinal.Equals(x.Label, y.Label) + && StringComparer.Ordinal.Equals(x.InsertText, y.InsertText); + + public int GetHashCode((string Label, string InsertText) value) + => HashCode.Combine( + StringComparer.Ordinal.GetHashCode(value.Label), + StringComparer.Ordinal.GetHashCode(value.InsertText)); + } + + private enum LuaLanguageServerCompletionKind + { + Text = 1, + Method = 2, + Function = 3, + Constructor = 4, + Field = 5, + Variable = 6, + Class = 7, + Interface = 8, + Module = 9, + Property = 10, + Unit = 11, + Value = 12, + Enum = 13, + Keyword = 14, + Snippet = 15, + Color = 16, + File = 17, + Reference = 18, + Folder = 19, + EnumMember = 20, + Constant = 21, + Struct = 22, + Event = 23, + Operator = 24, + TypeParameter = 25 + } + + private readonly struct CompletionTextAnalysis + { + public CompletionTextAnalysis(string? detail, string? description) + { + HasLocalScope = ContainsToken(detail, "local") + || ContainsToken(description, "local"); + + HasUpvalueOrParameter = ContainsToken(detail, "upvalue") + || ContainsToken(description, "upvalue") + || ContainsToken(detail, "parameter") + || ContainsToken(description, "parameter"); + + IconKindOverride = ResolveCompletionIconKind(detail); + } + + public bool HasLocalScope { get; } + public bool HasUpvalueOrParameter { get; } + public LuaCompletionIconKind? IconKindOverride { get; } + } + + public static IReadOnlyList ExtractCompletionItems(JsonElement response) + { + JsonElement itemsElement = response; + + if (response.ValueKind == JsonValueKind.Object && response.TryGetProperty("items", out JsonElement completionItemsElement)) + itemsElement = completionItemsElement; + + if (itemsElement.ValueKind != JsonValueKind.Array) + return []; + + var itemElements = new List(itemsElement.GetArrayLength()); + + foreach (JsonElement itemElement in itemsElement.EnumerateArray()) + itemElements.Add(itemElement.Clone()); + + return itemElements; + } + + public static IReadOnlyList ParseCompletionItems(IEnumerable itemElements, + Func>?>? resolveFactory = null) + { + var items = new List(); + var seenItems = new HashSet<(string Label, string InsertText)>(CompletionIdentityComparer.Instance); + int itemIndex = 0; + + foreach (JsonElement itemElement in itemElements) + { + LuaCompletionItem? item = ParseCompletionItem(itemElement, itemIndex); + itemIndex++; + + if (item is null) + continue; + + if (resolveFactory is not null && CompletionItemNeedsResolve(item)) + { + Func>? resolveAsync = resolveFactory(item, itemElement, itemIndex - 1); + + if (resolveAsync is not null) + item = item.WithResolveCallback(resolveAsync); + } + + if (seenItems.Add((item.Label, item.InsertText))) + items.Add(item); + } + + return items; + } + + public static LuaCompletionItem? ParseCompletionItem(JsonElement itemElement, int itemIndex, + Func>? resolveAsync = null) + { + if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) + return null; + + string? label = labelElement.GetString(); + + if (string.IsNullOrWhiteSpace(label)) + return null; + + string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) + && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) + ? newTextElement.GetString() ?? label + : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) + ? insertTextElement.GetString() ?? label + : label; + + if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) + && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) + { + insertText = StripSnippetPlaceholders(insertText); + } + + string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) + ? filterTextElement.GetString() ?? label + : label; + + LuaLanguageServerCompletionKind completionKind = TryReadCompletionKind(itemElement, out LuaLanguageServerCompletionKind parsedCompletionKind) + ? parsedCompletionKind + : LuaLanguageServerCompletionKind.Text; + + string? detail = BuildCompletionDetail(itemElement); + MarkupContent description = BuildCompletionDescription(itemElement); + string? searchableDescription = NormalizeMarkupText(description.Text); + var textAnalysis = new CompletionTextAnalysis(detail, searchableDescription); + + return new LuaCompletionItem( + label, + insertText, + detail, + description.Text, + filterText, + BuildCompletionPriority(itemElement, textAnalysis, itemIndex), + BuildCompletionIconKind(completionKind, textAnalysis), + description.IsMarkdown, + resolveAsync); + } + + private static class CompletionPriorityWeights + { + public const double PreselectedBonus = 1000000.0; + public const double ResponseOrderWeight = 100000.0; + public const double LocalScope = 20000.0; + public const double UpvalueOrParameter = 15000.0; + public const double VariableKind = 10000.0; + public const double FieldOrPropertyKind = 9000.0; + public const double MethodOrFunctionKind = 7000.0; + public const double KeywordKindPenalty = -5000.0; + } + + private static bool CompletionItemNeedsResolve(LuaCompletionItem item) + => string.IsNullOrEmpty(item.Detail) || string.IsNullOrEmpty(item.Description); + + private static double BuildCompletionPriority(JsonElement itemElement, CompletionTextAnalysis textAnalysis, int itemIndex) + { + double priority = CompletionPriorityWeights.ResponseOrderWeight - itemIndex; + + if (itemElement.TryGetProperty("preselect", out JsonElement preselectElement) + && preselectElement.ValueKind == JsonValueKind.True) + { + priority += CompletionPriorityWeights.PreselectedBonus; + } + + if (itemElement.TryGetProperty("kind", out JsonElement kindElement) + && kindElement.TryGetInt32(out int completionKind)) + { + priority += completionKind switch + { + (int)LuaLanguageServerCompletionKind.Variable => CompletionPriorityWeights.VariableKind, + (int)LuaLanguageServerCompletionKind.Field => CompletionPriorityWeights.FieldOrPropertyKind, + (int)LuaLanguageServerCompletionKind.Property => CompletionPriorityWeights.FieldOrPropertyKind, + (int)LuaLanguageServerCompletionKind.Method => CompletionPriorityWeights.MethodOrFunctionKind, + (int)LuaLanguageServerCompletionKind.Function => CompletionPriorityWeights.MethodOrFunctionKind, + (int)LuaLanguageServerCompletionKind.Keyword => CompletionPriorityWeights.KeywordKindPenalty, + _ => 0.0 + }; + } + + if (textAnalysis.HasLocalScope) + priority += CompletionPriorityWeights.LocalScope; + + if (textAnalysis.HasUpvalueOrParameter) + priority += CompletionPriorityWeights.UpvalueOrParameter; + + return priority; + } + + private static bool TryReadCompletionKind(JsonElement itemElement, out LuaLanguageServerCompletionKind kind) + { + kind = LuaLanguageServerCompletionKind.Text; + + if (!itemElement.TryGetProperty("kind", out JsonElement kindElement) + || !kindElement.TryGetInt32(out int rawKind) + || !Enum.IsDefined(typeof(LuaLanguageServerCompletionKind), rawKind)) + { + return false; + } + + kind = (LuaLanguageServerCompletionKind)rawKind; + return true; + } + + private static LuaCompletionIconKind BuildCompletionIconKind(LuaLanguageServerCompletionKind kind, CompletionTextAnalysis textAnalysis) + { + if (textAnalysis.IconKindOverride is LuaCompletionIconKind iconKindOverride) + return iconKindOverride; + + return kind switch + { + LuaLanguageServerCompletionKind.Method => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Function => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Constructor => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Field => LuaCompletionIconKind.Field, + LuaLanguageServerCompletionKind.Variable => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Class => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Interface => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Module => LuaCompletionIconKind.Namespace, + LuaLanguageServerCompletionKind.Property => LuaCompletionIconKind.Property, + LuaLanguageServerCompletionKind.Value => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Enum => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Keyword => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.Snippet => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.File => LuaCompletionIconKind.File, + LuaLanguageServerCompletionKind.Reference => LuaCompletionIconKind.Variable, + LuaLanguageServerCompletionKind.Folder => LuaCompletionIconKind.Folder, + LuaLanguageServerCompletionKind.EnumMember => LuaCompletionIconKind.Constant, + LuaLanguageServerCompletionKind.Constant => LuaCompletionIconKind.Constant, + LuaLanguageServerCompletionKind.Struct => LuaCompletionIconKind.Class, + LuaLanguageServerCompletionKind.Event => LuaCompletionIconKind.Method, + LuaLanguageServerCompletionKind.Operator => LuaCompletionIconKind.Keyword, + LuaLanguageServerCompletionKind.TypeParameter => LuaCompletionIconKind.Class, + _ => LuaCompletionIconKind.Misc + }; + } + + private static bool ContainsToken(string? text, string token) + => !string.IsNullOrEmpty(text) && text.Contains(token, StringComparison.OrdinalIgnoreCase); + + private static LuaCompletionIconKind? ResolveCompletionIconKind(string? detailText) + { + if (ContainsToken(detailText, "parameter")) + return LuaCompletionIconKind.Parameter; + + if (ContainsToken(detailText, "module") || ContainsToken(detailText, "namespace")) + return LuaCompletionIconKind.Namespace; + + if (ContainsToken(detailText, "method") || ContainsToken(detailText, "function")) + return LuaCompletionIconKind.Method; + + if (ContainsToken(detailText, "field")) + return LuaCompletionIconKind.Field; + + if (ContainsToken(detailText, "property") || ContainsToken(detailText, "global") + || ContainsToken(detailText, "default library")) + { + return LuaCompletionIconKind.Property; + } + + if (ContainsToken(detailText, "constant")) + return LuaCompletionIconKind.Constant; + + if (ContainsToken(detailText, "keyword")) + return LuaCompletionIconKind.Keyword; + + if (ContainsToken(detailText, "class") || ContainsToken(detailText, "interface") + || ContainsToken(detailText, "enum") || ContainsToken(detailText, "struct")) + { + return LuaCompletionIconKind.Class; + } + + return null; + } + + private static string? BuildCompletionDetail(JsonElement itemElement) + { + if (!itemElement.TryGetProperty("detail", out JsonElement detailElement)) + return null; + + string? detail = detailElement.GetString(); + return string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); + } + + private static MarkupContent BuildCompletionDescription(JsonElement itemElement) + { + if (!itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) + return default; + + MarkupContent documentation = ExtractMarkupContent(documentationElement); + + if (string.IsNullOrWhiteSpace(documentation.Text)) + return default; + + string? normalizedText = documentation.IsMarkdown + ? NormalizeMarkdownText(documentation.Text) + : NormalizeMarkupText(documentation.Text); + + return string.IsNullOrWhiteSpace(normalizedText) + ? default + : new MarkupContent(normalizedText, documentation.IsMarkdown); + } + + private static string StripSnippetPlaceholders(string snippet) + { + if (string.IsNullOrWhiteSpace(snippet)) + return snippet; + + var builder = new StringBuilder(snippet.Length); + int index = 0; + + while (index < snippet.Length) + { + if (snippet[index] == '$') + { + if (index + 1 < snippet.Length && snippet[index + 1] == '{') + { + int endIndex = snippet.IndexOf('}', index + 2); + + if (endIndex > index) + { + string placeholder = snippet[(index + 2)..endIndex]; + int separatorIndex = placeholder.IndexOf(':'); + + if (separatorIndex >= 0 && separatorIndex < placeholder.Length - 1) + builder.Append(placeholder[(separatorIndex + 1)..]); + + index = endIndex + 1; + continue; + } + } + + index++; + + while (index < snippet.Length && char.IsDigit(snippet[index])) + index++; + + continue; + } + + builder.Append(snippet[index]); + index++; + } + + return builder.ToString(); + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Navigation.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Navigation.cs new file mode 100644 index 0000000000..0cf866888c --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Navigation.cs @@ -0,0 +1,95 @@ +#nullable enable + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static partial class LuaLanguageServerResponseParser +{ + private static readonly string[] DefinitionRangeProperties = + [ + "targetSelectionRange", + "targetRange", + "range" + ]; + + /// + /// Parses hover content from a LuaLS hover response. + /// + public static LuaHoverInfo? ParseHoverInfo(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) + return null; + + MarkupContent hoverContent = ExtractMarkupContent(contentsElement); + + return string.IsNullOrWhiteSpace(hoverContent.Text) + ? null + : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); + } + + /// + /// Parses a definition location from a LuaLS definition response. + /// + public static LuaDefinitionLocation? ParseDefinitionLocation(JsonElement response) + { + JsonElement definitionElement = response; + + if (response.ValueKind == JsonValueKind.Array) + { + definitionElement = response.EnumerateArray().FirstOrDefault(); + + if (definitionElement.ValueKind == JsonValueKind.Undefined) + return null; + } + + if (definitionElement.ValueKind != JsonValueKind.Object) + return null; + + if (!TryGetDefinitionUri(definitionElement, out Uri? parsedUri)) + return null; + + if (!TryGetDefinitionStartElement(definitionElement, out JsonElement startElement)) + return null; + + int lineNumber = startElement.TryGetProperty("line", out JsonElement lineElement) + && lineElement.TryGetInt32(out int parsedLine) ? parsedLine + 1 : 1; + int columnNumber = startElement.TryGetProperty("character", out JsonElement characterElement) + && characterElement.TryGetInt32(out int parsedCharacter) ? parsedCharacter + 1 : 1; + + return new LuaDefinitionLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), lineNumber, columnNumber); + } + + private static bool TryGetDefinitionUri(JsonElement definitionElement, [NotNullWhen(true)] out Uri? parsedUri) + { + parsedUri = null; + + string? uri = definitionElement.TryGetProperty("targetUri", out JsonElement targetUriElement) + ? targetUriElement.GetString() + : definitionElement.TryGetProperty("uri", out JsonElement uriElement) + ? uriElement.GetString() + : null; + + return !string.IsNullOrWhiteSpace(uri) && Uri.TryCreate(uri, UriKind.Absolute, out parsedUri) && parsedUri.IsFile; + } + + private static bool TryGetDefinitionStartElement(JsonElement definitionElement, out JsonElement startElement) + { + foreach (string rangeProperty in DefinitionRangeProperties) + { + if (definitionElement.TryGetProperty(rangeProperty, out JsonElement rangeElement) + && rangeElement.TryGetProperty("start", out startElement) + && startElement.ValueKind == JsonValueKind.Object) + { + return true; + } + } + + startElement = default; + return false; + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.SignatureHelp.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.SignatureHelp.cs new file mode 100644 index 0000000000..772b8982da --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.SignatureHelp.cs @@ -0,0 +1,125 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses signature help metadata from a LuaLS signature-help response. + /// + public static LuaSignatureInfo? ParseSignatureHelp(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object + || !response.TryGetProperty("signatures", out JsonElement signaturesElement) + || signaturesElement.ValueKind != JsonValueKind.Array) + { + return null; + } + + int signatureCount = signaturesElement.GetArrayLength(); + + if (signatureCount == 0) + return null; + + int activeSignature = response.TryGetProperty("activeSignature", out JsonElement activeSignatureElement) + && activeSignatureElement.TryGetInt32(out int parsedActiveSignature) + ? Math.Clamp(parsedActiveSignature, 0, signatureCount - 1) + : 0; + + JsonElement signatureElement = signaturesElement[activeSignature]; + + if (signatureElement.ValueKind != JsonValueKind.Object + || !signatureElement.TryGetProperty("label", out JsonElement labelElement)) + { + return null; + } + + string? label = labelElement.GetString(); + + if (string.IsNullOrWhiteSpace(label)) + return null; + + string? documentation = signatureElement.TryGetProperty("documentation", out JsonElement documentationElement) + ? ExtractMarkupText(documentationElement) + : null; + + int activeParameter = ResolveActiveParameter(response, signatureElement); + + var parameters = new List(); + + if (signatureElement.TryGetProperty("parameters", out JsonElement parametersElement) + && parametersElement.ValueKind == JsonValueKind.Array) + { + foreach (JsonElement paramElement in parametersElement.EnumerateArray()) + { + string? parameterLabel = paramElement.TryGetProperty("label", out JsonElement paramLabelElement) + ? paramLabelElement.ValueKind == JsonValueKind.String + ? paramLabelElement.GetString() + : TryExtractParameterLabel(label, paramLabelElement, out string? extractedLabel) + ? extractedLabel + : null + : null; + + string? parameterDocumentation = paramElement.TryGetProperty("documentation", out JsonElement parameterDocumentationElement) + ? ExtractMarkupText(parameterDocumentationElement) + : null; + + parameters.Add(new LuaParameterInfo(parameterLabel ?? string.Empty, parameterDocumentation)); + } + } + + return new LuaSignatureInfo(label, documentation, parameters, activeParameter); + } + + private static int ResolveActiveParameter(JsonElement response, JsonElement signatureElement) + { + if (response.TryGetProperty("activeParameter", out JsonElement responseActiveParameterElement) + && responseActiveParameterElement.TryGetInt32(out int responseActiveParameter)) + { + return Math.Max(0, responseActiveParameter); + } + + if (signatureElement.TryGetProperty("activeParameter", out JsonElement signatureActiveParameterElement) + && signatureActiveParameterElement.TryGetInt32(out int signatureActiveParameter)) + { + return Math.Max(0, signatureActiveParameter); + } + + return 0; + } + + private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, + [NotNullWhen(true)] out string? parameterLabel) + { + parameterLabel = null; + + if (string.IsNullOrEmpty(signatureLabel) + || parameterLabelElement.ValueKind != JsonValueKind.Array) + { + return false; + } + + JsonElement.ArrayEnumerator labelParts = parameterLabelElement.EnumerateArray(); + + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int startIndex)) + return false; + + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int endIndex)) + return false; + + startIndex = Math.Max(0, Math.Min(startIndex, signatureLabel.Length)); + endIndex = Math.Max(startIndex, Math.Min(endIndex, signatureLabel.Length)); + + if (endIndex <= startIndex) + return false; + + parameterLabel = signatureLabel[startIndex..endIndex]; + return true; + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs index d25ee1c548..74d87eb574 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs @@ -2,491 +2,19 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Text; using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; -using TombLib.Scripting.Lua.Objects; namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; -internal static class LuaLanguageServerResponseParser +internal static partial class LuaLanguageServerResponseParser { - private enum LuaLanguageServerCompletionKind - { - Text = 1, - Method = 2, - Function = 3, - Constructor = 4, - Field = 5, - Variable = 6, - Class = 7, - Interface = 8, - Module = 9, - Property = 10, - Unit = 11, - Value = 12, - Enum = 13, - Keyword = 14, - Snippet = 15, - Color = 16, - File = 17, - Reference = 18, - Folder = 19, - EnumMember = 20, - Constant = 21, - Struct = 22, - Event = 23, - Operator = 24, - TypeParameter = 25 - } - private readonly struct MarkupContent(string? text, bool isMarkdown) { public string Text { get; } = text ?? string.Empty; public bool IsMarkdown { get; } = isMarkdown; } - /// - /// Parses completion entries from a LuaLS completion response. - /// - public static IReadOnlyList ParseCompletionItems(JsonElement response) - => ParseCompletionItems(ExtractCompletionItems(response)); - - public static IReadOnlyList ExtractCompletionItems(JsonElement response) - { - JsonElement itemsElement = response; - - if (response.ValueKind == JsonValueKind.Object && response.TryGetProperty("items", out JsonElement completionItemsElement)) - itemsElement = completionItemsElement; - - if (itemsElement.ValueKind != JsonValueKind.Array) - return []; - - var itemElements = new List(); - - foreach (JsonElement itemElement in itemsElement.EnumerateArray()) - itemElements.Add(itemElement.Clone()); - - return itemElements; - } - - public static IReadOnlyList ParseCompletionItems(IEnumerable itemElements, - Func>?>? resolveFactory = null) - { - var items = new List(); - int itemIndex = 0; - - foreach (JsonElement itemElement in itemElements) - { - LuaCompletionItem? item = ParseCompletionItem(itemElement, itemIndex, resolveFactory?.Invoke(itemElement, itemIndex)); - - if (item is not null) - items.Add(item); - - itemIndex++; - } - - return [.. items - .GroupBy(item => $"{item.Label}\0{item.InsertText}", StringComparer.OrdinalIgnoreCase) - .Select(group => group.First())]; - } - - public static bool CompletionItemNeedsResolve(JsonElement itemElement) - => string.IsNullOrWhiteSpace(BuildCompletionDetail(itemElement)) - || string.IsNullOrWhiteSpace(BuildCompletionDescription(itemElement).Text); - - public static LuaCompletionItem? ParseCompletionItem(JsonElement itemElement, int itemIndex, - Func>? resolveAsync = null) - { - if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) - return null; - - string? label = labelElement.GetString(); - - if (string.IsNullOrWhiteSpace(label)) - return null; - - string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) - && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) - ? newTextElement.GetString() ?? label - : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) - ? insertTextElement.GetString() ?? label - : label; - - if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) - && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) - { - insertText = StripSnippetPlaceholders(insertText); - } - - string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) - ? filterTextElement.GetString() ?? label - : label; - - LuaLanguageServerCompletionKind completionKind = TryReadCompletionKind(itemElement, out LuaLanguageServerCompletionKind parsedCompletionKind) - ? parsedCompletionKind - : LuaLanguageServerCompletionKind.Text; - - string? detail = BuildCompletionDetail(itemElement); - MarkupContent description = BuildCompletionDescription(itemElement); - string? searchableDescription = NormalizeMarkupText(description.Text); - - return new LuaCompletionItem( - label, - insertText, - detail, - description.Text, - filterText, - BuildCompletionPriority(itemElement, detail, searchableDescription, itemIndex), - BuildCompletionIconKind(completionKind, detail), - description.IsMarkdown, - resolveAsync); - } - - private static double BuildCompletionPriority(JsonElement itemElement, string? detail, string? description, int itemIndex) - { - const double preselectedBonus = 1000000.0; - const double responseOrderWeight = 100000.0; - const double localScopeBonus = 20000.0; - const double upvalueOrParameterBonus = 15000.0; - const double variableKindBonus = 10000.0; - const double fieldOrPropertyKindBonus = 9000.0; - const double methodOrFunctionKindBonus = 7000.0; - const double keywordKindPenalty = -5000.0; - - double priority = responseOrderWeight - itemIndex; - string? searchableText = CombineCompletionText(detail, description); - - if (itemElement.TryGetProperty("preselect", out JsonElement preselectElement) - && preselectElement.ValueKind == JsonValueKind.True) - { - priority += preselectedBonus; - } - - if (itemElement.TryGetProperty("kind", out JsonElement kindElement) - && kindElement.TryGetInt32(out int completionKind)) - { - priority += completionKind switch - { - (int)LuaLanguageServerCompletionKind.Variable => variableKindBonus, - (int)LuaLanguageServerCompletionKind.Field => fieldOrPropertyKindBonus, - (int)LuaLanguageServerCompletionKind.Property => fieldOrPropertyKindBonus, - (int)LuaLanguageServerCompletionKind.Method => methodOrFunctionKindBonus, - (int)LuaLanguageServerCompletionKind.Function => methodOrFunctionKindBonus, - (int)LuaLanguageServerCompletionKind.Keyword => keywordKindPenalty, - _ => 0.0 - }; - } - - if (!string.IsNullOrWhiteSpace(searchableText)) - { - if (CompletionTextContains(searchableText, "local")) - priority += localScopeBonus; - - if (CompletionTextContains(searchableText, "upvalue") - || CompletionTextContains(searchableText, "parameter")) - { - priority += upvalueOrParameterBonus; - } - } - - return priority; - } - - private static bool TryReadCompletionKind(JsonElement itemElement, out LuaLanguageServerCompletionKind kind) - { - kind = LuaLanguageServerCompletionKind.Text; - - if (!itemElement.TryGetProperty("kind", out JsonElement kindElement) - || !kindElement.TryGetInt32(out int rawKind) - || !Enum.IsDefined(typeof(LuaLanguageServerCompletionKind), rawKind)) - { - return false; - } - - kind = (LuaLanguageServerCompletionKind)rawKind; - return true; - } - - private static LuaCompletionIconKind BuildCompletionIconKind(LuaLanguageServerCompletionKind kind, string? detail) - { - if (CompletionTextContains(detail, "parameter")) - return LuaCompletionIconKind.Parameter; - - if (CompletionTextContains(detail, "module") || CompletionTextContains(detail, "namespace")) - return LuaCompletionIconKind.Namespace; - - if (CompletionTextContains(detail, "method") || CompletionTextContains(detail, "function")) - return LuaCompletionIconKind.Method; - - if (CompletionTextContains(detail, "field")) - return LuaCompletionIconKind.Field; - - if (CompletionTextContains(detail, "property") || CompletionTextContains(detail, "global") - || CompletionTextContains(detail, "default library")) - { - return LuaCompletionIconKind.Property; - } - - if (CompletionTextContains(detail, "constant")) - return LuaCompletionIconKind.Constant; - - if (CompletionTextContains(detail, "keyword")) - return LuaCompletionIconKind.Keyword; - - if (CompletionTextContains(detail, "class") || CompletionTextContains(detail, "interface") - || CompletionTextContains(detail, "enum") || CompletionTextContains(detail, "struct")) - { - return LuaCompletionIconKind.Class; - } - - return kind switch - { - LuaLanguageServerCompletionKind.Method => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Function => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Constructor => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Field => LuaCompletionIconKind.Field, - LuaLanguageServerCompletionKind.Variable => LuaCompletionIconKind.Variable, - LuaLanguageServerCompletionKind.Class => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Interface => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Module => LuaCompletionIconKind.Namespace, - LuaLanguageServerCompletionKind.Property => LuaCompletionIconKind.Property, - LuaLanguageServerCompletionKind.Value => LuaCompletionIconKind.Variable, - LuaLanguageServerCompletionKind.Enum => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Keyword => LuaCompletionIconKind.Keyword, - LuaLanguageServerCompletionKind.Snippet => LuaCompletionIconKind.Keyword, - LuaLanguageServerCompletionKind.File => LuaCompletionIconKind.File, - LuaLanguageServerCompletionKind.Reference => LuaCompletionIconKind.Variable, - LuaLanguageServerCompletionKind.Folder => LuaCompletionIconKind.Folder, - LuaLanguageServerCompletionKind.EnumMember => LuaCompletionIconKind.Constant, - LuaLanguageServerCompletionKind.Constant => LuaCompletionIconKind.Constant, - LuaLanguageServerCompletionKind.Struct => LuaCompletionIconKind.Class, - LuaLanguageServerCompletionKind.Event => LuaCompletionIconKind.Method, - LuaLanguageServerCompletionKind.Operator => LuaCompletionIconKind.Keyword, - LuaLanguageServerCompletionKind.TypeParameter => LuaCompletionIconKind.Class, - _ => LuaCompletionIconKind.Misc - }; - } - - /// - /// Parses hover content from a LuaLS hover response. - /// - public static LuaHoverInfo? ParseHoverInfo(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) - return null; - - MarkupContent hoverContent = ExtractMarkupContent(contentsElement); - - return string.IsNullOrWhiteSpace(hoverContent.Text) - ? null - : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); - } - - /// - /// Parses a definition location from a LuaLS definition response. - /// - public static LuaDefinitionLocation? ParseDefinitionLocation(JsonElement response) - { - JsonElement definitionElement = response; - - if (response.ValueKind == JsonValueKind.Array) - { - definitionElement = response.EnumerateArray().FirstOrDefault(); - - if (definitionElement.ValueKind == JsonValueKind.Undefined) - return null; - } - - if (definitionElement.ValueKind != JsonValueKind.Object) - return null; - - string? uri = definitionElement.TryGetProperty("targetUri", out JsonElement targetUriElement) - ? targetUriElement.GetString() - : definitionElement.TryGetProperty("uri", out JsonElement uriElement) - ? uriElement.GetString() - : null; - - if (string.IsNullOrWhiteSpace(uri) || !Uri.TryCreate(uri, UriKind.Absolute, out Uri? parsedUri) - || parsedUri is null || !parsedUri.IsFile) - { - return null; - } - - JsonElement startElement = definitionElement.TryGetProperty("targetSelectionRange", out JsonElement targetSelectionRangeElement) - && targetSelectionRangeElement.TryGetProperty("start", out JsonElement targetSelectionStartElement) - ? targetSelectionStartElement - : definitionElement.TryGetProperty("targetRange", out JsonElement targetRangeElement) - && targetRangeElement.TryGetProperty("start", out JsonElement targetRangeStartElement) - ? targetRangeStartElement - : definitionElement.TryGetProperty("range", out JsonElement rangeElement) - && rangeElement.TryGetProperty("start", out JsonElement rangeStartElement) - ? rangeStartElement - : default; - - if (startElement.ValueKind != JsonValueKind.Object) - return null; - - int lineNumber = startElement.TryGetProperty("line", out JsonElement lineElement) ? lineElement.GetInt32() + 1 : 1; - int columnNumber = startElement.TryGetProperty("character", out JsonElement characterElement) ? characterElement.GetInt32() + 1 : 1; - - return new LuaDefinitionLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), lineNumber, columnNumber); - } - - /// - /// Parses signature help metadata from a LuaLS signature-help response. - /// - public static LuaSignatureInfo? ParseSignatureHelp(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object - || !response.TryGetProperty("signatures", out JsonElement signaturesElement) - || signaturesElement.ValueKind != JsonValueKind.Array) - { - return null; - } - - int activeSignature = response.TryGetProperty("activeSignature", out JsonElement activeSignatureElement) - && activeSignatureElement.TryGetInt32(out int parsedActiveSignature) - ? Math.Max(0, parsedActiveSignature) - : 0; - - int signatureIndex = 0; - JsonElement signatureElement = default; - - foreach (JsonElement candidate in signaturesElement.EnumerateArray()) - { - if (signatureIndex == activeSignature) - { - signatureElement = candidate; - break; - } - - signatureIndex++; - } - - if (signatureElement.ValueKind != JsonValueKind.Object - || !signatureElement.TryGetProperty("label", out JsonElement labelElement)) - { - return null; - } - - string? label = labelElement.GetString(); - - if (string.IsNullOrWhiteSpace(label)) - return null; - - string? documentation = signatureElement.TryGetProperty("documentation", out JsonElement documentationElement) - ? ExtractMarkupText(documentationElement) - : null; - - int activeParameter = response.TryGetProperty("activeParameter", out JsonElement activeParameterElement) - && activeParameterElement.TryGetInt32(out int parsedActiveParameter) - ? Math.Max(0, parsedActiveParameter) - : signatureElement.TryGetProperty("activeParameter", out JsonElement signatureActiveParameterElement) - && signatureActiveParameterElement.TryGetInt32(out int parsedSignatureActiveParameter) - ? Math.Max(0, parsedSignatureActiveParameter) - : 0; - - var parameters = new List(); - - if (signatureElement.TryGetProperty("parameters", out JsonElement parametersElement) - && parametersElement.ValueKind == JsonValueKind.Array) - { - foreach (JsonElement paramElement in parametersElement.EnumerateArray()) - { - string? parameterLabel = paramElement.TryGetProperty("label", out JsonElement paramLabelElement) - ? paramLabelElement.ValueKind == JsonValueKind.String - ? paramLabelElement.GetString() - : TryExtractParameterLabel(label, paramLabelElement, out string? extractedLabel) - ? extractedLabel - : null - : null; - - string? parameterDocumentation = paramElement.TryGetProperty("documentation", out JsonElement parameterDocumentationElement) - ? ExtractMarkupText(parameterDocumentationElement) - : null; - - parameters.Add(new LuaParameterInfo(parameterLabel ?? string.Empty, parameterDocumentation)); - } - } - - return new LuaSignatureInfo(label, documentation, parameters, activeParameter); - } - - private static string? BuildCompletionDetail(JsonElement itemElement) - { - if (!itemElement.TryGetProperty("detail", out JsonElement detailElement)) - return null; - - string? detail = detailElement.GetString(); - return string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); - } - - private static MarkupContent BuildCompletionDescription(JsonElement itemElement) - { - if (!itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) - return default; - - MarkupContent documentation = ExtractMarkupContent(documentationElement); - - if (string.IsNullOrWhiteSpace(documentation.Text)) - return default; - - string? normalizedText = documentation.IsMarkdown - ? NormalizeMarkdownText(documentation.Text) - : NormalizeMarkupText(documentation.Text); - - return string.IsNullOrWhiteSpace(normalizedText) - ? default - : new MarkupContent(normalizedText, documentation.IsMarkdown); - } - - private static string? CombineCompletionText(string? detail, string? description) - { - if (string.IsNullOrWhiteSpace(detail)) - return description; - - if (string.IsNullOrWhiteSpace(description)) - return detail; - - return detail + Environment.NewLine + description; - } - - private static bool CompletionTextContains(string? text, string token) - => !string.IsNullOrWhiteSpace(text) && text.IndexOf(token, StringComparison.OrdinalIgnoreCase) >= 0; - - private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, - [NotNullWhen(true)] out string? parameterLabel) - { - parameterLabel = null; - - if (string.IsNullOrEmpty(signatureLabel) - || parameterLabelElement.ValueKind != JsonValueKind.Array) - { - return false; - } - - JsonElement.ArrayEnumerator labelParts = parameterLabelElement.EnumerateArray(); - - if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int startIndex)) - return false; - - if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int endIndex)) - return false; - - startIndex = Math.Max(0, Math.Min(startIndex, signatureLabel.Length)); - endIndex = Math.Max(startIndex, Math.Min(endIndex, signatureLabel.Length)); - - if (endIndex <= startIndex) - return false; - - parameterLabel = signatureLabel[startIndex..endIndex]; - return true; - } - private static string? ExtractMarkupText(JsonElement element) => NormalizeMarkupText(ExtractMarkupContent(element).Text); @@ -495,7 +23,7 @@ private static MarkupContent ExtractMarkupContent(JsonElement element) return element.ValueKind switch { JsonValueKind.String => new MarkupContent(element.GetString(), true), - JsonValueKind.Array => CombineMarkupContent(element.EnumerateArray().Select(ExtractMarkupContent)), + JsonValueKind.Array => CombineArrayMarkupContent(element), JsonValueKind.Object when element.TryGetProperty("value", out JsonElement valueElement) && element.TryGetProperty("kind", out JsonElement kindElement) => new MarkupContent(valueElement.GetString(), @@ -509,21 +37,24 @@ JsonValueKind.Object when element.TryGetProperty("value", out JsonElement plainV }; } - private static MarkupContent CombineMarkupContent(IEnumerable items) + private static MarkupContent CombineArrayMarkupContent(JsonElement arrayElement) { bool isMarkdown = false; - var parts = new List(); + List? parts = null; - foreach (MarkupContent item in items) + foreach (JsonElement child in arrayElement.EnumerateArray()) { + MarkupContent item = ExtractMarkupContent(child); + if (string.IsNullOrWhiteSpace(item.Text)) continue; + parts ??= []; parts.Add(item.Text.Trim()); isMarkdown |= item.IsMarkdown; } - return parts.Count == 0 + return parts is null ? default : new MarkupContent(string.Join(Environment.NewLine + Environment.NewLine, parts), isMarkdown); } @@ -548,53 +79,11 @@ private static MarkupContent CombineMarkupContent(IEnumerable ite } private static string? NormalizeMarkdownText(string? text) - => string.IsNullOrWhiteSpace(text) + { + return string.IsNullOrWhiteSpace(text) ? null : text.Replace("\r\n", "\n", StringComparison.Ordinal) .Replace('\r', '\n') .Trim(); - - private static string StripSnippetPlaceholders(string snippet) - { - if (string.IsNullOrWhiteSpace(snippet)) - return snippet; - - var builder = new StringBuilder(snippet.Length); - int index = 0; - - while (index < snippet.Length) - { - if (snippet[index] == '$') - { - if (index + 1 < snippet.Length && snippet[index + 1] == '{') - { - int endIndex = snippet.IndexOf('}', index + 2); - - if (endIndex > index) - { - string placeholder = snippet[(index + 2)..endIndex]; - int separatorIndex = placeholder.IndexOf(':'); - - if (separatorIndex >= 0 && separatorIndex < placeholder.Length - 1) - builder.Append(placeholder[(separatorIndex + 1)..]); - - index = endIndex + 1; - continue; - } - } - - index++; - - while (index < snippet.Length && char.IsDigit(snippet[index])) - index++; - - continue; - } - - builder.Append(snippet[index]); - index++; - } - - return builder.ToString(); } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs new file mode 100644 index 0000000000..87e89b622e --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs @@ -0,0 +1,210 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Result of a `textDocument/semanticTokens/full/delta` response: either the server returned a full +/// `data` array (preferred when it is cheaper than a delta), or it returned a list of `edits` that +/// should be applied to the client-side cached integer stream. +/// +internal readonly record struct LuaSemanticTokensDeltaResponse( + string? ResultId, + int[]? Data, + IReadOnlyList? Edits); + +internal readonly record struct LuaSemanticTokensEdit(int Start, int DeleteCount, int[] Data); + +internal static class LuaLanguageServerSemanticTokensDeltaParser +{ + public static LuaSemanticTokensDeltaResponse Parse(JsonElement response) + { + string? resultId = response.TryGetProperty("resultId", out JsonElement resultIdElement) + && resultIdElement.ValueKind == JsonValueKind.String + ? resultIdElement.GetString() + : null; + + if (response.TryGetProperty("data", out JsonElement dataElement) && dataElement.ValueKind == JsonValueKind.Array) + return new LuaSemanticTokensDeltaResponse(resultId, ReadIntArray(dataElement), Edits: null); + + if (response.TryGetProperty("edits", out JsonElement editsElement) && editsElement.ValueKind == JsonValueKind.Array) + { + var edits = new List(editsElement.GetArrayLength()); + + foreach (JsonElement editElement in editsElement.EnumerateArray()) + { + if (editElement.ValueKind != JsonValueKind.Object) + continue; + + int start = editElement.TryGetProperty("start", out JsonElement startElement) && startElement.TryGetInt32(out int parsedStart) ? parsedStart : 0; + int deleteCount = editElement.TryGetProperty("deleteCount", out JsonElement deleteCountElement) && deleteCountElement.TryGetInt32(out int parsedDeleteCount) ? parsedDeleteCount : 0; + int[] data = editElement.TryGetProperty("data", out JsonElement editDataElement) && editDataElement.ValueKind == JsonValueKind.Array + ? ReadIntArray(editDataElement) + : []; + + edits.Add(new LuaSemanticTokensEdit(start, deleteCount, data)); + } + + return new LuaSemanticTokensDeltaResponse(resultId, Data: null, edits); + } + + return new LuaSemanticTokensDeltaResponse(resultId, Data: null, Edits: null); + } + + /// + /// Applies a list of LSP semantic-token edits (as returned by `semanticTokens/full/delta`) to a + /// previously cached integer stream. Returns the new stream, or if any + /// edit is out of range. + /// + public static int[]? ApplyEdits(int[] previousData, IReadOnlyList edits) + { + ArgumentNullException.ThrowIfNull(previousData); + ArgumentNullException.ThrowIfNull(edits); + + // LSP guarantees edits are sorted by ascending start, but applying them in reverse keeps the + // untouched suffix indices stable and avoids any index shifting on the way through. + var ordered = new List(edits); + ordered.Sort(static (a, b) => a.Start.CompareTo(b.Start)); + + int newLength = previousData.Length; + + foreach (LuaSemanticTokensEdit edit in ordered) + { + if (edit.Start < 0 || edit.DeleteCount < 0 || edit.Start + edit.DeleteCount > previousData.Length) + return null; + + newLength += edit.Data.Length - edit.DeleteCount; + } + + if (newLength < 0) + return null; + + int[] result = new int[newLength]; + int sourceIndex = 0; + int destinationIndex = 0; + + foreach (LuaSemanticTokensEdit edit in ordered) + { + int copyLength = edit.Start - sourceIndex; + + if (copyLength > 0) + { + Array.Copy(previousData, sourceIndex, result, destinationIndex, copyLength); + destinationIndex += copyLength; + } + + if (edit.Data.Length > 0) + { + Array.Copy(edit.Data, 0, result, destinationIndex, edit.Data.Length); + destinationIndex += edit.Data.Length; + } + + sourceIndex = edit.Start + edit.DeleteCount; + } + + int tailLength = previousData.Length - sourceIndex; + + if (tailLength > 0) + { + Array.Copy(previousData, sourceIndex, result, destinationIndex, tailLength); + destinationIndex += tailLength; + } + + return destinationIndex == newLength ? result : null; + } + + private static int[] ReadIntArray(JsonElement arrayElement) + { + int[] data = new int[arrayElement.GetArrayLength()]; + int index = 0; + + foreach (JsonElement value in arrayElement.EnumerateArray()) + data[index++] = value.TryGetInt32(out int parsed) ? parsed : 0; + + return data; + } +} + +/// +/// Decodes a raw LuaLS semantic-token integer stream (already cached on the client) into the typed +/// list expected by the editor's colorizer. Mirrors +/// but operates directly on the cached array. +/// +internal static class LuaLanguageServerSemanticTokensDecoder +{ + private static readonly IReadOnlyList EmptyModifiers = []; + + public static IReadOnlyList Decode(int[] data, LuaDocumentSnapshot? document, + IReadOnlyList? tokenTypes, IReadOnlyList? tokenModifiers) + { + if (data.Length == 0 || document is null || tokenTypes is null || tokenTypes.Count == 0) + return []; + + LuaDocumentLineOffsets lineOffsets = LuaDocumentLineOffsets.Build(document.Content); + var semanticTokens = new List(data.Length / 5); + Dictionary>? modifierCache = null; + + int line = 0; + int character = 0; + + for (int tupleStart = 0; tupleStart + 4 < data.Length; tupleStart += 5) + { + int deltaLine = data[tupleStart]; + int deltaCharacter = data[tupleStart + 1]; + int length = data[tupleStart + 2]; + int tokenTypeIndex = data[tupleStart + 3]; + int modifierMask = data[tupleStart + 4]; + + line += deltaLine; + character = deltaLine == 0 ? character + deltaCharacter : deltaCharacter; + + if (line < 0 || line >= lineOffsets.LineCount || tokenTypeIndex < 0 || tokenTypeIndex >= tokenTypes.Count) + continue; + + int lineLength = lineOffsets.GetLineLength(line); + int safeCharacter = Math.Max(0, Math.Min(character, lineLength)); + int safeLength = Math.Max(0, Math.Min(length, lineLength - safeCharacter)); + + if (safeLength == 0) + continue; + + semanticTokens.Add(new LuaSemanticToken( + line, + safeCharacter, + safeLength, + tokenTypes[tokenTypeIndex], + GetOrAddModifiers(ref modifierCache, modifierMask, tokenModifiers))); + } + + return semanticTokens; + } + + private static IReadOnlyList GetOrAddModifiers( + ref Dictionary>? cache, + int modifierMask, + IReadOnlyList? tokenModifiers) + { + if (modifierMask == 0 || tokenModifiers is null || tokenModifiers.Count == 0) + return EmptyModifiers; + + cache ??= []; + + if (cache.TryGetValue(modifierMask, out IReadOnlyList? cached)) + return cached; + + var modifiers = new List(); + + for (int bitIndex = 0; bitIndex < tokenModifiers.Count; bitIndex++) + { + if ((modifierMask & (1 << bitIndex)) != 0) + modifiers.Add(tokenModifiers[bitIndex]); + } + + cache[modifierMask] = modifiers; + return modifiers; + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs index cb1b6a8845..cb911cec35 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs @@ -1,6 +1,5 @@ #nullable enable -using System; using System.Collections.Generic; using System.Text.Json; using TombLib.Scripting.Lua.Objects; @@ -18,76 +17,11 @@ public static IReadOnlyList Parse(JsonElement response, LuaDoc if (document is null || tokenTypes is null || tokenTypes.Count == 0) return []; - if (!response.TryGetProperty("data", out JsonElement dataElement) || dataElement.ValueKind != JsonValueKind.Array) - return []; - - string[] lines = NormalizeLineEndings(document.Content).Split('\n'); - var semanticTokens = new List(); - var rawData = new List(); - - foreach (JsonElement item in dataElement.EnumerateArray()) - { - if (item.TryGetInt32(out int value)) - rawData.Add(value); - } - - int line = 0; - int character = 0; - - for (int i = 0; i + 4 < rawData.Count; i += 5) - { - int deltaLine = rawData[i]; - int deltaCharacter = rawData[i + 1]; - int length = rawData[i + 2]; - int tokenTypeIndex = rawData[i + 3]; - int modifierMask = rawData[i + 4]; - - line += deltaLine; - - if (deltaLine == 0) - character += deltaCharacter; - else - character = deltaCharacter; - - if (line < 0 || line >= lines.Length || tokenTypeIndex < 0 || tokenTypeIndex >= tokenTypes.Count) - continue; - - int lineLength = lines[line].Length; - int safeCharacter = Math.Max(0, Math.Min(character, lineLength)); - int safeLength = Math.Max(0, Math.Min(length, lineLength - safeCharacter)); + LuaSemanticTokensDeltaResponse parsedResponse = LuaLanguageServerSemanticTokensDeltaParser.Parse(response); - if (safeLength == 0) - continue; - - semanticTokens.Add(new LuaSemanticToken( - line, - safeCharacter, - safeLength, - tokenTypes[tokenTypeIndex], - DecodeModifiers(modifierMask, tokenModifiers))); - } - - return semanticTokens; - } - - private static IReadOnlyList DecodeModifiers(int modifierMask, IReadOnlyList? tokenModifiers) - { - if (modifierMask == 0 || tokenModifiers is null || tokenModifiers.Count == 0) + if (parsedResponse.Data is not { } data) return []; - var modifiers = new List(); - - for (int bitIndex = 0; bitIndex < tokenModifiers.Count; bitIndex++) - { - if ((modifierMask & (1 << bitIndex)) != 0) - modifiers.Add(tokenModifiers[bitIndex]); - } - - return modifiers; + return LuaLanguageServerSemanticTokensDecoder.Decode(data, document, tokenTypes, tokenModifiers); } - - private static string NormalizeLineEndings(string? content) - => (content ?? string.Empty) - .Replace("\r\n", "\n", StringComparison.Ordinal) - .Replace('\r', '\n'); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs index 3c3a772edd..b9cc7e6c59 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs @@ -14,9 +14,7 @@ internal static class LuaLanguageServerSettingsFactory public static object Create(string workspaceRootDirectoryPath) { string apiDirectory = Path.Combine(workspaceRootDirectoryPath, ".API"); - string[] library = Directory.Exists(apiDirectory) - ? [Path.GetFullPath(apiDirectory)] - : []; + string[] library = Directory.Exists(apiDirectory) ? [apiDirectory] : []; return new { @@ -28,7 +26,7 @@ public static object Create(string workspaceRootDirectoryPath) }, workspace = new { - checkThirdParty = false, + checkThirdParty = "Disable", library }, completion = new @@ -45,10 +43,6 @@ public static object Create(string workspaceRootDirectoryPath) diagnostics = new { disable = new[] { "duplicate-set-field" } - }, - telemetry = new - { - enable = false } } }; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs new file mode 100644 index 0000000000..d347061ff1 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs @@ -0,0 +1,166 @@ +#nullable enable + +using NLog; +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Wraps a Windows job object configured with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE so that any +/// child processes assigned to it are forcibly terminated when the host (TombIDE) crashes or the +/// last handle to the job is released. This prevents stranded lua-language-server.exe +/// processes if the editor never gets a chance to run its disposal path. +/// +[SupportedOSPlatform("windows")] +internal static class LuaProcessJobObject +{ + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private static readonly object SyncRoot = new(); + private static IntPtr _jobHandle = IntPtr.Zero; + private static bool _initializationFailed; + + public static void TryAssignProcess(Process process) + { + if (process is null) + return; + + if (!OperatingSystem.IsWindows()) + return; + + IntPtr jobHandle = EnsureJobHandle(); + + if (jobHandle == IntPtr.Zero) + return; + + try + { + if (!AssignProcessToJobObject(jobHandle, process.Handle)) + { + int errorCode = Marshal.GetLastWin32Error(); + + // 5 = ERROR_ACCESS_DENIED. Pre-Windows 8 hosts (which TombIDE no longer ships for) + // or processes already inside an unbreakable job will return this; we just log and move on. + Log.Debug("AssignProcessToJobObject failed with Win32 error {ErrorCode} for the Lua language server process.", errorCode); + } + } + catch (Exception exception) + { + Log.Debug(exception, "Failed to assign the Lua language server process to the kill-on-close job object."); + } + } + + private static IntPtr EnsureJobHandle() + { + if (_jobHandle != IntPtr.Zero) + return _jobHandle; + + if (_initializationFailed) + return IntPtr.Zero; + + lock (SyncRoot) + { + if (_jobHandle != IntPtr.Zero) + return _jobHandle; + + if (_initializationFailed) + return IntPtr.Zero; + + IntPtr handle = CreateJobObject(IntPtr.Zero, lpName: null); + + if (handle == IntPtr.Zero) + { + _initializationFailed = true; + Log.Debug("CreateJobObject returned NULL (Win32 error {ErrorCode}); the Lua language server will rely on graceful shutdown.", Marshal.GetLastWin32Error()); + return IntPtr.Zero; + } + + JobObjectExtendedLimitInformation extendedLimit = default; + extendedLimit.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + + int payloadSize = Marshal.SizeOf(); + IntPtr payloadPointer = Marshal.AllocHGlobal(payloadSize); + + try + { + Marshal.StructureToPtr(extendedLimit, payloadPointer, fDeleteOld: false); + + if (!SetInformationJobObject(handle, JobObjectInformationClass.ExtendedLimitInformation, payloadPointer, (uint)payloadSize)) + { + int errorCode = Marshal.GetLastWin32Error(); + CloseHandle(handle); + _initializationFailed = true; + Log.Debug("SetInformationJobObject failed with Win32 error {ErrorCode}; the Lua language server will rely on graceful shutdown.", errorCode); + return IntPtr.Zero; + } + } + finally + { + Marshal.FreeHGlobal(payloadPointer); + } + + _jobHandle = handle; + AppDomain.CurrentDomain.ProcessExit += (_, _) => CloseHandle(handle); + return handle; + } + } + + private const uint JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000; + + private enum JobObjectInformationClass + { + ExtendedLimitInformation = 9 + } + + [StructLayout(LayoutKind.Sequential)] + private struct IoCounters + { + public ulong ReadOperationCount; + public ulong WriteOperationCount; + public ulong OtherOperationCount; + public ulong ReadTransferCount; + public ulong WriteTransferCount; + public ulong OtherTransferCount; + } + + [StructLayout(LayoutKind.Sequential)] + private struct JobObjectBasicLimitInformation + { + public long PerProcessUserTimeLimit; + public long PerJobUserTimeLimit; + public uint LimitFlags; + public UIntPtr MinimumWorkingSetSize; + public UIntPtr MaximumWorkingSetSize; + public uint ActiveProcessLimit; + public UIntPtr Affinity; + public uint PriorityClass; + public uint SchedulingClass; + } + + [StructLayout(LayoutKind.Sequential)] + private struct JobObjectExtendedLimitInformation + { + public JobObjectBasicLimitInformation BasicLimitInformation; + public IoCounters IoInfo; + public UIntPtr ProcessMemoryLimit; + public UIntPtr JobMemoryLimit; + public UIntPtr PeakProcessMemoryUsed; + public UIntPtr PeakJobMemoryUsed; + } + + [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string? lpName); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInformationClass infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess); + + [DllImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool CloseHandle(IntPtr hObject); +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs new file mode 100644 index 0000000000..d7969a55c8 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs @@ -0,0 +1,13 @@ +#nullable enable + +using System.Collections.Generic; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal sealed class LuaPublishedDiagnostics(string filePath, IReadOnlyList diagnostics, int version) +{ + public string FilePath { get; } = filePath; + public IReadOnlyList Diagnostics { get; } = diagnostics ?? []; + public int Version { get; } = version; +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs new file mode 100644 index 0000000000..1a1aa1d6e9 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs @@ -0,0 +1,208 @@ +#nullable enable + +using NLog; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Watches the Lua workspace root for relevant external file changes (`*.lua`, `.luarc.json`, +/// `.luarc.jsonc`) and forwards them to LuaLS through `workspace/didChangeWatchedFiles`. LuaLS does +/// not poll the file system itself for clients that opt into this capability, so without this hook +/// changes made by Git pull, file copy, or any other out-of-band tool would not reach the language +/// server until the user touched the affected document inside TombIDE. +/// +internal sealed class LuaWorkspaceFileWatcher : IDisposable +{ + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private static readonly TimeSpan DispatchDebounce = TimeSpan.FromMilliseconds(250); + + private readonly string _workspaceRootDirectoryPath; + private readonly Func _dispatchAsync; + private readonly ConcurrentDictionary _pendingChanges = new(StringComparer.OrdinalIgnoreCase); + private readonly SemaphoreSlim _dispatchGate = new(1, 1); + private readonly CancellationTokenSource _lifetimeCts = new(); + + private FileSystemWatcher? _luaWatcher; + private FileSystemWatcher? _configWatcher; + private Timer? _debounceTimer; + private volatile bool _isDisposed; + + public LuaWorkspaceFileWatcher(string workspaceRootDirectoryPath, Func dispatchAsync) + { + _workspaceRootDirectoryPath = workspaceRootDirectoryPath; + _dispatchAsync = dispatchAsync; + } + + public bool Start() + { + if (_isDisposed || _luaWatcher is not null) + return _luaWatcher is not null; + + if (!Directory.Exists(_workspaceRootDirectoryPath)) + return false; + + try + { + _luaWatcher = CreateWatcher("*.lua", includeSubdirectories: true); + _configWatcher = CreateWatcher(".luarc.*", includeSubdirectories: false); + _debounceTimer = new Timer(OnDebounceTick, state: null, dueTime: Timeout.Infinite, period: Timeout.Infinite); + + return true; + } + catch (Exception exception) + { + Log.Debug(exception, "Failed to start the Lua workspace file watcher for '{Workspace}'.", _workspaceRootDirectoryPath); + Dispose(); + + return false; + } + } + + private FileSystemWatcher CreateWatcher(string filter, bool includeSubdirectories) + { + var watcher = new FileSystemWatcher(_workspaceRootDirectoryPath, filter) + { + IncludeSubdirectories = includeSubdirectories, + NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.CreationTime | NotifyFilters.DirectoryName, + InternalBufferSize = 64 * 1024 + }; + + watcher.Created += (_, e) => QueueChange(e.FullPath, FileChangeKind.Created); + watcher.Changed += (_, e) => QueueChange(e.FullPath, FileChangeKind.Changed); + watcher.Deleted += (_, e) => QueueChange(e.FullPath, FileChangeKind.Deleted); + watcher.Renamed += (_, e) => + { + QueueChange(e.OldFullPath, FileChangeKind.Deleted); + QueueChange(e.FullPath, FileChangeKind.Created); + }; + watcher.Error += (_, e) => Log.Debug(e.GetException(), "Lua workspace file watcher reported an error."); + watcher.EnableRaisingEvents = true; + return watcher; + } + + private void QueueChange(string filePath, FileChangeKind kind) + { + if (_isDisposed || string.IsNullOrEmpty(filePath)) + return; + + // Coalesce multiple events for the same path: a Created event keeps winning over later Changed + // events for the same file, while a transient delete-then-create collapse is reported as a + // single Changed notification because the path exists again but its contents may have changed. + _pendingChanges.AddOrUpdate(filePath, kind, (_, existing) => Combine(existing, kind)); + _debounceTimer?.Change(DispatchDebounce, Timeout.InfiniteTimeSpan); + } + + private static FileChangeKind Combine(FileChangeKind existing, FileChangeKind incoming) + { + if (existing == FileChangeKind.Created && incoming == FileChangeKind.Deleted) + return FileChangeKind.Deleted; + + if (existing == FileChangeKind.Deleted && incoming == FileChangeKind.Created) + return FileChangeKind.Changed; + + return existing == FileChangeKind.Created ? FileChangeKind.Created : incoming; + } + + private void OnDebounceTick(object? _) + { + if (_isDisposed || _pendingChanges.IsEmpty) + return; + + _ = DispatchPendingChangesAsync(); + } + + private async Task DispatchPendingChangesAsync() + { + bool dispatchGateHeld = false; + + try + { + await _dispatchGate.WaitAsync(_lifetimeCts.Token).ConfigureAwait(false); + dispatchGateHeld = true; + + if (_pendingChanges.IsEmpty) + return; + + var batch = new FileChangeBatch(); + + foreach (var entry in _pendingChanges) + { + if (_pendingChanges.TryRemove(entry.Key, out FileChangeKind removedKind)) + batch.Add(entry.Key, removedKind); + } + + if (batch.Count == 0) + return; + + await _dispatchAsync(batch, _lifetimeCts.Token).ConfigureAwait(false); + } + catch (OperationCanceledException) + { } + catch (ObjectDisposedException) + { } + catch (Exception exception) + { + Log.Debug(exception, "Lua workspace file watcher dispatch failed."); + } + finally + { + if (dispatchGateHeld) + _dispatchGate.Release(); + } + } + + public void Dispose() + { + if (_isDisposed) + return; + + _isDisposed = true; + + TryDispose(_luaWatcher, nameof(_luaWatcher)); + TryDispose(_configWatcher, nameof(_configWatcher)); + TryDispose(_debounceTimer, nameof(_debounceTimer)); + + try { _lifetimeCts.Cancel(); } catch (ObjectDisposedException) { } + + _lifetimeCts.Dispose(); + _dispatchGate.Dispose(); + } + + private static void TryDispose(IDisposable? disposable, string resourceName) + { + if (disposable is null) + return; + + try + { + disposable.Dispose(); + } + catch (Exception exception) + { + Log.Debug(exception, "Failed to dispose Lua workspace watcher resource '{ResourceName}'.", resourceName); + } + } +} + +internal enum FileChangeKind +{ + Created = 1, + Changed = 2, + Deleted = 3 +} + +internal sealed class FileChangeBatch +{ + private readonly List<(string Path, FileChangeKind Kind)> _entries = []; + + public int Count => _entries.Count; + public IReadOnlyList<(string Path, FileChangeKind Kind)> Entries => _entries; + + public void Add(string path, FileChangeKind kind) => _entries.Add((path, kind)); +} diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index 4207fc8b65..a5eaf36b74 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -13,22 +13,28 @@ internal sealed class LuaSemanticTokensColorizer : DocumentColorizingTransformer { private static readonly TextDecorationCollection DeprecatedDecorations = CreateTextDecorations(TextDecorations.Strikethrough); - private static readonly IReadOnlyDictionary> EmptyTokensByLine = - new Dictionary>(); + private static readonly IReadOnlyDictionary> EmptyTokensByLine = + new Dictionary>(); private LuaThemeBrushSet _themeBrushSet; private readonly TextView _textView; - private IReadOnlyDictionary> _tokensByLine = EmptyTokensByLine; + + // Tokens are pre-styled at SetTokens time so that ColorizeLine, which runs on every redraw and + // for every visible line, can avoid re-resolving brushes and modifier flags per token. + private IReadOnlyList _rawTokens = []; + + private IReadOnlyDictionary> _tokensByLine = EmptyTokensByLine; public LuaSemanticTokensColorizer(TextView textView, LuaThemeBrushSet themeBrushSet) { - _textView = textView ?? throw new ArgumentNullException(nameof(textView)); - _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); + _textView = textView; + _themeBrushSet = themeBrushSet; } public void UpdateTheme(LuaThemeBrushSet themeBrushSet) { - _themeBrushSet = themeBrushSet ?? throw new ArgumentNullException(nameof(themeBrushSet)); + _themeBrushSet = themeBrushSet; + _tokensByLine = BuildStyledMap(_rawTokens, _themeBrushSet); _textView.Redraw(); } @@ -40,96 +46,103 @@ public void SetTokens(IReadOnlyList tokens) return; } - var groupedTokens = new Dictionary>(); - - for (int i = 0; i < tokens.Count; i++) - { - LuaSemanticToken token = tokens[i]; - - if (!groupedTokens.TryGetValue(token.Line, out List? lineTokens) || lineTokens is null) - { - lineTokens = []; - groupedTokens[token.Line] = lineTokens; - } - - lineTokens.Add(token); - } - - var frozenMap = new Dictionary>(groupedTokens.Count); - - foreach (KeyValuePair> pair in groupedTokens) - { - pair.Value.Sort((left, right) => - { - int characterComparison = left.Character.CompareTo(right.Character); - - if (characterComparison != 0) - return characterComparison; - - return left.Length.CompareTo(right.Length); - }); - - frozenMap[pair.Key] = pair.Value; - } - - _tokensByLine = frozenMap; + _rawTokens = tokens; + _tokensByLine = BuildStyledMap(tokens, _themeBrushSet); _textView.Redraw(); } public void ClearTokens() { - if (_tokensByLine.Count == 0) + if (_tokensByLine.Count == 0 && _rawTokens.Count == 0) return; + _rawTokens = []; _tokensByLine = EmptyTokensByLine; _textView.Redraw(); } protected override void ColorizeLine(DocumentLine line) { - if (!_tokensByLine.TryGetValue(line.LineNumber - 1, out IReadOnlyList? tokens) || tokens is null) + if (!_tokensByLine.TryGetValue(line.LineNumber - 1, out IReadOnlyList? tokens)) return; int lineLength = line.Length; for (int i = 0; i < tokens.Count; i++) { - LuaSemanticToken token = tokens[i]; - int startIndex = Math.Max(0, Math.Min(token.Character, lineLength)); - int endIndex = Math.Max(startIndex, Math.Min(token.Character + token.Length, lineLength)); + StyledSemanticToken styled = tokens[i]; + int startIndex = Math.Max(0, Math.Min(styled.Character, lineLength)); + int endIndex = Math.Max(startIndex, Math.Min(styled.Character + styled.Length, lineLength)); if (endIndex <= startIndex) continue; - LuaSemanticTokenStyle style = ResolveStyle(token); + LuaSemanticTokenStyle style = styled.Style; + ChangeLinePart(line.Offset + startIndex, line.Offset + endIndex, element => ApplyStyle(element, style)); + } + } + + private static IReadOnlyDictionary> BuildStyledMap( + IReadOnlyList tokens, LuaThemeBrushSet themeBrushSet) + { + if (tokens.Count == 0) + return EmptyTokensByLine; + + var grouped = new Dictionary>(); + + for (int i = 0; i < tokens.Count; i++) + { + LuaSemanticToken token = tokens[i]; + LuaSemanticTokenStyle style = ResolveStyle(token, themeBrushSet); if (!style.HasFormatting) continue; - ChangeLinePart(line.Offset + startIndex, line.Offset + endIndex, element => ApplyStyle(element, style)); + if (!grouped.TryGetValue(token.Line, out List? lineTokens)) + { + lineTokens = []; + grouped[token.Line] = lineTokens; + } + + lineTokens.Add(new StyledSemanticToken(token.Character, token.Length, style)); } + + var frozen = new Dictionary>(grouped.Count); + + foreach (KeyValuePair> pair in grouped) + { + pair.Value.Sort(static (left, right) => + { + int characterComparison = left.Character.CompareTo(right.Character); + return characterComparison != 0 ? characterComparison : left.Length.CompareTo(right.Length); + }); + + frozen[pair.Key] = pair.Value; + } + + return frozen; } - private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) + private static LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token, LuaThemeBrushSet brushSet) { Brush? foreground = token.Type switch { - "namespace" => _themeBrushSet.TypeBrush, - "type" => _themeBrushSet.TypeBrush, - "class" => _themeBrushSet.TypeBrush, - "enum" => _themeBrushSet.TypeBrush, - "interface" => _themeBrushSet.TypeBrush, - "struct" => _themeBrushSet.TypeBrush, - "typeParameter" => _themeBrushSet.TypeBrush, - "function" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, - "method" => token.HasModifier("defaultLibrary") ? _themeBrushSet.TypeBrush : _themeBrushSet.MethodBrush, - "parameter" => _themeBrushSet.VariableBrush, - "property" => _themeBrushSet.PropertyBrush, - "event" => _themeBrushSet.VariableBrush, - "enumMember" => _themeBrushSet.ConstantBrush, - "decorator" => _themeBrushSet.KeywordBrush, - "macro" => _themeBrushSet.KeywordBrush, - "variable" => ResolveVariableBrush(token), + "namespace" => brushSet.TypeBrush, + "type" => brushSet.TypeBrush, + "class" => brushSet.TypeBrush, + "enum" => brushSet.TypeBrush, + "interface" => brushSet.TypeBrush, + "struct" => brushSet.TypeBrush, + "typeParameter" => brushSet.TypeBrush, + "function" => token.HasModifier("defaultLibrary") ? brushSet.TypeBrush : brushSet.MethodBrush, + "method" => token.HasModifier("defaultLibrary") ? brushSet.TypeBrush : brushSet.MethodBrush, + "parameter" => brushSet.VariableBrush, + "property" => brushSet.PropertyBrush, + "event" => brushSet.VariableBrush, + "enumMember" => brushSet.ConstantBrush, + "decorator" => brushSet.KeywordBrush, + "macro" => brushSet.KeywordBrush, + "variable" => ResolveVariableBrush(token, brushSet), _ => null }; @@ -139,15 +152,15 @@ private LuaSemanticTokenStyle ResolveStyle(LuaSemanticToken token) token.HasModifier("deprecated") ? DeprecatedDecorations : null); } - private Brush? ResolveVariableBrush(LuaSemanticToken token) + private static SolidColorBrush? ResolveVariableBrush(LuaSemanticToken token, LuaThemeBrushSet brushSet) { if (token.HasModifier("defaultLibrary")) - return _themeBrushSet.TypeBrush; + return brushSet.TypeBrush; if (token.HasModifier("global")) - return _themeBrushSet.PropertyBrush; + return brushSet.PropertyBrush; - return _themeBrushSet.VariableBrush; + return brushSet.VariableBrush; } private static void ApplyStyle(VisualLineElement element, LuaSemanticTokenStyle style) @@ -174,18 +187,18 @@ private static TextDecorationCollection CreateTextDecorations(TextDecorationColl return clone; } - private readonly struct LuaSemanticTokenStyle + private readonly struct StyledSemanticToken(int character, int length, LuaSemanticTokenStyle style) { - public LuaSemanticTokenStyle(Brush? foreground, bool isBold, TextDecorationCollection? textDecorations) - { - Foreground = foreground; - IsBold = isBold; - TextDecorations = textDecorations; - } + public int Character { get; } = character; + public int Length { get; } = length; + public LuaSemanticTokenStyle Style { get; } = style; + } - public Brush? Foreground { get; } - public bool IsBold { get; } - public TextDecorationCollection? TextDecorations { get; } + private readonly struct LuaSemanticTokenStyle(Brush? foreground, bool isBold, TextDecorationCollection? textDecorations) + { + public Brush? Foreground { get; } = foreground; + public bool IsBold { get; } = isBold; + public TextDecorationCollection? TextDecorations { get; } = textDecorations; public bool HasFormatting => Foreground is not null || IsBold || TextDecorations is not null; } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index c01ef67d80..ce39244bb5 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -1,7 +1,6 @@ using ICSharpCode.AvalonEdit.CodeCompletion; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Threading; @@ -24,18 +23,29 @@ public sealed partial class LuaEditor private const int CompletionWindowMinWidth = 420; private const int CompletionWindowMaxWidth = 920; private const int CompletionWindowHeight = 320; + private const int CompletionWidthMeasurementSampleCount = 80; private const double CompletionToolTipHorizontalOffset = 10.0; private const double CompletionToolTipResolveDelayInMilliseconds = 120.0; private const double CompletionWindowHorizontalChrome = 52.0; private const double CompletionItemIconWidth = 24.0; private const double CompletionItemDetailSpacing = 12.0; - private static readonly FieldInfo? CompletionToolTipField = - typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); + // Reflection target: AvalonEdit's CompletionWindow keeps the documentation tooltip in a private field named "toolTip". + // Verified against the AvalonEdit version pinned in TombLib.Scripting.Lua.csproj. + private static readonly Lazy CompletionToolTipFieldAccessor = new(() => + { + FieldInfo? field = typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); + + if (field is null) + Log?.Debug("AvalonEdit completion tooltip styling is unavailable because the internal tooltip field could not be found."); - private static bool _completionToolTipFieldLoggedMissing; + return field; + }); + + private static FieldInfo? CompletionToolTipField => CompletionToolTipFieldAccessor.Value; private CancellationTokenSource? _completionCancellationTokenSource; + private CancellationTokenSource? _completionToolTipCancellationTokenSource; private int _completionRequestToken; private int _completionToolTipUpdateToken; @@ -74,10 +84,10 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) DismissSignatureHelp(); CloseDefinitionToolTip(true); - (int line, int column) = GetPositionFromOffset(offset); + (int Line, int Column) = GetPositionFromOffset(offset); var items = await IntellisenseProvider - .GetCompletionItemsAsync(FilePath, Text, line, column, triggerCharacter, cancellationToken) + .GetCompletionItemsAsync(FilePath, Text, Line, Column, triggerCharacter, cancellationToken) .ConfigureAwait(true); if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) @@ -118,7 +128,7 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) catch (Exception exception) { CloseCompletionWindow(); - WriteDebugFailure("Completion request", exception); + LogEditorFailure("Completion request", exception); } } @@ -128,15 +138,7 @@ private void StyleCompletionTooltip() return; if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) - { - if (!_completionToolTipFieldLoggedMissing) - { - _completionToolTipFieldLoggedMissing = true; - Debug.WriteLine("[Lua] AvalonEdit completion tooltip styling is unavailable because the internal tooltip field could not be found."); - } - return; - } tooltip.Background = DefaultToolTipBackground; tooltip.BorderBrush = DefaultToolTipBorder; @@ -168,13 +170,14 @@ private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseBu private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) { int updateToken = ++_completionToolTipUpdateToken; + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionToolTipCancellationTokenSource); Dispatcher.BeginInvoke( - new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, updateToken)), + new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, updateToken, cancellationToken)), DispatcherPriority.Background); } - private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken) + private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken, CancellationToken cancellationToken) { if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) return; @@ -196,12 +199,12 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) { - await Task.Delay(TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds)).ConfigureAwait(true); + await Task.Delay(TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds), cancellationToken).ConfigureAwait(true); if (updateToken != _completionToolTipUpdateToken) return; - object? resolvedDescription = await luaCompletionData.GetDescriptionAsync().ConfigureAwait(true); + object? resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); if (updateToken != _completionToolTipUpdateToken) return; @@ -219,43 +222,52 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken tooltip.IsOpen = false; } } + catch (OperationCanceledException) + { + // Newer selection or close superseded this tooltip update. + } catch (Exception exception) { tooltip.IsOpen = false; - WriteDebugFailure("Completion tooltip update", exception); + LogEditorFailure("Completion tooltip update", exception); } } - private void ResizeCompletionWindow(IReadOnlyList completionDataItems) + private void ResizeCompletionWindow(LuaCompletionData[] completionDataItems) { - if (_completionWindow is null || completionDataItems is null || completionDataItems.Count == 0) + if (_completionWindow is null || completionDataItems is null || completionDataItems.Length == 0) return; double requiredWidth = CompletionWindowMinWidth; + int measurementCount = Math.Min(completionDataItems.Length, CompletionWidthMeasurementSampleCount); + var textWidthCache = new Dictionary(StringComparer.Ordinal); - for (int i = 0; i < completionDataItems.Count; i++) - requiredWidth = Math.Max(requiredWidth, MeasureCompletionItemWidth(completionDataItems[i])); + for (int i = 0; i < measurementCount; i++) + requiredWidth = Math.Max(requiredWidth, MeasureCompletionItemWidth(completionDataItems[i], textWidthCache)); _completionWindow.Width = Math.Max( CompletionWindowMinWidth, Math.Min(CompletionWindowMaxWidth, requiredWidth + CompletionWindowHorizontalChrome)); } - private double MeasureCompletionItemWidth(LuaCompletionData completionData) + private double MeasureCompletionItemWidth(LuaCompletionData completionData, IDictionary textWidthCache) { - double width = CompletionItemIconWidth + MeasureCompletionTextWidth(completionData.DisplayText); + double width = CompletionItemIconWidth + MeasureCompletionTextWidth(completionData.DisplayText, textWidthCache); if (!string.IsNullOrWhiteSpace(completionData.DisplayDetail)) - width += CompletionItemDetailSpacing + MeasureCompletionTextWidth(completionData.DisplayDetail); + width += CompletionItemDetailSpacing + MeasureCompletionTextWidth(completionData.DisplayDetail, textWidthCache); return width; } - private double MeasureCompletionTextWidth(string text) + private double MeasureCompletionTextWidth(string text, IDictionary textWidthCache) { if (string.IsNullOrWhiteSpace(text)) return 0.0; + if (textWidthCache.TryGetValue(text, out double cachedWidth)) + return cachedWidth; + double pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip; var formattedText = new FormattedText( @@ -267,7 +279,9 @@ private double MeasureCompletionTextWidth(string text) Foreground, pixelsPerDip); - return formattedText.WidthIncludingTrailingWhitespace; + double width = formattedText.WidthIncludingTrailingWhitespace; + textWidthCache[text] = width; + return width; } private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) @@ -286,7 +300,10 @@ private static void ApplyCompletionToolTipContent(ToolTip tooltip, object conten } private void CancelCompletionToolTipUpdate() - => _completionToolTipUpdateToken++; + { + _completionToolTipUpdateToken++; + _completionToolTipCancellationTokenSource?.Cancel(); + } private void ScheduleCloseIfEmpty() => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index 3f6f5470b6..fe70b149c9 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -29,9 +29,7 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (!TryGetHoverRequestOffset(hoveredOffset, out int hoverOffset) || !IsIntellisenseAvailable()) { - if (canShowDiagnosticFallback) - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); - + ShowDiagnosticToolTipIfAvailable(canShowDiagnosticFallback, hasDiagnostic, diagnosticMessage, diagnosticSeverity); return; } @@ -59,10 +57,8 @@ protected override async void HandleMouseHover(MouseEventArgs e) { } catch (Exception exception) { - WriteDebugFailure("Hover request", exception); - - if (canShowDiagnosticFallback) - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + LogEditorFailure("Hover request", exception); + ShowDiagnosticToolTipIfAvailable(canShowDiagnosticFallback, hasDiagnostic, diagnosticMessage, diagnosticSeverity); } } @@ -79,20 +75,31 @@ private bool TryGetHoverRequestOffset(int hoveredOffset, out int hoverOffset) return !string.IsNullOrWhiteSpace(GetWordFromOffset(hoverOffset)); } - private void ShowDiagnosticToolTipIfAvailable(bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + private void ShowDiagnosticToolTipIfAvailable(bool canShowDiagnosticFallback, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) { - if (hasDiagnostic) + if (canShowDiagnosticFallback && hasDiagnostic) ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); } private void ShowBestHoverToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) { - if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) && hasDiagnostic) - ShowCombinedHoverAndDiagnosticToolTip(hoverInfo, diagnosticMessage, diagnosticSeverity); - else if (hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content)) - ShowHoverToolTip(hoverInfo); - else - ShowDiagnosticToolTipIfAvailable(hasDiagnostic, diagnosticMessage, diagnosticSeverity); + // Recompute eligibility: a completion window or signature popup may have opened during the + // asynchronous hover request; we must not paint a hover tooltip on top of either of them. + bool canShowToolTip = _completionWindow is null && !_signaturePopup.IsOpen; + + if (!canShowToolTip) + return; + + LuaHoverInfo? displayableHoverInfo = hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) + ? hoverInfo + : null; + + if (displayableHoverInfo is not null && hasDiagnostic) + ShowCombinedHoverAndDiagnosticToolTip(displayableHoverInfo, diagnosticMessage, diagnosticSeverity); + else if (displayableHoverInfo is not null) + ShowHoverToolTip(displayableHoverInfo); + else if (hasDiagnostic) + ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); } private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) @@ -137,10 +144,10 @@ private static FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo if (!IsIntellisenseAvailable()) return null; - (int line, int column) = GetPositionFromOffset(offset); + (int Line, int Column) = GetPositionFromOffset(offset); return await IntellisenseProvider - .GetHoverAsync(FilePath, Text, line, column, cancellationToken) + .GetHoverAsync(FilePath, Text, Line, Column, cancellationToken) .ConfigureAwait(true); } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index 06f6dc8a13..37019dc710 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -1,6 +1,5 @@ using ICSharpCode.AvalonEdit.Document; using System; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Windows; @@ -173,7 +172,7 @@ private void DismissTransientToolTips() CloseDefinitionToolTip(true); } - private (int line, int column) GetPositionFromOffset(int offset) + private (int Line, int Column) GetPositionFromOffset(int offset) { int safeOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); TextLocation location = Document.GetLocation(safeOffset); @@ -198,6 +197,6 @@ private static void CancelAndDispose(ref CancellationTokenSource? cancellationTo cancellationTokenSource = null; } - private static void WriteDebugFailure(string area, Exception exception) - => Debug.WriteLine($"[Lua] {area} failed: {exception}"); + private static void LogEditorFailure(string area, Exception exception) + => Log.Warn(exception, "Lua editor operation '{Area}' failed.", area); } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index bf29db6494..9f4d43d6c4 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; @@ -63,10 +62,10 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo if (!LuaEditorInteractionRules.TryGetDefinitionStartOffset(Document, offset, out int definitionOffset)) return false; - (int line, int column) = GetPositionFromOffset(definitionOffset); + (int Line, int Column) = GetPositionFromOffset(definitionOffset); LuaDefinitionLocation? definitionLocation = await IntellisenseProvider - .GetDefinitionAsync(FilePath, Text, line, column, cancellationToken) + .GetDefinitionAsync(FilePath, Text, Line, Column, cancellationToken) .ConfigureAwait(true); if (definitionLocation is null) @@ -81,7 +80,7 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo } catch (Exception exception) { - Debug.WriteLine($"[Lua] Go to definition failed: {exception}"); + LogEditorFailure("Go to definition", exception); return false; } } @@ -89,6 +88,7 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo /// /// Attempts to resolve and navigate to the symbol definition at the current caret position. /// - public async void NavigateToDefinitionAtCaretAsync() - => await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true); + /// A task that completes once the navigation attempt finishes. + public Task NavigateToDefinitionAtCaretAsync() + => TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None); } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs index bbbc711526..28b49693bb 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using TombLib.Scripting.Lua.Highlighting; using TombLib.Scripting.Lua.Objects; @@ -15,7 +16,7 @@ public sealed partial class LuaEditor public void SetSemanticTokens(IReadOnlyList tokens) { EnsureSemanticTokensColorizerAttached(); - _semanticTokensColorizer!.SetTokens(tokens); + _semanticTokensColorizer.SetTokens(tokens); } /// @@ -24,6 +25,7 @@ public void SetSemanticTokens(IReadOnlyList tokens) public void ClearSemanticTokens() => _semanticTokensColorizer?.ClearTokens(); + [MemberNotNull(nameof(_semanticTokensColorizer))] private void EnsureSemanticTokensColorizerAttached() { if (_semanticTokensColorizer is null) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index 9bd5827c54..d6dbcfd7cd 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -13,6 +13,8 @@ namespace TombLib.Scripting.Lua; public sealed partial class LuaEditor { + private const double SignaturePopupFontSize = 14.0; + private CancellationTokenSource? _signatureCancellationTokenSource; private readonly Popup _signaturePopup = new(); @@ -89,39 +91,29 @@ private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double c panel.Children.Add(BuildSignatureBlock(signatureInfo, brushSet)); if (!string.IsNullOrWhiteSpace(signatureInfo.Documentation)) - { - panel.Children.Add(new TextBlock - { - Text = signatureInfo.Documentation, - Foreground = brushSet.SignatureParamDocForeground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), - TextWrapping = TextWrapping.Wrap, - Margin = new Thickness(0.0, 4.0, 0.0, 0.0) - }); - } + panel.Children.Add(CreateSignatureDocumentationBlock(signatureInfo.Documentation, brushSet)); if (signatureInfo.ActiveParameter < signatureInfo.Parameters.Count) { LuaParameterInfo activeParam = signatureInfo.Parameters[signatureInfo.ActiveParameter]; if (!string.IsNullOrWhiteSpace(activeParam.Documentation)) - { - panel.Children.Add(new TextBlock - { - Text = activeParam.Label + ": " + activeParam.Documentation, - Foreground = brushSet.SignatureParamDocForeground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), - TextWrapping = TextWrapping.Wrap, - Margin = new Thickness(0.0, 4.0, 0.0, 0.0) - }); - } + panel.Children.Add(CreateSignatureDocumentationBlock(activeParam.Label + ": " + activeParam.Documentation, brushSet)); } return panel; } + private static TextBlock CreateSignatureDocumentationBlock(string text, LuaThemeBrushSet brushSet) => new() + { + Text = text, + Foreground = brushSet.SignatureParamDocForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, SignaturePopupFontSize), + TextWrapping = TextWrapping.Wrap, + Margin = new Thickness(0.0, 4.0, 0.0, 0.0) + }; + private void PositionSignaturePopup(Size popupSize) { AttachHostWindowHandlers(); @@ -138,14 +130,14 @@ private void PositionSignaturePopup(Size popupSize) Point editorPoint = TextArea.TextView.TranslatePoint(caretViewportPoint, this); double lineHeight = Math.Max(TextArea.TextView.DefaultLineHeight, caretRectangle.Height); double lineSlack = Math.Max(0.0, lineHeight - caretRectangle.Height); - double horizontalOffset = Math.Max(0.0, editorPoint.X + 2.0f); - double maxHorizontalOffset = Math.Max(0.0, ActualWidth - popupSize.Width - 8.0f); + double horizontalOffset = Math.Max(0.0, editorPoint.X + 2.0); + double maxHorizontalOffset = Math.Max(0.0, ActualWidth - popupSize.Width - 8.0); horizontalOffset = Math.Min(horizontalOffset, maxHorizontalOffset); - double verticalOffset = editorPoint.Y - popupSize.Height - lineSlack - 8.0f; + double verticalOffset = editorPoint.Y - popupSize.Height - lineSlack - 8.0; if (verticalOffset < 0.0) - verticalOffset = Math.Min(Math.Max(0.0, ActualHeight - popupSize.Height), editorPoint.Y + lineHeight + 4.0f); + verticalOffset = Math.Min(Math.Max(0.0, ActualHeight - popupSize.Height), editorPoint.Y + lineHeight + 4.0); _signaturePopup.HorizontalOffset = horizontalOffset; _signaturePopup.VerticalOffset = verticalOffset; @@ -163,10 +155,10 @@ private async Task RequestSignatureHelpAsync(int offset) try { - (int line, int column) = GetPositionFromOffset(offset); + (int Line, int Column) = GetPositionFromOffset(offset); LuaSignatureInfo? signatureInfo = await IntellisenseProvider - .GetSignatureHelpAsync(FilePath, Text, line, column, cancellationToken) + .GetSignatureHelpAsync(FilePath, Text, Line, Column, cancellationToken) .ConfigureAwait(true); if (cancellationToken.IsCancellationRequested) @@ -184,7 +176,7 @@ private async Task RequestSignatureHelpAsync(int offset) { } catch (Exception exception) { - WriteDebugFailure("Signature help", exception); + LogEditorFailure("Signature help", exception); } } @@ -196,47 +188,60 @@ private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo, Lua var textBlock = new TextBlock { FontFamily = new FontFamily("Consolas"), - FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0), + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, SignaturePopupFontSize), TextWrapping = TextWrapping.Wrap, Foreground = brushSet.SignatureForeground }; string label = signatureInfo.Label; - int paramStart = label.IndexOf('('); - if (paramStart < 0 || signatureInfo.Parameters.Count == 0) + if (signatureInfo.Parameters.Count == 0 + || !TryGetActiveParameterRange(label, signatureInfo, out int activeStart, out int activeEnd)) { textBlock.Text = label; return textBlock; } - textBlock.Inlines.Add(new Run(label[..(paramStart + 1)])); + if (activeStart > 0) + textBlock.Inlines.Add(new Run(label[..activeStart])); - string paramSection = label[(paramStart + 1)..]; - int closingParen = paramSection.LastIndexOf(')'); + textBlock.Inlines.Add(new Run(label[activeStart..activeEnd]) + { + FontWeight = FontWeights.Bold, + Foreground = brushSet.SignatureActiveParamForeground + }); - if (closingParen >= 0) - paramSection = paramSection[..closingParen]; + if (activeEnd < label.Length) + textBlock.Inlines.Add(new Run(label[activeEnd..])); - string[] parameterNames = paramSection.Split(','); + return textBlock; + } - for (int i = 0; i < parameterNames.Length; i++) - { - if (i > 0) - textBlock.Inlines.Add(new Run(", ")); + private static bool TryGetActiveParameterRange(string label, LuaSignatureInfo signatureInfo, out int activeStart, out int activeEnd) + { + activeStart = 0; + activeEnd = 0; - var run = new Run(parameterNames[i].Trim()); + int activeIndex = Math.Min(signatureInfo.ActiveParameter, signatureInfo.Parameters.Count - 1); - if (i == signatureInfo.ActiveParameter) - { - run.FontWeight = FontWeights.Bold; - run.Foreground = brushSet.SignatureActiveParamForeground; - } + if (activeIndex < 0) + return false; - textBlock.Inlines.Add(run); - } + string activeLabel = signatureInfo.Parameters[activeIndex].Label; - textBlock.Inlines.Add(new Run(")")); - return textBlock; + if (string.IsNullOrEmpty(activeLabel)) + return false; + + int searchStart = label.IndexOf('('); + searchStart = searchStart < 0 ? 0 : searchStart + 1; + + int matchIndex = label.IndexOf(activeLabel, searchStart, StringComparison.Ordinal); + + if (matchIndex < 0) + return false; + + activeStart = matchIndex; + activeEnd = matchIndex + activeLabel.Length; + return true; } } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index a147bf47fb..e43234a6d3 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -1,3 +1,4 @@ +using NLog; using System; using TombLib.Scripting.Bases; using TombLib.Scripting.Highlighting; @@ -12,6 +13,8 @@ namespace TombLib.Scripting.Lua; /// public sealed partial class LuaEditor : TextEditorBase { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + /// /// Gets the default file extension associated with Lua documents. /// diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index 463fef1b7e..10c042ed14 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -63,11 +63,12 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in lock (_resolveSync) { - if (!CanResolve) - return Description; - - if (_resolveTask is null || _resolveTask.IsCanceled || _resolveTask.IsFaulted) + if (_resolveTask is null || _resolveTask.IsFaulted || _resolveTask.IsCanceled) + { + // Use the caller's token so a stale, abandoned resolve also cancels the underlying LSP request + // instead of staying in flight against the language server. _resolveTask = _item.ResolveAsync(cancellationToken); + } resolveTask = _resolveTask; } @@ -81,6 +82,17 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in ApplyResolvedItem(resolvedItem); return Description; } + catch (OperationCanceledException) + { + // Allow a future request to retry the resolve when the caller cancels mid-flight. + lock (_resolveSync) + { + if (ReferenceEquals(_resolveTask, resolveTask)) + _resolveTask = null; + } + + throw; + } catch { lock (_resolveSync) @@ -102,7 +114,7 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in return lines.Length == 0 ? null : string.Join(" ", lines).Trim(); } - private object? BuildDescriptionContent() + private Border? BuildDescriptionContent() { bool hasDetail = !string.IsNullOrWhiteSpace(_item.Detail); bool hasDescription = !string.IsNullOrWhiteSpace(_item.Description); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs index 286f95a38a..a3729ec28e 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Concurrent; using System.Windows.Media; using TombLib.Scripting.Lua.Resources; @@ -7,24 +7,12 @@ namespace TombLib.Scripting.Lua.Objects; // Geometry paths below are vendored from microsoft/vscode-codicons under the MIT license. internal static class LuaCompletionIconFactory { - private static readonly Dictionary Cache = []; + private static readonly ConcurrentDictionary Cache = new(); public static ImageSource GetIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) - { - string cacheKey = brushSet.ThemeName + ":" + kind; - - lock (Cache) - { - if (Cache.TryGetValue(cacheKey, out ImageSource? image)) - return image; - - image = CreateIcon(kind, brushSet); - Cache[cacheKey] = image; - return image; - } - } + => Cache.GetOrAdd(brushSet.ThemeName + ":" + kind, _ => CreateIcon(kind, brushSet)); - private static ImageSource CreateIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) + private static DrawingImage CreateIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) { var drawingGroup = new DrawingGroup(); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index 8188897289..569be5a797 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -34,7 +34,7 @@ public LuaCompletionItem( bool isDescriptionMarkdown = false, Func>? resolveAsync = null) { - Label = label ?? throw new ArgumentNullException(nameof(label)); + Label = label; InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; Detail = string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); Description = string.IsNullOrWhiteSpace(description) ? null : description.Trim(); @@ -101,4 +101,12 @@ public Task ResolveAsync(CancellationToken cancellationToken ? Task.FromResult(this) : _resolveAsync(cancellationToken); } + + /// + /// Returns a copy of this item with the supplied resolve callback attached. + /// + /// The lazy resolve callback. + /// A new completion item with the resolve callback attached. + public LuaCompletionItem WithResolveCallback(Func> resolveAsync) + => new(Label, InsertText, Detail, Description, FilterText, Priority, IconKind, IsDescriptionMarkdown, resolveAsync); } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs index 31f8ce0277..acbccef167 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaDefinitionLocation.cs @@ -15,7 +15,7 @@ public sealed class LuaDefinitionLocation /// The one-based column number. public LuaDefinitionLocation(string filePath, int lineNumber, int columnNumber) { - FilePath = filePath ?? throw new ArgumentNullException(nameof(filePath)); + FilePath = filePath; LineNumber = Math.Max(1, lineNumber); ColumnNumber = Math.Max(1, columnNumber); } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs index 8f5f8057b3..1a745545f4 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaHoverInfo.cs @@ -1,5 +1,3 @@ -using System; - namespace TombLib.Scripting.Lua.Objects; /// @@ -14,7 +12,7 @@ public sealed class LuaHoverInfo /// Whether the content should be rendered as Markdown. public LuaHoverInfo(string content, bool isMarkdown) { - Content = content ?? throw new ArgumentNullException(nameof(content)); + Content = content; IsMarkdown = isMarkdown; } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs index a2605fed7f..55da5caeef 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaSignatureInfo.cs @@ -18,7 +18,7 @@ public sealed class LuaSignatureInfo public LuaSignatureInfo(string label, string? documentation, IReadOnlyList parameters, int activeParameter) { - Label = label ?? throw new ArgumentNullException(nameof(label)); + Label = label; Documentation = documentation; Parameters = parameters ?? []; ActiveParameter = Math.Max(0, activeParameter); @@ -57,7 +57,7 @@ public sealed class LuaParameterInfo /// Optional documentation for the parameter. public LuaParameterInfo(string label, string? documentation) { - Label = label ?? string.Empty; + Label = label; Documentation = documentation; } diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs index 014a6f75c9..a4b23d7667 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs @@ -6,60 +6,40 @@ namespace TombLib.Scripting.Lua.Resources; /// /// Bundles the frozen WPF brushes derived from a resolved Lua theme. /// -internal sealed class LuaThemeBrushSet +internal sealed class LuaThemeBrushSet( + string themeName, + SolidColorBrush editorBackground, + SolidColorBrush editorForeground, + SolidColorBrush mutedText, + SolidColorBrush misc, + SolidColorBrush method, + SolidColorBrush variable, + SolidColorBrush property, + SolidColorBrush type, + SolidColorBrush keyword, + SolidColorBrush languageConstant, + SolidColorBrush constant, + SolidColorBrush file, + SolidColorBrush signatureParamDoc, + SolidColorBrush signatureActiveParam, + SolidColorBrush signatureForeground) { - public LuaThemeBrushSet( - string themeName, - SolidColorBrush editorBackground, - SolidColorBrush editorForeground, - SolidColorBrush mutedText, - SolidColorBrush misc, - SolidColorBrush method, - SolidColorBrush variable, - SolidColorBrush property, - SolidColorBrush type, - SolidColorBrush keyword, - SolidColorBrush languageConstant, - SolidColorBrush constant, - SolidColorBrush file, - SolidColorBrush signatureParamDoc, - SolidColorBrush signatureActiveParam, - SolidColorBrush signatureForeground) - { - ThemeName = themeName; - EditorBackground = editorBackground; - EditorForeground = editorForeground; - MutedTextBrush = mutedText; - MiscBrush = misc; - MethodBrush = method; - VariableBrush = variable; - PropertyBrush = property; - TypeBrush = type; - KeywordBrush = keyword; - LanguageConstantBrush = languageConstant; - ConstantBrush = constant; - FileBrush = file; - SignatureParamDocForeground = signatureParamDoc; - SignatureActiveParamForeground = signatureActiveParam; - SignatureForeground = signatureForeground; - } - - public string ThemeName { get; } - public SolidColorBrush EditorBackground { get; } - public SolidColorBrush EditorForeground { get; } - public SolidColorBrush MutedTextBrush { get; } - public SolidColorBrush MiscBrush { get; } - public SolidColorBrush MethodBrush { get; } - public SolidColorBrush VariableBrush { get; } - public SolidColorBrush PropertyBrush { get; } - public SolidColorBrush TypeBrush { get; } - public SolidColorBrush KeywordBrush { get; } - public SolidColorBrush LanguageConstantBrush { get; } - public SolidColorBrush ConstantBrush { get; } - public SolidColorBrush FileBrush { get; } - public SolidColorBrush SignatureParamDocForeground { get; } - public SolidColorBrush SignatureActiveParamForeground { get; } - public SolidColorBrush SignatureForeground { get; } + public string ThemeName { get; } = themeName; + public SolidColorBrush EditorBackground { get; } = editorBackground; + public SolidColorBrush EditorForeground { get; } = editorForeground; + public SolidColorBrush MutedTextBrush { get; } = mutedText; + public SolidColorBrush MiscBrush { get; } = misc; + public SolidColorBrush MethodBrush { get; } = method; + public SolidColorBrush VariableBrush { get; } = variable; + public SolidColorBrush PropertyBrush { get; } = property; + public SolidColorBrush TypeBrush { get; } = type; + public SolidColorBrush KeywordBrush { get; } = keyword; + public SolidColorBrush LanguageConstantBrush { get; } = languageConstant; + public SolidColorBrush ConstantBrush { get; } = constant; + public SolidColorBrush FileBrush { get; } = file; + public SolidColorBrush SignatureParamDocForeground { get; } = signatureParamDoc; + public SolidColorBrush SignatureActiveParamForeground { get; } = signatureActiveParam; + public SolidColorBrush SignatureForeground { get; } = signatureForeground; /// /// Gets the brush used to render the specified completion item kind. diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs index 192b5938b3..280bcff746 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeRepository.cs @@ -1,3 +1,4 @@ +using NLog; using System; using System.Collections.Generic; using System.IO; @@ -12,6 +13,8 @@ namespace TombLib.Scripting.Lua.Resources; /// public static class LuaThemeRepository { + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private static readonly Lazy Catalog = new(LoadCatalog); /// @@ -75,9 +78,9 @@ private static LuaThemeCatalog LoadCatalog() if (theme is not null) themes.Add(theme.Normalize(Path.GetFileNameWithoutExtension(filePath))); } - catch (Exception ex) + catch (Exception exception) { - System.Diagnostics.Debug.WriteLine($"Failed to load Lua theme '{filePath}': {ex.Message}"); + Log.Warn(exception, "Failed to load Lua theme '{FilePath}'.", filePath); } } } @@ -109,7 +112,7 @@ private static LuaThemeCatalog LoadCatalog() return new LuaThemeCatalog(orderedThemes, themesByLookupName, defaultTheme); } - private static void AddLookupName(IDictionary themesByLookupName, string lookupName, LuaTheme theme) + private static void AddLookupName(Dictionary themesByLookupName, string lookupName, LuaTheme theme) { if (string.IsNullOrWhiteSpace(lookupName) || themesByLookupName.ContainsKey(lookupName)) return; @@ -117,17 +120,10 @@ private static void AddLookupName(IDictionary themesByLookupNa themesByLookupName[lookupName] = theme; } - private sealed class LuaThemeCatalog + private sealed class LuaThemeCatalog(IReadOnlyList themes, IReadOnlyDictionary themesByLookupName, LuaTheme defaultTheme) { - public LuaThemeCatalog(IReadOnlyList themes, IReadOnlyDictionary themesByLookupName, LuaTheme defaultTheme) - { - Themes = themes; - ThemesByLookupName = themesByLookupName; - DefaultTheme = defaultTheme; - } - - public IReadOnlyList Themes { get; } - public IReadOnlyDictionary ThemesByLookupName { get; } - public LuaTheme DefaultTheme { get; } + public IReadOnlyList Themes { get; } = themes; + public IReadOnlyDictionary ThemesByLookupName { get; } = themesByLookupName; + public LuaTheme DefaultTheme { get; } = defaultTheme; } } diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index 95aea4184a..d3fc4dbd90 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -1,25 +1,27 @@  + false enable true true + + GlobalPaths.cs - - UserControl - + + PreserveNewest @@ -28,4 +30,5 @@ PreserveNewest - \ No newline at end of file + + diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs index feee858900..da22510783 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs @@ -1,6 +1,6 @@ +using ICSharpCode.AvalonEdit.Document; using System; using System.Collections.Generic; -using ICSharpCode.AvalonEdit.Document; namespace TombLib.Scripting.Lua.Utils; @@ -8,7 +8,7 @@ internal sealed class LuaDocumentLineParserStateCache { private readonly object _syncRoot = new(); private readonly TextDocument _document; - private readonly List _cachedLineStartStates = new(); + private readonly List _cachedLineStartStates = []; public LuaDocumentLineParserStateCache(TextDocument document) { diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs index 30862abe9f..358133b857 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEditorInteractionRules.cs @@ -1,6 +1,6 @@ +using ICSharpCode.AvalonEdit.Document; using System; using System.Runtime.CompilerServices; -using ICSharpCode.AvalonEdit.Document; namespace TombLib.Scripting.Lua.Utils; @@ -34,7 +34,7 @@ public static bool TryGetHoverOffset(TextDocument? document, int offset, out int if (document is null || document.TextLength == 0) return false; - int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + int safeOffset = ClampOffset(document, offset); if (safeOffset >= document.TextLength) return false; @@ -109,7 +109,7 @@ public static bool TryGetDefinitionStartOffset(TextDocument? document, int offse if (document is null || document.TextLength == 0) return false; - int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + int safeOffset = ClampOffset(document, offset); if (IsInsideCommentOrString(document, safeOffset)) return false; @@ -131,7 +131,7 @@ public static bool IsInsideCommentOrString(TextDocument? document, int offset) if (document is null || document.TextLength == 0) return false; - int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + int safeOffset = ClampOffset(document, offset); DocumentLine currentLine = document.GetLineByOffset(safeOffset); LuaLineParserState lineStartState = GetLineStartParserState(document, currentLine); int lineStart = currentLine.Offset; @@ -144,6 +144,9 @@ public static bool IsInsideCommentOrString(TextDocument? document, int offset) private static LuaLineParserState GetLineStartParserState(TextDocument document, DocumentLine currentLine) => LineStartStateCaches.GetValue(document, static doc => new LuaDocumentLineParserStateCache(doc)).GetLineStartState(currentLine.LineNumber); + private static int ClampOffset(TextDocument document, int offset) + => Math.Clamp(offset, 0, document.TextLength); + private static bool TryGetDefinitionWordBounds(TextDocument document, int offset, out int wordStart, out int wordEnd) { wordStart = 0; @@ -152,7 +155,7 @@ private static bool TryGetDefinitionWordBounds(TextDocument document, int offset if (document.TextLength == 0) return false; - int probeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + int probeOffset = ClampOffset(document, offset); if (probeOffset >= document.TextLength) probeOffset = document.TextLength - 1; diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs index 0d242026a5..6a53cc1268 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Text; @@ -16,16 +17,10 @@ internal enum LuaLineParserStateKind /// /// Stores the parser continuation state needed to evaluate long strings and long comments across line boundaries. /// -internal readonly struct LuaLineParserState +internal readonly struct LuaLineParserState(LuaLineParserStateKind kind, int longBracketEqualsCount) { - public LuaLineParserState(LuaLineParserStateKind kind, int longBracketEqualsCount) - { - Kind = kind; - LongBracketEqualsCount = longBracketEqualsCount; - } - - public LuaLineParserStateKind Kind { get; } - public int LongBracketEqualsCount { get; } + public LuaLineParserStateKind Kind { get; } = kind; + public int LongBracketEqualsCount { get; } = longBracketEqualsCount; } /// @@ -250,12 +245,27 @@ public static string StripLineComment(string lineText) /// The line text to inspect. /// The structural characters that participate in brace and delimiter analysis. public static IEnumerable EnumerateStructuralCharacters(string lineText) + => EnumerateStructuralCharactersCore(lineText, default, captureFinalState: null); + + /// + /// Enumerates structural characters from a line while carrying long-string and long-comment + /// continuation state across line boundaries. Use the returned + /// as the next line's so multi-line [[...]] blocks can + /// not break callers that do brace tracking across the whole document. + /// + internal static IEnumerable EnumerateStructuralCharacters(string lineText, LuaLineParserState initialState, Action captureFinalState) + => EnumerateStructuralCharactersCore(lineText, initialState, captureFinalState); + + private static IEnumerable EnumerateStructuralCharactersCore(string lineText, LuaLineParserState initialState, Action? captureFinalState) { + ParserState state = GetInitialParserState(initialState); + int longBracketEqualsCount = initialState.LongBracketEqualsCount; + if (string.IsNullOrEmpty(lineText)) + { + captureFinalState?.Invoke(CreateContinuationState(state, longBracketEqualsCount)); yield break; - - ParserState state = ParserState.None; - int longBracketEqualsCount = 0; + } for (int i = 0; i < lineText.Length; i++) { @@ -267,6 +277,7 @@ public static IEnumerable EnumerateStructuralCharacters(string lineText) { i += endTokenLength - 1; state = ParserState.None; + longBracketEqualsCount = 0; } continue; @@ -295,7 +306,10 @@ public static IEnumerable EnumerateStructuralCharacters(string lineText) } if (IsLineCommentStart(lineText, i)) + { + captureFinalState?.Invoke(CreateContinuationState(ParserState.None, 0)); yield break; + } if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) { @@ -318,6 +332,13 @@ public static IEnumerable EnumerateStructuralCharacters(string lineText) yield return currentChar; } + + // Single/double-quoted strings do not legally span lines in Lua, so they implicitly + // terminate at the newline; only long-bracket modes are propagated to the next line. + if (state != ParserState.LongString && state != ParserState.LongComment) + state = ParserState.None; + + captureFinalState?.Invoke(CreateContinuationState(state, longBracketEqualsCount)); } private static bool TryMatchLongCommentStart(string lineText, int index, out int equalsCount, out int tokenLength) diff --git a/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs index 7175f63ba6..a0f0e332f9 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/TombEngineLanguageScriptService.cs @@ -7,11 +7,12 @@ namespace TombLib.Scripting.Lua.Utils; /// /// Inserts generated Tomb Engine language strings into an existing Lua strings table. /// -public sealed class TombEngineLanguageScriptService +public sealed partial class TombEngineLanguageScriptService { - private static readonly Regex SetStringsRegex = new( - @"TEN\.Flow\.SetStrings\s*\(\s*(?[^)\s]+)\s*\)", - RegexOptions.Compiled | RegexOptions.IgnoreCase); + [GeneratedRegex(@"TEN\.Flow\.SetStrings\s*\(\s*(?[^)\s]+)\s*\)", RegexOptions.IgnoreCase | RegexOptions.Compiled)] + private static partial Regex GetSetStringsRegex(); + + private static readonly Regex SetStringsRegex = GetSetStringsRegex(); /// /// Attempts to insert a generated language entry into the strings table referenced by TEN.Flow.SetStrings(...). @@ -78,12 +79,18 @@ private static Regex CreateStringsStartRegex(string stringsVariableName) { int bracketDepth = 0; bool foundOpeningBracket = false; + LuaLineParserState parserState = default; for (DocumentLine? line = stringsStartLine; line is not null; line = line.NextLine) { - string lineText = LuaLineParser.StripLineComment(document.GetText(line)); - - foreach (char character in LuaLineParser.EnumerateStructuralCharacters(lineText)) + // Use the raw line text (not StripLineComment) so the structural enumerator can keep + // long-string and long-comment continuation state in sync across lines. A multi-line + // `[[...]]` entry inside the strings table would otherwise leak `{` / `}` characters + // from the string body into our brace counter. + string lineText = document.GetText(line); + LuaLineParserState capturedState = parserState; + + foreach (char character in LuaLineParser.EnumerateStructuralCharacters(lineText, parserState, state => capturedState = state)) { if (character == '{') { @@ -101,6 +108,8 @@ private static Regex CreateStringsStartRegex(string stringsVariableName) return line; } } + + parserState = capturedState; } return null; @@ -108,16 +117,39 @@ private static Regex CreateStringsStartRegex(string stringsVariableName) private static DocumentLine? FindLanguageInsertionLine(TextDocument document, DocumentLine stringsStartLine, DocumentLine stopLine) { - for (int i = stopLine.LineNumber - 1; i > stringsStartLine.LineNumber; i--) + // Walk forward from the strings-table opener so we can keep parser continuation state in + // lockstep, then pick the latest line that ends with `}` or `},` while not sitting inside + // a long string or comment carried over from earlier lines. + LuaLineParserState parserState = default; + DocumentLine? bestCandidate = null; + + for (DocumentLine? line = stringsStartLine; line is not null && line.LineNumber <= stopLine.LineNumber; line = line.NextLine) { - DocumentLine line = document.GetLineByNumber(i); - string cleanLine = LuaLineParser.StripLineComment(document.GetText(line)).TrimEnd(); + LuaLineParserState capturedState = parserState; + bool insideLongBlockAtLineStart = parserState.Kind != LuaLineParserStateKind.None; - if (cleanLine.EndsWith("}") || cleanLine.EndsWith("},")) - return line; + // Drain the enumerator to advance parser state to the next line; ignore the chars. + foreach (char _ in LuaLineParser.EnumerateStructuralCharacters(document.GetText(line), parserState, state => capturedState = state)) + { } + + if (line.LineNumber <= stringsStartLine.LineNumber || line.LineNumber >= stopLine.LineNumber) + { + parserState = capturedState; + continue; + } + + if (!insideLongBlockAtLineStart) + { + string cleanLine = LuaLineParser.StripLineComment(document.GetText(line)).TrimEnd(); + + if (cleanLine.EndsWith('}') || cleanLine.EndsWith("},")) + bestCandidate = line; + } + + parserState = capturedState; } - return null; + return bestCandidate; } private static int InsertLanguageScript(TextDocument document, string languageScript, DocumentLine insertionLine) @@ -125,7 +157,7 @@ private static int InsertLanguageScript(TextDocument document, string languageSc string rawLine = document.GetText(insertionLine); string cleanLine = LuaLineParser.StripLineComment(rawLine).TrimEnd(); - if (cleanLine.EndsWith("}")) + if (cleanLine.EndsWith('}')) { int commaOffset = insertionLine.Offset + cleanLine.Length; document.Insert(commaOffset, ","); diff --git a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs index 25b92b5508..5d58562c11 100644 --- a/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs +++ b/TombLib/TombLib.Test/LuaEditorInteractionRulesTests.cs @@ -1,4 +1,3 @@ -using System; using ICSharpCode.AvalonEdit.Document; using TombLib.Scripting.Lua.Utils; @@ -111,7 +110,8 @@ public void IsValidManualCompletionContext_BlocksLongCommentContinuationOnFollow public void TryGetHoverOffset_ReturnsOffsetWhenPointerIsOnIdentifierText() { const string identifier = "targetValue"; - string text = "return " + identifier; + const string text = "return " + identifier; + var document = CreateDocument(text); int identifierStart = text.IndexOf(identifier, StringComparison.Ordinal); int probeOffset = identifierStart + 2; @@ -126,7 +126,8 @@ public void TryGetHoverOffset_ReturnsOffsetWhenPointerIsOnIdentifierText() public void TryGetHoverOffset_BlocksTrailingWhitespaceAfterIdentifier() { const string identifier = "targetValue"; - string text = "return " + identifier; + const string text = "return " + identifier; + var document = CreateDocument(text); int probeOffset = document.TextLength; @@ -177,7 +178,8 @@ public void TryGetHoverOffset_RefreshesLongCommentStateAfterDocumentEdit() public void TryGetDefinitionStartOffset_ReturnsWordStartFromInsideIdentifier() { const string identifier = "targetValue"; - string text = "local " + identifier + " = 1"; + const string text = "local " + identifier + " = 1"; + var document = CreateDocument(text); int identifierStart = text.IndexOf(identifier, StringComparison.Ordinal); int probeOffset = identifierStart + 4; @@ -192,7 +194,8 @@ public void TryGetDefinitionStartOffset_ReturnsWordStartFromInsideIdentifier() public void TryGetDefinitionStartOffset_ReturnsWordStartWhenCaretIsAfterIdentifier() { const string identifier = "targetValue"; - string text = "return " + identifier; + const string text = "return " + identifier; + var document = CreateDocument(text); int identifierStart = text.IndexOf(identifier, StringComparison.Ordinal); int probeOffset = identifierStart + identifier.Length; @@ -229,4 +232,4 @@ public void TryGetDefinitionStartOffset_BlocksLongStringContinuationOnFollowingL private static TextDocument CreateDocument(params string[] lines) => new(string.Join(Environment.NewLine, lines)); -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs b/TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs new file mode 100644 index 0000000000..1913760615 --- /dev/null +++ b/TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs @@ -0,0 +1,122 @@ +using System.Text.Json; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaIncrementalEditCalculatorTests +{ + [TestMethod] + public void Compute_CollapsesUnchangedPrefixAndSuffixIntoMinimalRangeEdit() + { + const string oldText = "local foo = 1\nlocal bar = 2\n"; + const string newText = "local foo = 1\nlocal baz = 2\n"; + + LuaDocumentChangeRange range = LuaIncrementalEditCalculator.Compute(oldText, newText, LuaDocumentLineOffsets.Build(oldText)); + + Assert.AreEqual(1, range.StartLine); + Assert.AreEqual(8, range.StartCharacter); + Assert.AreEqual(1, range.EndLine); + Assert.AreEqual(9, range.EndCharacter); + Assert.AreEqual("z", range.Text); + } + + [TestMethod] + public void Compute_HandlesPureInsertionAtEndOfFile() + { + const string oldText = "local foo = 1\n"; + const string newText = "local foo = 1\nlocal bar = 2\n"; + + LuaDocumentChangeRange range = LuaIncrementalEditCalculator.Compute(oldText, newText, LuaDocumentLineOffsets.Build(oldText)); + + Assert.AreEqual(1, range.StartLine); + Assert.AreEqual(0, range.StartCharacter); + Assert.AreEqual(1, range.EndLine); + Assert.AreEqual(0, range.EndCharacter); + Assert.AreEqual("local bar = 2\n", range.Text); + } + + [TestMethod] + public void Compute_NoChange_ProducesEmptyRange() + { + const string text = "print('hi')\n"; + + LuaDocumentChangeRange range = LuaIncrementalEditCalculator.Compute(text, text, LuaDocumentLineOffsets.Build(text)); + + Assert.AreEqual(string.Empty, range.Text); + Assert.AreEqual(range.StartLine, range.EndLine); + Assert.AreEqual(range.StartCharacter, range.EndCharacter); + } +} + +[TestClass] +public class LuaLanguageServerSemanticTokensDeltaParserTests +{ + [TestMethod] + public void ApplyEdits_ReplacesContiguousRangeAndPreservesSurroundingData() + { + int[] previous = [0, 0, 5, 1, 0, 0, 6, 3, 2, 0, 1, 0, 4, 1, 0]; + LuaSemanticTokensEdit edit = new(Start: 5, DeleteCount: 5, Data: [0, 6, 4, 2, 0]); + + int[]? result = LuaLanguageServerSemanticTokensDeltaParser.ApplyEdits(previous, [edit]); + + Assert.IsNotNull(result); + CollectionAssert.AreEqual(new[] { 0, 0, 5, 1, 0, 0, 6, 4, 2, 0, 1, 0, 4, 1, 0 }, result); + } + + [TestMethod] + public void ApplyEdits_ReturnsNullWhenEditOutOfRange() + { + int[] previous = [0, 0, 1, 0, 0]; + LuaSemanticTokensEdit edit = new(Start: 4, DeleteCount: 5, Data: []); + + int[]? result = LuaLanguageServerSemanticTokensDeltaParser.ApplyEdits(previous, [edit]); + + Assert.IsNull(result); + } + + [TestMethod] + public void ApplyEdits_AppliesMultipleEditsInAscendingOrder() + { + int[] previous = [10, 11, 12, 13, 14]; + LuaSemanticTokensEdit insertHead = new(Start: 0, DeleteCount: 0, Data: [99]); + LuaSemanticTokensEdit replaceTail = new(Start: 4, DeleteCount: 1, Data: [44, 45]); + + int[]? result = LuaLanguageServerSemanticTokensDeltaParser.ApplyEdits(previous, [replaceTail, insertHead]); + + Assert.IsNotNull(result); + CollectionAssert.AreEqual(new[] { 99, 10, 11, 12, 13, 44, 45 }, result); + } +} + +[TestClass] +public class LuaLanguageServerSemanticTokensParserTests +{ + [TestMethod] + public void Parse_DecodesDataArrayUsingSharedDecoder() + { + JsonElement response = JsonSerializer.SerializeToElement(new + { + data = new[] { 0, 6, 5, 0, 0 } + }); + + var document = new LuaDocumentSnapshot( + @"C:\Workspace\test.lua", + new Uri(@"C:\Workspace\test.lua").AbsoluteUri, + "local value = 1", + 1); + + IReadOnlyList tokens = LuaLanguageServerSemanticTokensParser.Parse( + response, + document, + ["variable"], + []); + + Assert.AreEqual(1, tokens.Count); + Assert.AreEqual(0, tokens[0].Line); + Assert.AreEqual(6, tokens[0].Character); + Assert.AreEqual(5, tokens[0].Length); + Assert.AreEqual("variable", tokens[0].Type); + } +} diff --git a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs new file mode 100644 index 0000000000..fdcbbaade7 --- /dev/null +++ b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs @@ -0,0 +1,378 @@ +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Text; +using System.Text.Json; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; + +namespace TombLib.Test; + +[TestClass] +public class LuaLanguageServerClientTests +{ + [TestMethod] + public void Dispose_WritesGracefulShutdownMessages() + { + using Process process = StartDisposableProcess(); + using var outputStream = new RecordingStream(); + using var client = new LuaLanguageServerClient(@"C:\Workspace", process.StartInfo.FileName, static () => new { }); + + SetPrivateField(client, "_process", process); + SetPrivateField(client, "_inputStream", Stream.Null); + SetPrivateField(client, "_outputStream", outputStream); + + client.Dispose(); + + string writtenPayload = outputStream.GetWrittenText(); + + Assert.IsTrue(writtenPayload.Contains("\"method\":\"shutdown\"", StringComparison.Ordinal), writtenPayload); + Assert.IsTrue(writtenPayload.Contains("\"method\":\"exit\"", StringComparison.Ordinal), writtenPayload); + } + + [TestMethod] + public async Task HandleServerRequestAsync_SemanticTokensRefresh_AcknowledgesAndRaisesEvent() + { + await using var outputStream = new RecordingStream(); + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + bool refreshRequested = false; + + SetPrivateField(client, "_outputStream", outputStream); + client.SemanticTokensRefreshRequested += () => refreshRequested = true; + + await InvokePrivateTaskAsync(client, "HandleServerRequestAsync", + JsonSerializer.SerializeToElement(7L), + "workspace/semanticTokens/refresh", + default(JsonElement)).ConfigureAwait(false); + + string writtenPayload = outputStream.GetWrittenText(); + + Assert.IsTrue(refreshRequested); + Assert.IsTrue(writtenPayload.Contains("\"id\":7", StringComparison.Ordinal), writtenPayload); + Assert.IsTrue(writtenPayload.Contains("\"result\":null", StringComparison.Ordinal), writtenPayload); + } + + [TestMethod] + public async Task PumpDiagnosticsAsync_CoalescesQueuedDiagnosticsByFile() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + int publishedCount = 0; + string? lastMessage = null; + + client.DiagnosticsPublished += parameters => + { + publishedCount++; + lastMessage = parameters.GetProperty("diagnostics")[0].GetProperty("message").GetString(); + CancelLifetime(client); + }; + + InvokePrivateMethod(client, "RaiseDiagnosticsPublished", CreateDiagnosticsParameters("file:///C:/Workspace/test.lua", "Stale warning.")); + InvokePrivateMethod(client, "RaiseDiagnosticsPublished", CreateDiagnosticsParameters("file:///C:/Workspace/test.lua", "Current warning.")); + + await InvokePrivateTaskAsync(client, "PumpDiagnosticsAsync").ConfigureAwait(false); + + Assert.AreEqual(1, publishedCount); + Assert.AreEqual("Current warning.", lastMessage); + } + + [TestMethod] + public async Task ReadHeadersAndPayloadAsync_ReadsChunkedFrameAcrossBoundaries() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + string payloadJson = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"value\":42}}"; + byte[] frame = CreateLspFrame(payloadJson); + + SetPrivateField(client, "_inputStream", new ChunkedReadStream(SplitBytes(frame, 5, 7, 11, 3))); + + int? contentLength = await InvokePrivateTaskAsync(client, "ReadHeadersAsync").ConfigureAwait(false); + byte[]? payload = await InvokePrivateTaskAsync(client, "ReadPayloadAsync", contentLength!.Value).ConfigureAwait(false); + + Assert.AreEqual(Encoding.UTF8.GetByteCount(payloadJson), contentLength); + Assert.IsNotNull(payload); + Assert.AreEqual(payloadJson, Encoding.UTF8.GetString(payload)); + } + + [TestMethod] + public async Task ReadLoopAsync_HandlesChunkedSemanticTokensRefreshRequest() + { + await using var outputStream = new RecordingStream(); + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + bool refreshRequested = false; + byte[] frame = CreateLspFrame("{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"workspace/semanticTokens/refresh\"}"); + + SetPrivateField(client, "_inputStream", new ChunkedReadStream(SplitBytes(frame, 4, 9, 6, 13))); + SetPrivateField(client, "_outputStream", outputStream); + client.SemanticTokensRefreshRequested += () => refreshRequested = true; + + await InvokePrivateTaskAsync(client, "ReadLoopAsync").ConfigureAwait(false); + + string writtenPayload = outputStream.GetWrittenText(); + + Assert.IsTrue(refreshRequested); + Assert.IsTrue(writtenPayload.Contains("\"id\":9", StringComparison.Ordinal), writtenPayload); + Assert.IsTrue(writtenPayload.Contains("\"result\":null", StringComparison.Ordinal), writtenPayload); + } + + [TestMethod] + public async Task ReadLoopAsync_FailsPendingRequestsWhenConnectionCloses() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + var pendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + GetPendingRequests(client).TryAdd(42, pendingRequest); + SetPrivateField(client, "_inputStream", new ChunkedReadStream()); + + await InvokePrivateTaskAsync(client, "ReadLoopAsync").ConfigureAwait(false); + + await Assert.ThrowsExceptionAsync(() => pendingRequest.Task).ConfigureAwait(false); + } + + [TestMethod] + public async Task ReadLoopAsync_CompletesPendingRequestFromChunkedResponse() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + var pendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + byte[] frame = CreateLspFrame("{\"jsonrpc\":\"2.0\",\"id\":42,\"result\":{\"label\":\"ok\"}}"); + + GetPendingRequests(client).TryAdd(42, pendingRequest); + SetPrivateField(client, "_inputStream", new ChunkedReadStream(SplitBytes(frame, 6, 8, 5, 9))); + + await InvokePrivateTaskAsync(client, "ReadLoopAsync").ConfigureAwait(false); + + JsonElement result = await pendingRequest.Task.ConfigureAwait(false); + + Assert.AreEqual("ok", result.GetProperty("label").GetString()); + } + + private static Process StartDisposableProcess() + { + var startInfo = new ProcessStartInfo + { + FileName = Path.Combine(Environment.SystemDirectory, "cmd.exe"), + Arguments = "/c ping 127.0.0.1 -n 10 > nul", + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + return Process.Start(startInfo) + ?? throw new InvalidOperationException("Unable to start the disposable test process."); + } + + private static void SetPrivateField(LuaLanguageServerClient client, string fieldName, object? value) + { + FieldInfo field = typeof(LuaLanguageServerClient).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + field.SetValue(client, value); + } + + private static void InvokePrivateMethod(object instance, string methodName, params object?[] parameters) + { + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private method '{methodName}' was not found."); + + method.Invoke(instance, parameters); + } + + private static async Task InvokePrivateTaskAsync(object instance, string methodName, params object?[] parameters) + { + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private method '{methodName}' was not found."); + + Task task = (Task)(method.Invoke(instance, parameters) + ?? throw new InvalidOperationException($"Private method '{methodName}' returned null instead of a Task.")); + + await task.ConfigureAwait(false); + } + + private static async Task InvokePrivateTaskAsync(object instance, string methodName, params object?[] parameters) + { + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private method '{methodName}' was not found."); + + Task task = (Task)(method.Invoke(instance, parameters) + ?? throw new InvalidOperationException($"Private method '{methodName}' returned null instead of a Task.")); + + return await task.ConfigureAwait(false); + } + + private static JsonElement CreateDiagnosticsParameters(string uri, string message) + => JsonSerializer.SerializeToElement(new + { + uri, + diagnostics = new[] + { + new + { + message, + range = new + { + start = new { line = 0, character = 0 }, + end = new { line = 0, character = 1 } + } + } + } + }); + + private static void CancelLifetime(LuaLanguageServerClient client) + { + FieldInfo field = typeof(LuaLanguageServerClient).GetField("_lifetimeCts", BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException("Private field '_lifetimeCts' was not found."); + + ((CancellationTokenSource)field.GetValue(client)!).Cancel(); + } + + private static ConcurrentDictionary> GetPendingRequests(LuaLanguageServerClient client) + { + FieldInfo field = typeof(LuaLanguageServerClient).GetField("_pendingRequests", BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException("Private field '_pendingRequests' was not found."); + + return (ConcurrentDictionary>)field.GetValue(client)!; + } + + private static byte[] CreateLspFrame(string json) + { + byte[] payload = Encoding.UTF8.GetBytes(json); + byte[] header = Encoding.ASCII.GetBytes($"Content-Length: {payload.Length}\r\n\r\n"); + byte[] frame = new byte[header.Length + payload.Length]; + + Buffer.BlockCopy(header, 0, frame, 0, header.Length); + Buffer.BlockCopy(payload, 0, frame, header.Length, payload.Length); + return frame; + } + + private static byte[][] SplitBytes(byte[] source, params int[] chunkLengths) + { + var chunks = new List(); + int offset = 0; + + for (int i = 0; i < chunkLengths.Length && offset < source.Length; i++) + { + int length = Math.Min(chunkLengths[i], source.Length - offset); + + if (length <= 0) + continue; + + byte[] chunk = new byte[length]; + Buffer.BlockCopy(source, offset, chunk, 0, length); + chunks.Add(chunk); + offset += length; + } + + if (offset < source.Length) + { + byte[] remainder = new byte[source.Length - offset]; + Buffer.BlockCopy(source, offset, remainder, 0, remainder.Length); + chunks.Add(remainder); + } + + return [.. chunks]; + } + + private sealed class RecordingStream : Stream + { + private readonly MemoryStream _innerStream = new(); + + public override bool CanRead => false; + public override bool CanSeek => false; + public override bool CanWrite => true; + public override long Length => _innerStream.Length; + + public override long Position + { + get => _innerStream.Position; + set => _innerStream.Position = value; + } + + public string GetWrittenText() + => Encoding.UTF8.GetString(_innerStream.ToArray()); + + public override void Flush() + => _innerStream.Flush(); + + public override int Read(byte[] buffer, int offset, int count) + => throw new NotSupportedException(); + + public override long Seek(long offset, SeekOrigin origin) + => throw new NotSupportedException(); + + public override void SetLength(long value) + => _innerStream.SetLength(value); + + public override void Write(byte[] buffer, int offset, int count) + => _innerStream.Write(buffer, offset, count); + + public override void Write(ReadOnlySpan buffer) + => _innerStream.Write(buffer); + + public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + => _innerStream.WriteAsync(buffer, cancellationToken); + + protected override void Dispose(bool disposing) + { + if (disposing) + _innerStream.Flush(); + + base.Dispose(disposing); + } + } + + private sealed class ChunkedReadStream(params byte[][] chunks) : Stream + { + private readonly IReadOnlyList _chunks = chunks; + private int _chunkIndex; + private int _chunkOffset; + + public override bool CanRead => true; + public override bool CanSeek => false; + public override bool CanWrite => false; + public override long Length => throw new NotSupportedException(); + public override long Position + { + get => throw new NotSupportedException(); + set => throw new NotSupportedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + => ReadAsync(buffer.AsMemory(offset, count)).GetAwaiter().GetResult(); + + public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + if (_chunkIndex >= _chunks.Count) + return ValueTask.FromResult(0); + + byte[] chunk = _chunks[_chunkIndex]; + int bytesAvailable = chunk.Length - _chunkOffset; + int bytesToCopy = Math.Min(buffer.Length, bytesAvailable); + + chunk.AsMemory(_chunkOffset, bytesToCopy).CopyTo(buffer); + _chunkOffset += bytesToCopy; + + if (_chunkOffset >= chunk.Length) + { + _chunkIndex++; + _chunkOffset = 0; + } + + return ValueTask.FromResult(bytesToCopy); + } + + public override void Flush() + { } + + public override long Seek(long offset, SeekOrigin origin) + => throw new NotSupportedException(); + + public override void SetLength(long value) + => throw new NotSupportedException(); + + public override void Write(byte[] buffer, int offset, int count) + => throw new NotSupportedException(); + } +} diff --git a/TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs new file mode 100644 index 0000000000..311bc430b1 --- /dev/null +++ b/TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs @@ -0,0 +1,67 @@ +using System.Text.Json; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; + +namespace TombLib.Test; + +[TestClass] +public class LuaLanguageServerDiagnosticsParserTests +{ + [TestMethod] + public void TryParse_PreservesZeroWidthDiagnosticOnEmptyLineByAnchoringToNextVisibleCharacter() + { + const string filePath = @"C:\Workspace\test.lua"; + const string content = "local value = 1\n\nnextLine = 2"; + + bool parsed = LuaLanguageServerDiagnosticsParser.TryParse( + CreateDiagnostics(line: 1, startCharacter: 0, endLine: 1, endCharacter: 0), + filePath, + content, + documentVersion: 1, + out LuaPublishedDiagnostics? publishedDiagnostics); + + Assert.IsTrue(parsed); + Assert.IsNotNull(publishedDiagnostics); + Assert.AreEqual(1, publishedDiagnostics.Diagnostics.Count); + Assert.AreEqual(content.IndexOf("nextLine", StringComparison.Ordinal), publishedDiagnostics.Diagnostics[0].StartOffset); + Assert.AreEqual(publishedDiagnostics.Diagnostics[0].StartOffset + 1, publishedDiagnostics.Diagnostics[0].EndOffset); + } + + [TestMethod] + public void TryParse_PreservesZeroWidthDiagnosticOnTrailingEmptyLineByAnchoringToPreviousVisibleCharacter() + { + const string filePath = @"C:\Workspace\test.lua"; + const string content = "return value\n"; + + bool parsed = LuaLanguageServerDiagnosticsParser.TryParse( + CreateDiagnostics(line: 1, startCharacter: 0, endLine: 1, endCharacter: 0), + filePath, + content, + documentVersion: 1, + out LuaPublishedDiagnostics? publishedDiagnostics); + + Assert.IsTrue(parsed); + Assert.IsNotNull(publishedDiagnostics); + Assert.AreEqual(1, publishedDiagnostics.Diagnostics.Count); + Assert.AreEqual('e', content[publishedDiagnostics.Diagnostics[0].StartOffset]); + Assert.AreEqual(publishedDiagnostics.Diagnostics[0].StartOffset + 1, publishedDiagnostics.Diagnostics[0].EndOffset); + } + + private static JsonElement CreateDiagnostics(int line, int startCharacter, int endLine, int endCharacter) + => JsonSerializer.SerializeToElement(new + { + version = 1, + diagnostics = new[] + { + new + { + severity = 1, + message = "Syntax error.", + range = new + { + start = new { line, character = startCharacter }, + end = new { line = endLine, character = endCharacter } + } + } + } + }); +} diff --git a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs new file mode 100644 index 0000000000..e88f2af76e --- /dev/null +++ b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs @@ -0,0 +1,314 @@ +using System.Reflection; +using System.Text.Json; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaLanguageServerIntellisenseProviderTests +{ + [TestMethod] + public async Task GetHoverAsync_ReplaysTrackedDocumentsAfterLanguageServerRestart() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + await provider.GetHoverAsync(filePath, content, 0, 0); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/hover" }, + client.GetSentMethodNames()); + + Assert.AreEqual(1, client.StartCallCount); + + client.IsReady = false; + + await provider.GetHoverAsync(filePath, content, 0, 0); + + CollectionAssert.AreEqual( + new[] + { + "textDocument/didOpen", + "textDocument/hover", + "textDocument/didOpen", + "textDocument/hover" + }, + client.GetSentMethodNames()); + + Assert.AreEqual(2, client.StartCallCount); + } + + [TestMethod] + public async Task DiagnosticsPublished_IgnoresVersionMismatchAndStoresMatchingVersion() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string firstContent = "local value = 1"; + const string secondContent = "local second = 2"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + int diagnosticsUpdatedCount = 0; + provider.DiagnosticsUpdated += (_, _) => diagnosticsUpdatedCount++; + + await provider.GetHoverAsync(filePath, firstContent, 0, 0); + await provider.GetHoverAsync(filePath, secondContent, 0, 0); + + client.PublishDiagnostics(CreateDiagnostics(filePath, 1, 6, 12, "Stale warning.")); + Assert.AreEqual(0, diagnosticsUpdatedCount); + Assert.AreEqual(0, provider.GetDiagnostics(filePath).Count); + + client.PublishDiagnostics(CreateDiagnostics(filePath, 3, 6, 12, "Future warning.")); + Assert.AreEqual(0, diagnosticsUpdatedCount); + Assert.AreEqual(0, provider.GetDiagnostics(filePath).Count); + + client.PublishDiagnostics(CreateDiagnostics(filePath, 2, 6, 12, "Current warning.")); + + IReadOnlyList diagnostics = provider.GetDiagnostics(filePath); + + Assert.AreEqual(1, diagnosticsUpdatedCount); + Assert.AreEqual(1, diagnostics.Count); + Assert.AreEqual(6, diagnostics[0].StartOffset); + Assert.AreEqual(12, diagnostics[0].EndOffset); + } + + [TestMethod] + public async Task UpdateDocument_WaitsForEarlierOpenNotificationToFinish() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + client.BlockNextOpenNotification(); + + provider.OpenDocument(filePath, "local value = 1"); + provider.UpdateDocument(filePath, "local value = 2"); + + Assert.IsFalse(await client.WaitForNotificationAsync("textDocument/didChange", TimeSpan.FromMilliseconds(250))); + + client.ReleaseOpenNotification(); + + Assert.IsTrue(await client.WaitForNotificationAsync("textDocument/didChange", TimeSpan.FromSeconds(1))); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/didChange" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task CloseDocument_WaitsForQueuedOpenNotificationToFinish() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + client.BlockNextOpenNotification(); + + provider.OpenDocument(filePath, "local value = 1"); + provider.CloseDocument(filePath); + + Assert.IsFalse(await client.WaitForNotificationAsync("textDocument/didClose", TimeSpan.FromMilliseconds(250))); + + client.ReleaseOpenNotification(); + + Assert.IsTrue(await client.WaitForNotificationAsync("textDocument/didClose", TimeSpan.FromSeconds(1))); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/didClose" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task GetHoverAsync_RetriesWorkspaceWatcherStartAfterWorkspaceDirectoryAppears() + { + string workspaceRoot = Path.Combine(Path.GetTempPath(), "LuaWatcherRetry_" + Guid.NewGuid().ToString("N")); + string filePath = Path.Combine(workspaceRoot, "Scripts", "test.lua"); + const string content = "local value = 1"; + + try + { + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + await provider.GetHoverAsync(filePath, content, 0, 0); + + Assert.IsNull(GetWorkspaceWatcher(provider)); + + Directory.CreateDirectory(workspaceRoot); + + await provider.GetHoverAsync(filePath, content, 0, 0); + + Assert.IsNotNull(GetWorkspaceWatcher(provider)); + } + finally + { + if (Directory.Exists(workspaceRoot)) + Directory.Delete(workspaceRoot, recursive: true); + } + } + + [TestMethod] + public async Task SemanticTokensRefreshRequested_RefreshesTrackedDocuments() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + SemanticTokenTypes = ["variable"] + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + var semanticTokensUpdated = new TaskCompletionSource>(TaskCreationOptions.RunContinuationsAsynchronously); + + provider.SemanticTokensUpdated += (updatedFilePath, tokens) => + { + if (string.Equals(updatedFilePath, filePath, StringComparison.OrdinalIgnoreCase)) + semanticTokensUpdated.TrySetResult(tokens); + }; + + await provider.GetHoverAsync(filePath, content, 0, 0); + + client.PublishSemanticTokensRefreshRequested(); + + Task completedTask = await Task.WhenAny(semanticTokensUpdated.Task, Task.Delay(TimeSpan.FromSeconds(1))).ConfigureAwait(false); + Assert.AreSame(semanticTokensUpdated.Task, completedTask); + + IReadOnlyList semanticTokens = await semanticTokensUpdated.Task.ConfigureAwait(false); + + Assert.AreEqual(1, semanticTokens.Count); + Assert.AreEqual("variable", semanticTokens[0].Type); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/hover", "textDocument/semanticTokens/full" }, + client.GetSentMethodNames()); + } + + private static JsonElement CreateDiagnostics(string filePath, int version, int startCharacter, int endCharacter, string message) + => JsonSerializer.SerializeToElement(new + { + uri = new Uri(filePath).AbsoluteUri, + version, + diagnostics = new[] + { + new + { + severity = 2, + message, + range = new + { + start = new { line = 0, character = startCharacter }, + end = new { line = 0, character = endCharacter } + } + } + } + }); + + private static LuaWorkspaceFileWatcher? GetWorkspaceWatcher(LuaLanguageServerIntellisenseProvider provider) + { + FieldInfo field = typeof(LuaLanguageServerIntellisenseProvider).GetField("_workspaceFileWatcher", BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException("Private field '_workspaceFileWatcher' was not found."); + + return field.GetValue(provider) as LuaWorkspaceFileWatcher; + } + + private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient + { + private readonly List _sentMethodNames = []; + private TaskCompletionSource? _openNotificationGate; + private readonly TaskCompletionSource _changeNotificationObserved = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _closeNotificationObserved = new(TaskCreationOptions.RunContinuationsAsynchronously); + + public bool IsReady { get; set; } = true; + public IReadOnlyList SemanticTokenTypes { get; set; } = []; + public IReadOnlyList SemanticTokenModifiers { get; set; } = []; + public bool SupportsCompletionResolve => false; + public bool SupportsSemanticTokensDelta => false; + public int StartCallCount { get; private set; } + + public event Action? DiagnosticsPublished; + + public event Action? SemanticTokensRefreshRequested; + + public Task StartAsync(CancellationToken cancellationToken) + { + StartCallCount++; + IsReady = true; + return Task.FromResult(true); + } + + public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) + { + _sentMethodNames.Add(method); + + if (method == "textDocument/didChange") + _changeNotificationObserved.TrySetResult(true); + + if (method == "textDocument/didClose") + _closeNotificationObserved.TrySetResult(true); + + if (method == "textDocument/didOpen" && _openNotificationGate is not null) + return _openNotificationGate.Task; + + return Task.CompletedTask; + } + + public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) + { + _sentMethodNames.Add(method); + + if (method == "textDocument/semanticTokens/full") + { + return Task.FromResult(JsonSerializer.SerializeToElement(new + { + data = new[] { 0, 6, 5, 0, 0 }, + resultId = "tokens-1" + })); + } + + return Task.FromResult(JsonSerializer.SerializeToElement(new { })); + } + + public string[] GetSentMethodNames() => [.. _sentMethodNames]; + + public void BlockNextOpenNotification() + => _openNotificationGate = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + public void ReleaseOpenNotification() + => _openNotificationGate?.TrySetResult(true); + + public async Task WaitForNotificationAsync(string method, TimeSpan timeout) + { + Task observedNotification = method switch + { + "textDocument/didChange" => _changeNotificationObserved.Task, + "textDocument/didClose" => _closeNotificationObserved.Task, + _ => Task.CompletedTask + }; + + Task completedTask = await Task.WhenAny(observedNotification, Task.Delay(timeout)).ConfigureAwait(false); + return ReferenceEquals(completedTask, observedNotification); + } + + public void PublishDiagnostics(JsonElement parameters) + => DiagnosticsPublished?.Invoke(parameters); + + public void PublishSemanticTokensRefreshRequested() + => SemanticTokensRefreshRequested?.Invoke(); + + public void Dispose() + { } + } +} diff --git a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs new file mode 100644 index 0000000000..d85e85b394 --- /dev/null +++ b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs @@ -0,0 +1,62 @@ +using System.Text.Json; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaLanguageServerResponseParserTests +{ + [TestMethod] + public void ParseCompletionItem_AddsLocalAndUpvaluePriorityBonuses() + { + JsonElement baselineElement = CreateCompletionItem("baseline", kind: 6, detail: "variable", documentation: "plain text"); + JsonElement boostedElement = CreateCompletionItem("boosted", kind: 6, detail: "local variable", documentation: "upvalue"); + + LuaCompletionItem? baselineItem = LuaLanguageServerResponseParser.ParseCompletionItem(baselineElement, 0); + LuaCompletionItem? boostedItem = LuaLanguageServerResponseParser.ParseCompletionItem(boostedElement, 0); + + Assert.IsNotNull(baselineItem); + Assert.IsNotNull(boostedItem); + Assert.AreEqual(35000.0, boostedItem.Priority - baselineItem.Priority); + } + + [TestMethod] + public void ParseCompletionItem_UsesParameterIconWhenDetailContainsParameter() + { + JsonElement itemElement = CreateCompletionItem("arg", kind: 6, detail: "parameter", documentation: null); + + LuaCompletionItem? item = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, 0); + + Assert.IsNotNull(item); + Assert.AreEqual(LuaCompletionIconKind.Parameter, item.IconKind); + } + + [TestMethod] + public void ParseCompletionItems_DeduplicatesLabelAndInsertTextCaseSensitively() + { + IReadOnlyList items = LuaLanguageServerResponseParser.ParseCompletionItems( + [ + CreateCompletionItem("Value", kind: 6, detail: "variable", documentation: null, insertText: "Value"), + CreateCompletionItem("value", kind: 6, detail: "variable", documentation: null, insertText: "value"), + CreateCompletionItem("Value", kind: 6, detail: "variable", documentation: null, insertText: "Value") + ]); + + // Lua is case-sensitive: "Value" and "value" are distinct symbols, but the duplicate "Value" + // must still collapse so the popup does not show the same entry twice. + Assert.AreEqual(2, items.Count); + Assert.AreEqual("Value", items[0].Label); + Assert.AreEqual("value", items[1].Label); + } + + private static JsonElement CreateCompletionItem(string label, int kind, string? detail, string? documentation, string? insertText = null) + => JsonSerializer.SerializeToElement(new Dictionary + { + ["label"] = label, + ["kind"] = kind, + ["detail"] = detail, + ["documentation"] = documentation, + ["insertText"] = insertText ?? label, + ["filterText"] = label + }); +} diff --git a/TombLib/TombLib.Test/LuaLineParserTests.cs b/TombLib/TombLib.Test/LuaLineParserTests.cs index c54df9f9af..9df235f9d1 100644 --- a/TombLib/TombLib.Test/LuaLineParserTests.cs +++ b/TombLib/TombLib.Test/LuaLineParserTests.cs @@ -1,4 +1,3 @@ -using System.Linq; using TombLib.Scripting.Lua.Utils; namespace TombLib.Test; @@ -10,7 +9,6 @@ public class LuaLineParserTests public void IsInsideCommentOrString_ReturnsTrueInsideLongComment() { bool result = LuaLineParser.IsInsideCommentOrString("--[[ comment"); - Assert.IsTrue(result); } @@ -18,7 +16,6 @@ public void IsInsideCommentOrString_ReturnsTrueInsideLongComment() public void IsInsideCommentOrString_ReturnsTrueInsideLongString() { bool result = LuaLineParser.IsInsideCommentOrString("value = [[comment"); - Assert.IsTrue(result); } @@ -26,15 +23,13 @@ public void IsInsideCommentOrString_ReturnsTrueInsideLongString() public void StripLineComment_RemovesInlineLongCommentAndKeepsCodeAfterIt() { string result = LuaLineParser.StripLineComment("value = 1 --[[ remove this ]] + 2"); - Assert.AreEqual("value = 1 + 2", result); } [TestMethod] public void EnumerateStructuralCharacters_SkipsLongStringContents() { - string result = new string(LuaLineParser.EnumerateStructuralCharacters("{ [[ignored } text]] }").ToArray()); - + string result = new(LuaLineParser.EnumerateStructuralCharacters("{ [[ignored } text]] }").ToArray()); Assert.AreEqual("{ }", result); } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs b/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs index f72f15ecc5..aee31d1747 100644 --- a/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs +++ b/TombLib/TombLib.Test/LuaThemeConfigurationTests.cs @@ -1,7 +1,6 @@ -using System.Linq; +using TombLib.Scripting.Highlighting; using TombLib.Scripting.Lua; using TombLib.Scripting.Lua.Resources; -using TombLib.Scripting.Highlighting; namespace TombLib.Test; @@ -168,4 +167,4 @@ public void TomorrowTheme_UsesCanonicalPalette() Assert.AreEqual("#4271AE", functionRule?.Foreground); Assert.AreEqual("#8959A8", keywordRule?.Foreground); } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Test/TombLib.Test.csproj b/TombLib/TombLib.Test/TombLib.Test.csproj index efdaf2ee7f..51bf59557b 100644 --- a/TombLib/TombLib.Test/TombLib.Test.csproj +++ b/TombLib/TombLib.Test/TombLib.Test.csproj @@ -18,6 +18,7 @@ + From a16aac5cc0cf67b6bc3724df35b0dd2384230572 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Wed, 22 Apr 2026 23:28:52 +0100 Subject: [PATCH 22/34] More improvements --- .../LuaStudio.Intellisense.cs | 29 +++ .../ILuaLanguageServerClient.cs | 1 + .../LuaLanguageServerClient.cs | 52 +++++ ...ageServerIntellisenseProvider.Documents.cs | 13 +- ...rverIntellisenseProvider.SemanticTokens.cs | 6 +- .../LuaLanguageServerIntellisenseProvider.cs | 78 +++++++- ...LanguageServerSemanticTokensDeltaParser.cs | 9 +- .../LuaLanguageServerSemanticTokensParser.cs | 27 --- .../LuaLanguageServerStartupFailure.cs | 5 + .../LuaTextDocumentSyncKind.cs | 10 + .../LuaWorkspaceFileWatcher.cs | 3 + .../Objects/LuaCompletionData.cs | 15 +- .../LuaIncrementalEditCalculatorTests.cs | 33 ---- .../LuaLanguageServerClientTests.cs | 36 ++++ ...LanguageServerIntellisenseProviderTests.cs | 180 +++++++++++++++++- .../LuaLanguageServerResponseParserTests.cs | 127 ++++++++++++ 16 files changed, 545 insertions(+), 79 deletions(-) delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 518e2377fd..589dd9ad15 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -30,6 +30,12 @@ private void HookLuaIntellisense() _intellisenseProvider.DiagnosticsUpdated += IntellisenseProvider_DiagnosticsUpdated; _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; _intellisenseProvider.SemanticTokensUpdated += IntellisenseProvider_SemanticTokensUpdated; + + if (_intellisenseProvider is LuaLanguageServerIntellisenseProvider languageServerProvider) + { + languageServerProvider.StartupFailed -= IntellisenseProvider_StartupFailed; + languageServerProvider.StartupFailed += IntellisenseProvider_StartupFailed; + } } private void DisposeLuaIntellisense() @@ -37,6 +43,10 @@ private void DisposeLuaIntellisense() EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; + + if (_intellisenseProvider is LuaLanguageServerIntellisenseProvider languageServerProvider) + languageServerProvider.StartupFailed -= IntellisenseProvider_StartupFailed; + _intellisenseProvider.Dispose(); } @@ -50,6 +60,7 @@ private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() // of knowing why diagnostics, completion and definition lookups silently stop working. // Log a warning and surface a single non-blocking notification so the failure is visible. Log.Warn("Bundled Lua language server was not found; Lua IntelliSense (diagnostics, completion, hover, go-to-definition) will be unavailable for this session."); + DarkUI.Forms.DarkMessageBox.Show(this, "The bundled Lua language server (LuaLS) could not be located.\n\n" + "Lua IntelliSense - including diagnostics, completion, hover and go-to-definition - will be unavailable for this session.\n\n" + @@ -114,6 +125,24 @@ private void IntellisenseProvider_SemanticTokensUpdated(string filePath, IReadOn } } + private void IntellisenseProvider_StartupFailed(LuaLanguageServerStartupFailure failure) + { + if (InvokeRequired) + { + BeginInvoke(new Action(IntellisenseProvider_StartupFailed), failure); + return; + } + + if (IsDisposed) + return; + + DarkUI.Forms.DarkMessageBox.Show(this, + failure.Message, + failure.IsPersistent ? "Lua IntelliSense disabled" : "Lua IntelliSense unavailable", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + } + private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) { if (definitionLocation is null || string.IsNullOrWhiteSpace(definitionLocation.FilePath) || !File.Exists(definitionLocation.FilePath)) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs index dca780dc08..48cf6fe61d 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs @@ -11,6 +11,7 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; internal interface ILuaLanguageServerClient : IDisposable { bool IsReady { get; } + LuaTextDocumentSyncKind TextDocumentSyncKind { get; } IReadOnlyList SemanticTokenTypes { get; } IReadOnlyList SemanticTokenModifiers { get; } bool SupportsCompletionResolve { get; } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index 3d0b4516f5..caef2c2985 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -72,6 +72,7 @@ internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient private int _receiveBufferCount; private Task? _readLoopTask; private Task? _stderrLoopTask; + private LuaTextDocumentSyncKind _textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; private string[] _semanticTokenTypes = []; private string[] _semanticTokenModifiers = []; private bool _supportsCompletionResolve; @@ -83,6 +84,7 @@ public bool IsReady private set => _isReady = value; } + public LuaTextDocumentSyncKind TextDocumentSyncKind => _textDocumentSyncKind; public IReadOnlyList SemanticTokenTypes => _semanticTokenTypes; public IReadOnlyList SemanticTokenModifiers => _semanticTokenModifiers; public bool SupportsCompletionResolve => _supportsCompletionResolve; @@ -271,12 +273,24 @@ private void CaptureServerCapabilities(JsonElement initializeResponse) { _supportsCompletionResolve = false; _supportsSemanticTokensDelta = false; + _textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; _semanticTokenTypes = []; _semanticTokenModifiers = []; if (!initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities)) return; + if (TryReadTextDocumentSyncKind(capabilities, out LuaTextDocumentSyncKind textDocumentSyncKind)) + { + if (textDocumentSyncKind == LuaTextDocumentSyncKind.None) + { + throw new NotSupportedException( + "The Lua language server does not advertise full or incremental text synchronization required by TombIDE."); + } + + _textDocumentSyncKind = textDocumentSyncKind; + } + if (capabilities.TryGetProperty("completionProvider", out JsonElement completionProvider) && completionProvider.TryGetProperty("resolveProvider", out JsonElement resolveProvider)) { @@ -300,6 +314,42 @@ private void CaptureServerCapabilities(JsonElement initializeResponse) _semanticTokenModifiers = ReadStringArray(legend, "tokenModifiers"); } + private static bool TryReadTextDocumentSyncKind(JsonElement capabilities, out LuaTextDocumentSyncKind textDocumentSyncKind) + { + textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; + + if (!capabilities.TryGetProperty("textDocumentSync", out JsonElement textDocumentSyncElement)) + return false; + + if (textDocumentSyncElement.ValueKind == JsonValueKind.Number + && textDocumentSyncElement.TryGetInt32(out int rawSyncKind)) + { + textDocumentSyncKind = ParseTextDocumentSyncKind(rawSyncKind); + return true; + } + + if (textDocumentSyncElement.ValueKind != JsonValueKind.Object) + return false; + + if (!textDocumentSyncElement.TryGetProperty("change", out JsonElement changeElement) + || !changeElement.TryGetInt32(out rawSyncKind)) + { + textDocumentSyncKind = LuaTextDocumentSyncKind.None; + return true; + } + + textDocumentSyncKind = ParseTextDocumentSyncKind(rawSyncKind); + return true; + } + + private static LuaTextDocumentSyncKind ParseTextDocumentSyncKind(int rawSyncKind) => rawSyncKind switch + { + 0 => LuaTextDocumentSyncKind.None, + 1 => LuaTextDocumentSyncKind.Full, + 2 => LuaTextDocumentSyncKind.Incremental, + _ => LuaTextDocumentSyncKind.None + }; + private static string[] ReadStringArray(JsonElement parent, string propertyName) { if (!parent.TryGetProperty(propertyName, out JsonElement property) || property.ValueKind != JsonValueKind.Array) @@ -480,7 +530,9 @@ private void ResetProcessState() _receiveBufferCount = 0; _readLoopTask = null; _stderrLoopTask = null; + _textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; _supportsCompletionResolve = false; + _supportsSemanticTokensDelta = false; _semanticTokenTypes = []; _semanticTokenModifiers = []; } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs index 298c32c64b..eddad4aaad 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs @@ -167,8 +167,9 @@ await _client.SendNotificationAsync("textDocument/didOpen", } else if (request.Kind == LuaDocumentSynchronizationKind.Change) { - object contentChange = request.ChangeRange is { } changeRange - ? new + object contentChange = _client.TextDocumentSyncKind switch + { + LuaTextDocumentSyncKind.Incremental when request.ChangeRange is { } changeRange => new { range = new { @@ -176,8 +177,12 @@ await _client.SendNotificationAsync("textDocument/didOpen", end = new { line = changeRange.EndLine, character = changeRange.EndCharacter } }, text = changeRange.Text - } - : new { text = request.Document.Content }; + }, + LuaTextDocumentSyncKind.Full => new { text = request.Document.Content }, + LuaTextDocumentSyncKind.Incremental => new { text = request.Document.Content }, + _ => throw new InvalidOperationException( + "The Lua language server does not support document changes required by TombIDE.") + }; await _client.SendNotificationAsync("textDocument/didChange", new diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs index 4e41ea6764..d08375fe1c 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs @@ -131,11 +131,7 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc return (tokens, data, fullResponse.ResultId); } - // Legacy code path: parser returns the typed token list without exposing the raw int stream. - IReadOnlyList legacyTokens = LuaLanguageServerSemanticTokensParser.Parse( - response, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); - - return (legacyTokens, null, fullResponse.ResultId); + return ([], null, fullResponse.ResultId); } private CancellationToken ReplaceSemanticTokenRequest(string filePath, CancellationToken cancellationToken, out CancellationTokenSource? linkedSource) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index 34b6469491..7d60cd014d 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.IO; using System.Threading; using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; @@ -19,6 +20,7 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10); private const int HardStartupFailureThreshold = 3; + private readonly string _workspaceApiDirectoryPath; private readonly string _workspaceRootDirectoryPath; private readonly ILuaLanguageServerClient? _client; private readonly LuaIntellisenseDocumentManager _documents = new(); @@ -30,6 +32,8 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell private bool _startupSucceeded; private int _consecutiveStartupFailures; + private bool _permanentStartupFailureReported; + private bool _transientStartupFailureReported; private volatile bool _isDisposed; public bool IsAvailable => !_isDisposed && _client is not null @@ -37,6 +41,7 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell public event Action>? DiagnosticsUpdated; public event Action>? SemanticTokensUpdated; + public event Action? StartupFailed; public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string? serverExecutablePath) : this(workspaceRootDirectoryPath, CreateClient(workspaceRootDirectoryPath, serverExecutablePath)) @@ -45,6 +50,7 @@ public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, internal LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, ILuaLanguageServerClient? client) { _workspaceRootDirectoryPath = LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); + _workspaceApiDirectoryPath = Path.Combine(_workspaceRootDirectoryPath, ".API"); _client = client; if (_client is not null) @@ -104,7 +110,7 @@ public void CloseDocument(string filePath) private async Task EnsureStartedAsync(CancellationToken cancellationToken) { - if (_client is null) + if (_client is null || _consecutiveStartupFailures >= HardStartupFailureThreshold) return false; if (_startupSucceeded && _client.IsReady) @@ -119,6 +125,9 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) { IReadOnlyList documentsToReopen = []; + if (_consecutiveStartupFailures >= HardStartupFailureThreshold) + return false; + if (_startupSucceeded && _client.IsReady) { EnsureWorkspaceFileWatcherStarted(); @@ -144,13 +153,16 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) if (_startupSucceeded) { _consecutiveStartupFailures = 0; + _transientStartupFailureReported = false; + _permanentStartupFailureReported = false; EnsureWorkspaceFileWatcherStarted(); } else { _consecutiveStartupFailures++; + bool isPermanentFailure = _consecutiveStartupFailures >= HardStartupFailureThreshold; - if (_consecutiveStartupFailures >= HardStartupFailureThreshold) + if (isPermanentFailure) { Log.Error("Lua language server failed to start {Count} times consecutively for workspace '{Workspace}'; IntelliSense is now disabled until the editor is restarted.", _consecutiveStartupFailures, _workspaceRootDirectoryPath); @@ -160,6 +172,8 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) Log.Warn("Failed to start the Lua language server for workspace '{Workspace}' (attempt {Attempt}/{Threshold}).", _workspaceRootDirectoryPath, _consecutiveStartupFailures, HardStartupFailureThreshold); } + + ReportStartupFailure(isPermanentFailure); } return _startupSucceeded; @@ -189,12 +203,15 @@ private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, Canc return; var changes = new List(batch.Count); + bool shouldRefreshConfiguration = false; foreach ((string path, FileChangeKind kind) in batch.Entries) { if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(path, out string normalizedPath)) continue; + shouldRefreshConfiguration |= IsWorkspaceConfigurationPath(normalizedPath); + changes.Add(new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedPath), @@ -207,6 +224,13 @@ private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, Canc try { + if (shouldRefreshConfiguration) + { + await _client.SendNotificationAsync("workspace/didChangeConfiguration", + new { settings = LuaLanguageServerSettingsFactory.Create(_workspaceRootDirectoryPath) }, + cancellationToken).ConfigureAwait(false); + } + await _client.SendNotificationAsync("workspace/didChangeWatchedFiles", new { changes }, cancellationToken).ConfigureAwait(false); } @@ -218,6 +242,56 @@ await _client.SendNotificationAsync("workspace/didChangeWatchedFiles", } } + private bool IsWorkspaceConfigurationPath(string normalizedPath) + { + if (string.Equals(normalizedPath, _workspaceApiDirectoryPath, StringComparison.OrdinalIgnoreCase)) + return true; + + string apiDirectoryPrefix = _workspaceApiDirectoryPath + Path.DirectorySeparatorChar; + + if (normalizedPath.StartsWith(apiDirectoryPrefix, StringComparison.OrdinalIgnoreCase)) + return true; + + string fileName = Path.GetFileName(normalizedPath); + return string.Equals(fileName, ".luarc.json", StringComparison.OrdinalIgnoreCase) + || string.Equals(fileName, ".luarc.jsonc", StringComparison.OrdinalIgnoreCase); + } + + private void ReportStartupFailure(bool isPermanentFailure) + { + if (isPermanentFailure) + { + if (_permanentStartupFailureReported) + return; + + _permanentStartupFailureReported = true; + } + else + { + if (_transientStartupFailureReported) + return; + + _transientStartupFailureReported = true; + } + + LuaLanguageServerStartupFailure failure = isPermanentFailure + ? new LuaLanguageServerStartupFailure( + "The bundled Lua language server failed to start repeatedly and Lua IntelliSense is now disabled until TombIDE is restarted. See the log for technical details.", + true) + : new LuaLanguageServerStartupFailure( + "The bundled Lua language server failed to start. Lua IntelliSense will remain unavailable until TombIDE can start the server successfully. TombIDE will retry automatically when Lua IntelliSense is requested again.", + false); + + try + { + StartupFailed?.Invoke(failure); + } + catch (Exception exception) + { + Log.Debug(exception, "Lua IntelliSense startup-failure notification handler threw."); + } + } + public void Dispose() { if (_isDisposed) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs index 87e89b622e..56b13566a0 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs @@ -65,8 +65,10 @@ public static LuaSemanticTokensDeltaResponse Parse(JsonElement response) ArgumentNullException.ThrowIfNull(previousData); ArgumentNullException.ThrowIfNull(edits); - // LSP guarantees edits are sorted by ascending start, but applying them in reverse keeps the - // untouched suffix indices stable and avoids any index shifting on the way through. + // LSP requires edits to be sorted by ascending start; we re-sort defensively in case the server + // or our own caching layer reorders them. Edits are then applied left-to-right with a running + // source/destination cursor so the resulting integer stream stays consistent regardless of + // individual edit sizes. var ordered = new List(edits); ordered.Sort(static (a, b) => a.Start.CompareTo(b.Start)); @@ -131,8 +133,7 @@ private static int[] ReadIntArray(JsonElement arrayElement) /// /// Decodes a raw LuaLS semantic-token integer stream (already cached on the client) into the typed -/// list expected by the editor's colorizer. Mirrors -/// but operates directly on the cached array. +/// list expected by the editor's colorizer. /// internal static class LuaLanguageServerSemanticTokensDecoder { diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs deleted file mode 100644 index cb911cec35..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensParser.cs +++ /dev/null @@ -1,27 +0,0 @@ -#nullable enable - -using System.Collections.Generic; -using System.Text.Json; -using TombLib.Scripting.Lua.Objects; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal static class LuaLanguageServerSemanticTokensParser -{ - /// - /// Decodes the LuaLS semantic token payload for a synchronized document snapshot. - /// - public static IReadOnlyList Parse(JsonElement response, LuaDocumentSnapshot? document, - IReadOnlyList? tokenTypes, IReadOnlyList? tokenModifiers) - { - if (document is null || tokenTypes is null || tokenTypes.Count == 0) - return []; - - LuaSemanticTokensDeltaResponse parsedResponse = LuaLanguageServerSemanticTokensDeltaParser.Parse(response); - - if (parsedResponse.Data is not { } data) - return []; - - return LuaLanguageServerSemanticTokensDecoder.Decode(data, document, tokenTypes, tokenModifiers); - } -} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs new file mode 100644 index 0000000000..6b061471be --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs @@ -0,0 +1,5 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal readonly record struct LuaLanguageServerStartupFailure(string Message, bool IsPersistent); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs new file mode 100644 index 0000000000..8e366c5481 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs @@ -0,0 +1,10 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal enum LuaTextDocumentSyncKind +{ + None = 0, + Full = 1, + Incremental = 2 +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs index 1a1aa1d6e9..cee361cd51 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs @@ -29,6 +29,7 @@ internal sealed class LuaWorkspaceFileWatcher : IDisposable private readonly CancellationTokenSource _lifetimeCts = new(); private FileSystemWatcher? _luaWatcher; + private FileSystemWatcher? _apiDirectoryWatcher; private FileSystemWatcher? _configWatcher; private Timer? _debounceTimer; private volatile bool _isDisposed; @@ -49,6 +50,7 @@ public bool Start() try { + _apiDirectoryWatcher = CreateWatcher(".API", includeSubdirectories: false); _luaWatcher = CreateWatcher("*.lua", includeSubdirectories: true); _configWatcher = CreateWatcher(".luarc.*", includeSubdirectories: false); _debounceTimer = new Timer(OnDebounceTick, state: null, dueTime: Timeout.Infinite, period: Timeout.Infinite); @@ -164,6 +166,7 @@ public void Dispose() _isDisposed = true; + TryDispose(_apiDirectoryWatcher, nameof(_apiDirectoryWatcher)); TryDispose(_luaWatcher, nameof(_luaWatcher)); TryDispose(_configWatcher, nameof(_configWatcher)); TryDispose(_debounceTimer, nameof(_debounceTimer)); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index 10c042ed14..57db0ea936 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -24,6 +24,8 @@ internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChange private static readonly SolidColorBrush DescriptionBackgroundBrush = TextEditorColorPalette.ToolTipBackground; private static readonly SolidColorBrush DescriptionForegroundBrush = TextEditorColorPalette.ToolTipForeground; + private static readonly object NoDescriptionSentinel = new(); + private readonly object _resolveSync = new(); private readonly LuaThemeBrushSet _brushSet; @@ -47,7 +49,18 @@ public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet) public string? DisplayDetail => _displayDetail; public Visibility DetailVisibility => string.IsNullOrEmpty(_displayDetail) ? Visibility.Collapsed : Visibility.Visible; public object Content => DisplayText; - public object? Description => _cachedDescription ??= BuildDescriptionContent(); + + public object? Description + { + get + { + // Cache a sentinel for a missing description so subsequent accesses do not keep + // rebuilding the same null result on every selection change. + _cachedDescription ??= BuildDescriptionContent() ?? NoDescriptionSentinel; + return ReferenceEquals(_cachedDescription, NoDescriptionSentinel) ? null : _cachedDescription; + } + } + public double Priority => _item.Priority; public bool CanResolve => _item.CanResolve; diff --git a/TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs b/TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs index 1913760615..427bd47295 100644 --- a/TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs +++ b/TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs @@ -1,6 +1,4 @@ -using System.Text.Json; using TombIDE.ScriptingStudio.Services.LuaIntellisense; -using TombLib.Scripting.Lua.Objects; namespace TombLib.Test; @@ -89,34 +87,3 @@ public void ApplyEdits_AppliesMultipleEditsInAscendingOrder() CollectionAssert.AreEqual(new[] { 99, 10, 11, 12, 13, 44, 45 }, result); } } - -[TestClass] -public class LuaLanguageServerSemanticTokensParserTests -{ - [TestMethod] - public void Parse_DecodesDataArrayUsingSharedDecoder() - { - JsonElement response = JsonSerializer.SerializeToElement(new - { - data = new[] { 0, 6, 5, 0, 0 } - }); - - var document = new LuaDocumentSnapshot( - @"C:\Workspace\test.lua", - new Uri(@"C:\Workspace\test.lua").AbsoluteUri, - "local value = 1", - 1); - - IReadOnlyList tokens = LuaLanguageServerSemanticTokensParser.Parse( - response, - document, - ["variable"], - []); - - Assert.AreEqual(1, tokens.Count); - Assert.AreEqual(0, tokens[0].Line); - Assert.AreEqual(6, tokens[0].Character); - Assert.AreEqual(5, tokens[0].Length); - Assert.AreEqual("variable", tokens[0].Type); - } -} diff --git a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs index fdcbbaade7..43405b0a91 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs @@ -12,6 +12,42 @@ namespace TombLib.Test; [TestClass] public class LuaLanguageServerClientTests { + [TestMethod] + public void CaptureServerCapabilities_UsesFullTextSyncWhenServerAdvertisesFullSync() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + + InvokePrivateMethod(client, "CaptureServerCapabilities", JsonSerializer.SerializeToElement(new + { + capabilities = new + { + textDocumentSync = new + { + change = 1 + } + } + })); + + Assert.AreEqual(LuaTextDocumentSyncKind.Full, client.TextDocumentSyncKind); + } + + [TestMethod] + public void CaptureServerCapabilities_RejectsMissingDocumentChangeSupport() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + + TargetInvocationException exception = Assert.ThrowsException(() => + InvokePrivateMethod(client, "CaptureServerCapabilities", JsonSerializer.SerializeToElement(new + { + capabilities = new + { + textDocumentSync = 0 + } + }))); + + Assert.IsInstanceOfType(exception.InnerException, typeof(NotSupportedException)); + } + [TestMethod] public void Dispose_WritesGracefulShutdownMessages() { diff --git a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs index e88f2af76e..2f4bf3e382 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs @@ -9,6 +9,146 @@ namespace TombLib.Test; [TestClass] public class LuaLanguageServerIntellisenseProviderTests { + [TestMethod] + public async Task GetCompletionItemsAsync_ResolvesCompletionItemDetailsWhenServerSupportsResolve() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + SupportsCompletionResolve = true, + CompletionResponse = JsonSerializer.SerializeToElement(new + { + items = new object[] + { + new + { + label = "spawn", + kind = 3, + insertText = "spawn" + } + } + }), + CompletionResolveResponse = JsonSerializer.SerializeToElement(new + { + label = "spawn", + kind = 3, + insertText = "spawn", + detail = "function", + documentation = "Spawn docs." + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + IReadOnlyList items = await provider.GetCompletionItemsAsync(filePath, "spa", 0, 3); + LuaCompletionItem resolvedItem = await items[0].ResolveAsync(); + + Assert.AreEqual(1, items.Count); + Assert.IsTrue(items[0].CanResolve); + Assert.AreEqual("function", resolvedItem.Detail); + Assert.AreEqual("Spawn docs.", resolvedItem.Description); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/completion", "completionItem/resolve" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task DispatchWorkspaceFileChangesAsync_RefreshesConfigurationWhenApiLibraryChanges() + { + string workspaceRoot = Path.Combine(Path.GetTempPath(), "LuaConfigRefresh_" + Guid.NewGuid().ToString("N")); + string apiDirectory = Path.Combine(workspaceRoot, ".API"); + string apiFilePath = Path.Combine(apiDirectory, "Generated.lua"); + + try + { + Directory.CreateDirectory(apiDirectory); + File.WriteAllText(apiFilePath, "return {}"); + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + var batch = new FileChangeBatch(); + + batch.Add(apiFilePath, FileChangeKind.Changed); + + await InvokePrivateTaskAsync(provider, "DispatchWorkspaceFileChangesAsync", batch, CancellationToken.None); + + CollectionAssert.AreEqual( + new[] { "workspace/didChangeConfiguration", "workspace/didChangeWatchedFiles" }, + client.GetSentMethodNames()); + + JsonElement settings = client.GetLastNotificationParameters("workspace/didChangeConfiguration") + .GetProperty("settings") + .GetProperty("Lua") + .GetProperty("workspace") + .GetProperty("library"); + + Assert.AreEqual(1, settings.GetArrayLength()); + Assert.AreEqual(apiDirectory, settings[0].GetString()); + } + finally + { + if (Directory.Exists(workspaceRoot)) + Directory.Delete(workspaceRoot, recursive: true); + } + } + + [TestMethod] + public async Task GetHoverAsync_RaisesTransientAndPermanentStartupFailuresOnceEach() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + IsReady = false, + StartResult = false + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + var failures = new List(); + + provider.StartupFailed += failure => failures.Add(failure); + + await provider.GetHoverAsync(filePath, content, 0, 0); + await provider.GetHoverAsync(filePath, content, 0, 0); + await provider.GetHoverAsync(filePath, content, 0, 0); + await provider.GetHoverAsync(filePath, content, 0, 0); + + Assert.AreEqual(2, failures.Count); + Assert.IsFalse(failures[0].IsPersistent); + Assert.IsTrue(failures[1].IsPersistent); + Assert.AreEqual(3, client.StartCallCount); + } + + [TestMethod] + public async Task UpdateDocument_SendsFullTextChangeWhenServerAdvertisesFullSync() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + TextDocumentSyncKind = LuaTextDocumentSyncKind.Full + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(filePath, "local value = 1"); + provider.UpdateDocument(filePath, "local value = 2"); + + Assert.IsTrue(await client.WaitForNotificationAsync("textDocument/didChange", TimeSpan.FromSeconds(1))); + + JsonElement parameters = client.GetLastNotificationParameters("textDocument/didChange"); + JsonElement change = parameters.GetProperty("contentChanges")[0]; + + Assert.AreEqual("local value = 2", change.GetProperty("text").GetString()); + Assert.IsFalse(change.TryGetProperty("range", out _)); + } + [TestMethod] public async Task GetHoverAsync_ReplaysTrackedDocumentsAfterLanguageServerRestart() { @@ -224,17 +364,33 @@ private static JsonElement CreateDiagnostics(string filePath, int version, int s return field.GetValue(provider) as LuaWorkspaceFileWatcher; } + private static async Task InvokePrivateTaskAsync(object instance, string methodName, params object?[] parameters) + { + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private method '{methodName}' was not found."); + + Task task = (Task)(method.Invoke(instance, parameters) + ?? throw new InvalidOperationException($"Private method '{methodName}' returned null instead of a Task.")); + + await task.ConfigureAwait(false); + } + private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient { + private readonly List<(string Method, JsonElement Parameters)> _sentNotifications = []; private readonly List _sentMethodNames = []; private TaskCompletionSource? _openNotificationGate; private readonly TaskCompletionSource _changeNotificationObserved = new(TaskCreationOptions.RunContinuationsAsynchronously); private readonly TaskCompletionSource _closeNotificationObserved = new(TaskCreationOptions.RunContinuationsAsynchronously); public bool IsReady { get; set; } = true; + public bool StartResult { get; set; } = true; + public JsonElement CompletionResponse { get; set; } + public JsonElement CompletionResolveResponse { get; set; } + public LuaTextDocumentSyncKind TextDocumentSyncKind { get; set; } = LuaTextDocumentSyncKind.Incremental; public IReadOnlyList SemanticTokenTypes { get; set; } = []; public IReadOnlyList SemanticTokenModifiers { get; set; } = []; - public bool SupportsCompletionResolve => false; + public bool SupportsCompletionResolve { get; set; } public bool SupportsSemanticTokensDelta => false; public int StartCallCount { get; private set; } @@ -245,13 +401,14 @@ private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient public Task StartAsync(CancellationToken cancellationToken) { StartCallCount++; - IsReady = true; - return Task.FromResult(true); + IsReady = StartResult; + return Task.FromResult(StartResult); } public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) { _sentMethodNames.Add(method); + _sentNotifications.Add((method, JsonSerializer.SerializeToElement(parameters))); if (method == "textDocument/didChange") _changeNotificationObserved.TrySetResult(true); @@ -269,6 +426,12 @@ public Task SendRequestAsync(string method, object parameters, Canc { _sentMethodNames.Add(method); + if (method == "textDocument/completion" && CompletionResponse.ValueKind != JsonValueKind.Undefined) + return Task.FromResult(CompletionResponse); + + if (method == "completionItem/resolve" && CompletionResolveResponse.ValueKind != JsonValueKind.Undefined) + return Task.FromResult(CompletionResolveResponse); + if (method == "textDocument/semanticTokens/full") { return Task.FromResult(JsonSerializer.SerializeToElement(new @@ -283,6 +446,17 @@ public Task SendRequestAsync(string method, object parameters, Canc public string[] GetSentMethodNames() => [.. _sentMethodNames]; + public JsonElement GetLastNotificationParameters(string method) + { + for (int i = _sentNotifications.Count - 1; i >= 0; i--) + { + if (string.Equals(_sentNotifications[i].Method, method, StringComparison.Ordinal)) + return _sentNotifications[i].Parameters; + } + + throw new InvalidOperationException($"Notification '{method}' was not observed."); + } + public void BlockNextOpenNotification() => _openNotificationGate = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs index d85e85b394..dfc4b22765 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs @@ -49,6 +49,133 @@ public void ParseCompletionItems_DeduplicatesLabelAndInsertTextCaseSensitively() Assert.AreEqual("value", items[1].Label); } + [TestMethod] + public void ParseDefinitionLocation_UsesFirstEntryFromMultiLocationResponse() + { + string firstPath = Path.GetFullPath(@"C:\Workspace\Scripts\first.lua"); + string secondPath = Path.GetFullPath(@"C:\Workspace\Scripts\second.lua"); + + LuaDefinitionLocation? location = LuaLanguageServerResponseParser.ParseDefinitionLocation( + JsonSerializer.SerializeToElement(new object[] + { + new + { + uri = new Uri(firstPath).AbsoluteUri, + range = new + { + start = new { line = 2, character = 4 }, + end = new { line = 2, character = 10 } + } + }, + new + { + uri = new Uri(secondPath).AbsoluteUri, + range = new + { + start = new { line = 8, character = 1 }, + end = new { line = 8, character = 5 } + } + } + })); + + Assert.IsNotNull(location); + Assert.AreEqual(firstPath, location.FilePath); + Assert.AreEqual(3, location.LineNumber); + Assert.AreEqual(5, location.ColumnNumber); + } + + [TestMethod] + public void ParseDefinitionLocation_UsesTargetSelectionRangeFromLocationLink() + { + string targetPath = Path.GetFullPath(@"C:\Workspace\Scripts\linked.lua"); + + LuaDefinitionLocation? location = LuaLanguageServerResponseParser.ParseDefinitionLocation( + JsonSerializer.SerializeToElement(new + { + targetUri = new Uri(targetPath).AbsoluteUri, + targetSelectionRange = new + { + start = new { line = 4, character = 2 }, + end = new { line = 4, character = 9 } + } + })); + + Assert.IsNotNull(location); + Assert.AreEqual(targetPath, location.FilePath); + Assert.AreEqual(5, location.LineNumber); + Assert.AreEqual(3, location.ColumnNumber); + } + + [TestMethod] + public void ParseSignatureHelp_UsesParameterLabelOffsetsAndActiveParameter() + { + LuaSignatureInfo? signatureInfo = LuaLanguageServerResponseParser.ParseSignatureHelp( + JsonSerializer.SerializeToElement(new + { + activeSignature = 0, + activeParameter = 1, + signatures = new[] + { + new + { + label = "spawn(room, objectName)", + documentation = new + { + kind = "markdown", + value = "Spawns an object." + }, + parameters = new object[] + { + new + { + label = new[] { 6, 10 }, + documentation = "Room id." + }, + new + { + label = new[] { 12, 22 }, + documentation = "Object name." + } + } + } + } + })); + + Assert.IsNotNull(signatureInfo); + Assert.AreEqual("spawn(room, objectName)", signatureInfo.Label); + Assert.AreEqual("Spawns an object.", signatureInfo.Documentation); + Assert.AreEqual(1, signatureInfo.ActiveParameter); + Assert.AreEqual(2, signatureInfo.Parameters.Count); + Assert.AreEqual("objectName", signatureInfo.Parameters[1].Label); + Assert.AreEqual("Object name.", signatureInfo.Parameters[1].Documentation); + } + + [TestMethod] + public void ParseSignatureHelp_UsesSignatureLevelActiveParameterWhenResponseOmitsIt() + { + LuaSignatureInfo? signatureInfo = LuaLanguageServerResponseParser.ParseSignatureHelp( + JsonSerializer.SerializeToElement(new + { + signatures = new[] + { + new + { + label = "move(x, y)", + activeParameter = 1, + parameters = new object[] + { + new { label = "x" }, + new { label = "y" } + } + } + } + })); + + Assert.IsNotNull(signatureInfo); + Assert.AreEqual(1, signatureInfo.ActiveParameter); + Assert.AreEqual("y", signatureInfo.Parameters[1].Label); + } + private static JsonElement CreateCompletionItem(string label, int kind, string? detail, string? documentation, string? insertText = null) => JsonSerializer.SerializeToElement(new Dictionary { From 133e3dd29842ba6a40ceb49662aee863810e6891 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Wed, 22 Apr 2026 23:39:40 +0100 Subject: [PATCH 23/34] Add docs --- .../ILuaLanguageServerClient.cs | 53 ++++++++++++++++ .../LuaIntellisense/LuaDocumentLineOffsets.cs | 28 +++++++++ .../LuaIntellisense/LuaDocumentSnapshot.cs | 43 +++++++++++-- .../LuaDocumentSynchronizationKind.cs | 10 +++ .../LuaIncrementalEditCalculator.cs | 7 +++ .../LuaIntellisenseDocumentManager.cs | 53 ++++++++++++++++ .../LuaLanguageServerClient.cs | 62 ++++++++++++++++++ ...uageServerIntellisenseProvider.Requests.cs | 37 +++++++++++ .../LuaLanguageServerIntellisenseProvider.cs | 55 ++++++++++++++++ .../LuaLanguageServerPathHelper.cs | 8 +++ ...LanguageServerResponseParser.Completion.cs | 18 ++++++ ...LanguageServerSemanticTokensDeltaParser.cs | 25 ++++++++ .../LuaLanguageServerStartupFailure.cs | 5 ++ .../LuaIntellisense/LuaProcessJobObject.cs | 4 ++ .../LuaPublishedDiagnostics.cs | 35 +++++++++-- .../LuaTextDocumentSyncKind.cs | 14 +++++ .../LuaWorkspaceFileWatcher.cs | 41 ++++++++++++ .../LuaSemanticTokensColorizer.cs | 19 ++++++ .../LuaEditor.Completion.cs | 3 + .../Objects/LuaCompletionData.cs | 55 ++++++++++++++++ .../Objects/LuaCompletionIconFactory.cs | 9 +++ .../Objects/LuaCompletionWindowStyle.cs | 8 +++ .../Resources/LuaEditorColorPalette.cs | 8 +++ .../Resources/LuaThemeBrushSet.cs | 63 +++++++++++++++++++ .../Utils/LuaDocumentLineParserStateCache.cs | 12 ++++ .../Utils/LuaLineParser.cs | 18 ++++++ 26 files changed, 684 insertions(+), 9 deletions(-) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs index 48cf6fe61d..2d4024ccef 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs @@ -8,19 +8,72 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Defines the transport and capability surface used by the Lua IntelliSense provider to talk to LuaLS. +/// internal interface ILuaLanguageServerClient : IDisposable { + /// + /// Gets a value indicating whether the language server finished initialization and can accept requests. + /// bool IsReady { get; } + + /// + /// Gets the text-document synchronization mode negotiated with the language server. + /// LuaTextDocumentSyncKind TextDocumentSyncKind { get; } + + /// + /// Gets the semantic token types reported by the server capabilities. + /// IReadOnlyList SemanticTokenTypes { get; } + + /// + /// Gets the semantic token modifiers reported by the server capabilities. + /// IReadOnlyList SemanticTokenModifiers { get; } + + /// + /// Gets a value indicating whether the server supports completionItem/resolve. + /// bool SupportsCompletionResolve { get; } + + /// + /// Gets a value indicating whether the server supports semantic-token delta responses. + /// bool SupportsSemanticTokensDelta { get; } + /// + /// Occurs when the server publishes diagnostics for a tracked document. + /// event Action? DiagnosticsPublished; + + /// + /// Occurs when the server requests a semantic-token refresh for open documents. + /// event Action? SemanticTokensRefreshRequested; + /// + /// Starts the language server process and completes the LSP initialization handshake. + /// + /// A token that can cancel startup. + /// when the client is ready; otherwise, . Task StartAsync(CancellationToken cancellationToken); + + /// + /// Sends a JSON-RPC notification to the language server. + /// + /// The LSP method name. + /// The notification payload. + /// A token that can cancel the send operation. Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken); + + /// + /// Sends a JSON-RPC request to the language server and waits for the response payload. + /// + /// The LSP method name. + /// The request payload. + /// A token that can cancel the request. + /// The raw JSON response payload. Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs index 35c87cbe93..28b0e85ccf 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs @@ -24,16 +24,37 @@ private LuaDocumentLineOffsets(string content, int[] lineStartOffsets, int[] lin _lineLengths = lineLengths; } + /// + /// Gets the number of logical lines in the document. + /// public int LineCount => _lineLengths.Length; + + /// + /// Gets the total document length in characters. + /// public int TextLength => _content.Length; + /// + /// Gets the length of the specified zero-based line. + /// + /// The zero-based line index. + /// The line length in characters. public int GetLineLength(int lineIndex) => _lineLengths[lineIndex]; + + /// + /// Gets the absolute document offset where the specified zero-based line starts. + /// + /// The zero-based line index. + /// The absolute document offset. public int GetLineStartOffset(int lineIndex) => _lineStartOffsets[lineIndex]; /// /// Returns the offset within the document for the supplied zero-based line and character indices, /// clamping the character index to the line length. /// + /// The zero-based line index. + /// The zero-based character index within the line. + /// The absolute document offset. public int GetOffset(int lineIndex, int character) { int safeLine = Math.Clamp(lineIndex, 0, _lineLengths.Length - 1); @@ -41,6 +62,11 @@ public int GetOffset(int lineIndex, int character) return _lineStartOffsets[safeLine] + safeCharacter; } + /// + /// Gets the text of the specified zero-based line. + /// + /// The zero-based line index. + /// The line text without its trailing newline sequence. public string GetLineText(int lineIndex) { int safeLine = Math.Clamp(lineIndex, 0, _lineLengths.Length - 1); @@ -51,6 +77,8 @@ public string GetLineText(int lineIndex) /// Builds the offset table from the given content in a single pass, avoiding the large intermediate /// allocations of . /// + /// The document text to analyze. + /// A line-offset table for the supplied content. public static LuaDocumentLineOffsets Build(string? content) { string text = content ?? string.Empty; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs index f9319ce6f1..132dda738b 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs @@ -2,10 +2,43 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; -internal sealed class LuaDocumentSnapshot(string filePath, string uri, string? content, int version) +/// +/// Captures the current synchronized state of a tracked Lua document. +/// +internal sealed class LuaDocumentSnapshot { - public string FilePath { get; } = filePath; - public string Uri { get; } = uri; - public string Content { get; } = content ?? string.Empty; - public int Version { get; } = version; + /// + /// Initializes a new instance of the class. + /// + /// The normalized local file path. + /// The corresponding file URI sent to LuaLS. + /// The current document text. + /// The local synchronization version. + public LuaDocumentSnapshot(string filePath, string uri, string? content, int version) + { + FilePath = filePath; + Uri = uri; + Content = content ?? string.Empty; + Version = version; + } + + /// + /// Gets the normalized local file path. + /// + public string FilePath { get; } + + /// + /// Gets the file URI sent to LuaLS for this document. + /// + public string Uri { get; } + + /// + /// Gets the current document text. + /// + public string Content { get; } + + /// + /// Gets the local synchronization version. + /// + public int Version { get; } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs index 5537702dd1..50c30cc53e 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs @@ -2,8 +2,18 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Identifies the LSP document-synchronization action that should be sent for a tracked file. +/// internal enum LuaDocumentSynchronizationKind { + /// + /// The document must be opened on the server. + /// Open, + + /// + /// The document content changed and should be updated on the server. + /// Change } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs index 94100bf667..53e02df930 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs @@ -12,6 +12,13 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; /// internal static class LuaIncrementalEditCalculator { + /// + /// Computes the minimal single-range edit that transforms one document snapshot into another. + /// + /// The previously synchronized document content. + /// The updated document content. + /// The line-offset table for . + /// The incremental change range to send in textDocument/didChange. public static LuaDocumentChangeRange Compute(string oldText, string newText, LuaDocumentLineOffsets oldOffsets) { oldText ??= string.Empty; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs index 784d4a9b17..7c05bda5d9 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs @@ -8,6 +8,9 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Tracks the local document state mirrored to LuaLS, including versions, diagnostics, and semantic-token caches. +/// internal sealed class LuaIntellisenseDocumentManager { private sealed class DocumentState @@ -40,18 +43,35 @@ private sealed class DocumentState private readonly object _syncRoot = new(); private readonly Dictionary _documents = new(StringComparer.OrdinalIgnoreCase); + /// + /// Gets the cached diagnostics for the specified normalized file path. + /// + /// The normalized file path. + /// The cached diagnostics, or an empty list when none are stored. public IReadOnlyList GetDiagnostics(string filePath) { lock (_syncRoot) return _documents.TryGetValue(filePath, out DocumentState? state) ? state.Diagnostics : []; } + /// + /// Gets the cached semantic tokens for the specified normalized file path. + /// + /// The normalized file path. + /// The cached semantic tokens, or an empty list when none are stored. public IReadOnlyList GetSemanticTokens(string filePath) { lock (_syncRoot) return _documents.TryGetValue(filePath, out DocumentState? state) ? state.SemanticTokens : []; } + /// + /// Synchronizes the tracked state for a document and returns the LSP action required to mirror it to LuaLS. + /// + /// The normalized file path. + /// The latest document content. + /// Whether an additional open-editor reference should be recorded. + /// A synchronization request when LuaLS must be updated; otherwise, . public LuaDocumentSynchronizationRequest? Synchronize(string filePath, string? content, bool acquireOpenReference = false) { string safeContent = content ?? string.Empty; @@ -105,6 +125,9 @@ public IReadOnlyList GetSemanticTokens(string filePath) /// removed (and a `didClose` snapshot returned) once the reference count drops to zero, /// so multiple editor tabs sharing the same file do not invalidate each other on close. /// + /// The normalized file path. + /// When this method returns, contains the closing snapshot if the document was removed. + /// when the caller should send didClose; otherwise, . public bool TryClose(string filePath, [NotNullWhen(true)] out LuaDocumentSnapshot? document) { lock (_syncRoot) @@ -130,6 +153,10 @@ public bool TryClose(string filePath, [NotNullWhen(true)] out LuaDocumentSnapsho } } + /// + /// Marks all open documents for replay after a language-server restart and returns their snapshots. + /// + /// The snapshots that should be reopened on the next successful start. public IReadOnlyList PrepareForRestart() { lock (_syncRoot) @@ -149,6 +176,11 @@ public IReadOnlyList PrepareForRestart() } } + /// + /// Gets the current snapshot for a tracked document. + /// + /// The normalized file path. + /// The current snapshot, or when the document is not tracked. public LuaDocumentSnapshot? GetDocumentSnapshot(string filePath) { lock (_syncRoot) @@ -159,6 +191,10 @@ public IReadOnlyList PrepareForRestart() } } + /// + /// Gets snapshots for all documents that are currently considered open. + /// + /// The open-document snapshots. public IReadOnlyList GetOpenDocuments() { lock (_syncRoot) @@ -175,6 +211,11 @@ public IReadOnlyList GetOpenDocuments() } } + /// + /// Stores a diagnostics payload when it is not stale for the tracked document version. + /// + /// The diagnostics payload to cache. + /// when the payload was stored; otherwise, . public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) { lock (_syncRoot) @@ -193,6 +234,13 @@ public bool TryStoreDiagnostics(LuaPublishedDiagnostics publishedDiagnostics) } } + /// + /// Stores semantic tokens when they are not stale for the tracked document version. + /// + /// The normalized file path. + /// The document version associated with the tokens. + /// The semantic tokens to cache. + /// when the token set was stored; otherwise, . public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList semanticTokens) { lock (_syncRoot) @@ -215,6 +263,8 @@ public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList, if any. /// Used by the provider to send `semanticTokens/full/delta` requests with the previous result id. /// + /// The normalized file path. + /// The previous result id and cached integer stream, if available. public (string? PreviousResultId, int[]? PreviousData) GetSemanticTokensDeltaState(string filePath) { lock (_syncRoot) @@ -230,6 +280,9 @@ public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList + /// The normalized file path. + /// The server-provided semantic-token result id. + /// The cached integer token stream. public void StoreSemanticTokensDeltaState(string filePath, string? resultId, int[]? data) { lock (_syncRoot) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index caef2c2985..3bae99951f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -13,6 +13,9 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Hosts the LuaLS process, performs the LSP handshake, and transports JSON-RPC requests and notifications. +/// internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -78,21 +81,56 @@ internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient private bool _supportsCompletionResolve; private bool _supportsSemanticTokensDelta; + /// + /// Gets a value indicating whether the client finished initialization and can accept requests. + /// public bool IsReady { get => _isReady; private set => _isReady = value; } + /// + /// Gets the text-document synchronization mode negotiated with the server. + /// public LuaTextDocumentSyncKind TextDocumentSyncKind => _textDocumentSyncKind; + + /// + /// Gets the semantic token types advertised by the server. + /// public IReadOnlyList SemanticTokenTypes => _semanticTokenTypes; + + /// + /// Gets the semantic token modifiers advertised by the server. + /// public IReadOnlyList SemanticTokenModifiers => _semanticTokenModifiers; + + /// + /// Gets a value indicating whether the server supports completion-item resolve requests. + /// public bool SupportsCompletionResolve => _supportsCompletionResolve; + + /// + /// Gets a value indicating whether the server supports semantic-token delta responses. + /// public bool SupportsSemanticTokensDelta => _supportsSemanticTokensDelta; + /// + /// Occurs when the server publishes diagnostics for a tracked document. + /// public event Action? DiagnosticsPublished; + + /// + /// Occurs when the server requests that semantic tokens be refreshed. + /// public event Action? SemanticTokensRefreshRequested; + /// + /// Initializes a new instance of the class. + /// + /// The normalized workspace root directory. + /// The LuaLS executable path. + /// Produces the current settings payload for workspace/didChangeConfiguration. public LuaLanguageServerClient(string workspaceRootDirectoryPath, string serverExecutablePath, Func settingsProvider) { _workspaceRootDirectoryPath = workspaceRootDirectoryPath; @@ -100,6 +138,11 @@ public LuaLanguageServerClient(string workspaceRootDirectoryPath, string serverE _settingsProvider = settingsProvider; } + /// + /// Starts the LuaLS process and completes the initialize/initialized handshake. + /// + /// A token that can cancel startup. + /// when startup succeeded; otherwise, . public async Task StartAsync(CancellationToken cancellationToken) { if (IsReady) @@ -112,6 +155,7 @@ public async Task StartAsync(CancellationToken cancellationToken) if (IsReady) return true; + // Reset any stale transport state, then spawn the LuaLS process and attach the read loops. ThrowIfDisposed(allowDisposed: false); ResetProcessState(); @@ -142,6 +186,7 @@ public async Task StartAsync(CancellationToken cancellationToken) _stderrLoopTask = Task.Run(ReadStandardErrorLoopAsync, CancellationToken.None); _diagnosticsPumpTask ??= Task.Run(PumpDiagnosticsAsync, CancellationToken.None); + // Complete the LSP handshake before marking the client ready for provider requests. using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); @@ -157,6 +202,7 @@ public async Task StartAsync(CancellationToken cancellationToken) } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { + // Caller-driven cancellation should tear down the half-started process so later retries begin cleanly. await DisposeProcessAsync().ConfigureAwait(false); throw; } @@ -174,9 +220,22 @@ public async Task StartAsync(CancellationToken cancellationToken) } } + /// + /// Sends a JSON-RPC notification to the language server. + /// + /// The LSP method name. + /// The notification payload. + /// A token that can cancel the send operation. public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) => SendNotificationCoreAsync(method, parameters, cancellationToken, allowDisposed: false); + /// + /// Sends a JSON-RPC request to the language server and returns the raw response payload. + /// + /// The LSP method name. + /// The request payload. + /// A token that can cancel the request. + /// The raw JSON response payload. public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) => SendRequestCoreAsync(method, parameters, cancellationToken, allowDisposed: false); @@ -543,6 +602,9 @@ private void ThrowIfDisposed(bool allowDisposed) ObjectDisposedException.ThrowIf(_isDisposed, nameof(LuaLanguageServerClient)); } + /// + /// Stops the language-server process, completes pending requests, and releases transport resources. + /// public void Dispose() { if (_isDisposed) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs index 43b4a2b423..0c849ea19d 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs @@ -11,6 +11,16 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; internal sealed partial class LuaLanguageServerIntellisenseProvider { + /// + /// Requests completion items for the specified document position. + /// + /// The local file path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// The optional trigger character that caused completion. + /// A token that can cancel the request. + /// The completion items returned by LuaLS. public async Task> GetCompletionItemsAsync(string filePath, string content, int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) { @@ -34,6 +44,15 @@ public async Task> GetCompletionItemsAsync(stri cancellationToken).ConfigureAwait(false); } + /// + /// Requests hover information for the specified document position. + /// + /// The local file path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The hover payload, or when none exists. public Task GetHoverAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { @@ -45,6 +64,15 @@ public async Task> GetCompletionItemsAsync(stri cancellationToken); } + /// + /// Requests a definition location for the specified document position. + /// + /// The local file path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The definition location, or when none exists. public Task GetDefinitionAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { @@ -56,6 +84,15 @@ public async Task> GetCompletionItemsAsync(stri cancellationToken); } + /// + /// Requests signature-help information for the specified document position. + /// + /// The local file path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The signature-help payload, or when none exists. public Task GetSignatureHelpAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index 7d60cd014d..b71dcab156 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -13,6 +13,9 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Implements the Lua IntelliSense provider by synchronizing editor documents with LuaLS and caching its responses. +/// internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -36,13 +39,32 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell private bool _transientStartupFailureReported; private volatile bool _isDisposed; + /// + /// Gets a value indicating whether IntelliSense requests can currently be served. + /// public bool IsAvailable => !_isDisposed && _client is not null && _consecutiveStartupFailures < HardStartupFailureThreshold; + /// + /// Occurs when diagnostics for a tracked document change. + /// public event Action>? DiagnosticsUpdated; + + /// + /// Occurs when semantic tokens for a tracked document change. + /// public event Action>? SemanticTokensUpdated; + + /// + /// Occurs when repeated language-server startup failures should be surfaced to the user. + /// public event Action? StartupFailed; + /// + /// Initializes a new instance of the class. + /// + /// The root directory of the current Lua script workspace. + /// The LuaLS executable path, or when unavailable. public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string? serverExecutablePath) : this(workspaceRootDirectoryPath, CreateClient(workspaceRootDirectoryPath, serverExecutablePath)) { } @@ -70,6 +92,11 @@ internal LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath () => LuaLanguageServerSettingsFactory.Create(normalizedRoot)); } + /// + /// Gets the latest diagnostics cached for the specified document. + /// + /// The local file path. + /// The cached diagnostics, or an empty list when none are available. public IReadOnlyList GetDiagnostics(string filePath) { if (_isDisposed) @@ -81,6 +108,11 @@ public IReadOnlyList GetDiagnostics(string filePath) return _documents.GetDiagnostics(normalizedFilePath); } + /// + /// Gets the latest semantic tokens cached for the specified document. + /// + /// The local file path. + /// The cached semantic tokens, or an empty list when none are available. public IReadOnlyList GetSemanticTokens(string filePath) { if (_isDisposed) @@ -92,14 +124,28 @@ public IReadOnlyList GetSemanticTokens(string filePath) return _documents.GetSemanticTokens(normalizedFilePath); } + /// + /// Opens a document in the provider and synchronizes its current content with LuaLS. + /// + /// The local file path. + /// The current document content. public void OpenDocument(string filePath, string content) => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, acquireOpenReference: true, refreshSemanticTokens: true, CancellationToken.None), "Document open"); + /// + /// Pushes updated content for a document that is already tracked by the provider. + /// + /// The local file path. + /// The updated document content. public void UpdateDocument(string filePath, string content) => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, acquireOpenReference: false, refreshSemanticTokens: true, CancellationToken.None), "Document change"); + /// + /// Closes a tracked document and releases its server-side state when the last open reference disappears. + /// + /// The local file path. public void CloseDocument(string filePath) { if (_isDisposed || _client is null || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) @@ -113,6 +159,7 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) if (_client is null || _consecutiveStartupFailures >= HardStartupFailureThreshold) return false; + // Fast path: once the client is healthy, keep the workspace watcher alive and avoid taking the startup lock. if (_startupSucceeded && _client.IsReady) { EnsureWorkspaceFileWatcherStarted(); @@ -125,6 +172,7 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) { IReadOnlyList documentsToReopen = []; + // Re-check state after taking the lock so concurrent callers share the same restart/startup work. if (_consecutiveStartupFailures >= HardStartupFailureThreshold) return false; @@ -140,6 +188,7 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) documentsToReopen = _documents.PrepareForRestart(); } + // Start the transport, then replay tracked documents when this is a restart rather than a cold start. _startupSucceeded = await _client.StartAsync(cancellationToken).ConfigureAwait(false); if (_startupSucceeded && documentsToReopen.Count > 0) @@ -159,6 +208,7 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) } else { + // Record repeated failures so IntelliSense eventually stops advertising availability until restart. _consecutiveStartupFailures++; bool isPermanentFailure = _consecutiveStartupFailures >= HardStartupFailureThreshold; @@ -202,6 +252,7 @@ private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, Canc if (_client is null || _isDisposed || batch.Count == 0) return; + // Normalize every path once, drop invalid entries, and track whether any change affects LuaLS configuration. var changes = new List(batch.Count); bool shouldRefreshConfiguration = false; @@ -224,6 +275,7 @@ private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, Canc try { + // Configuration-affecting files must refresh settings before the watched-files notification lands. if (shouldRefreshConfiguration) { await _client.SendNotificationAsync("workspace/didChangeConfiguration", @@ -292,6 +344,9 @@ private void ReportStartupFailure(bool isPermanentFailure) } } + /// + /// Releases the language-server client, workspace watcher, and any in-flight semantic-token requests. + /// public void Dispose() { if (_isDisposed) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs index f7ad81e540..5437ab7f01 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs @@ -6,6 +6,9 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Normalizes local paths and file URIs so LuaLS and TombIDE use a consistent document identity. +/// internal static class LuaLanguageServerPathHelper { /// @@ -30,6 +33,11 @@ public static string NormalizeLocalPath(string filePath) return Path.GetFullPath(sanitizedFilePath); } + /// + /// Normalizes a file URI into the absolute local-path form used by the language server client. + /// + /// The file URI to normalize. + /// The normalized absolute local path. public static string NormalizeLocalPath(Uri uri) { string localPath = uri.LocalPath; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs index 9603edae33..5e33976f14 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs @@ -78,6 +78,11 @@ public CompletionTextAnalysis(string? detail, string? description) public LuaCompletionIconKind? IconKindOverride { get; } } + /// + /// Extracts the completion-item array from either an LSP completion list or a plain array response. + /// + /// The raw completion response payload. + /// The cloned completion-item elements. public static IReadOnlyList ExtractCompletionItems(JsonElement response) { JsonElement itemsElement = response; @@ -96,6 +101,12 @@ public static IReadOnlyList ExtractCompletionItems(JsonElement resp return itemElements; } + /// + /// Parses a sequence of raw completion items into editor completion entries. + /// + /// The raw completion-item payloads. + /// Builds an optional lazy-resolve callback for each item. + /// The parsed completion items. public static IReadOnlyList ParseCompletionItems(IEnumerable itemElements, Func>?>? resolveFactory = null) { @@ -126,6 +137,13 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< return items; } + /// + /// Parses a single raw LSP completion item into a . + /// + /// The raw completion-item payload. + /// The zero-based response index used for priority weighting. + /// An optional lazy-resolve callback. + /// The parsed completion item, or when the payload is invalid. public static LuaCompletionItem? ParseCompletionItem(JsonElement itemElement, int itemIndex, Func>? resolveAsync = null) { diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs index 56b13566a0..e043e46ad5 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs @@ -12,15 +12,32 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; /// `data` array (preferred when it is cheaper than a delta), or it returned a list of `edits` that /// should be applied to the client-side cached integer stream. /// +/// The result id that can seed the next delta request. +/// The full semantic-token integer stream, when provided. +/// The incremental edits, when provided instead of . internal readonly record struct LuaSemanticTokensDeltaResponse( string? ResultId, int[]? Data, IReadOnlyList? Edits); +/// +/// Represents a single edit against a cached semantic-token integer stream. +/// +/// The zero-based start offset within the integer stream. +/// The number of integers to remove. +/// The replacement integers to insert. internal readonly record struct LuaSemanticTokensEdit(int Start, int DeleteCount, int[] Data); +/// +/// Parses LuaLS semantic-token delta responses and applies them to the cached token stream. +/// internal static class LuaLanguageServerSemanticTokensDeltaParser { + /// + /// Parses a semantic-token response that may contain either a full token stream or incremental edits. + /// + /// The raw JSON response payload. + /// The parsed semantic-token delta response. public static LuaSemanticTokensDeltaResponse Parse(JsonElement response) { string? resultId = response.TryGetProperty("resultId", out JsonElement resultIdElement) @@ -139,6 +156,14 @@ internal static class LuaLanguageServerSemanticTokensDecoder { private static readonly IReadOnlyList EmptyModifiers = []; + /// + /// Decodes a raw semantic-token integer stream into the typed token objects expected by the editor. + /// + /// The raw LSP semantic-token integer stream. + /// The document snapshot associated with the token stream. + /// The semantic token types advertised by the server. + /// The semantic token modifiers advertised by the server. + /// The decoded semantic tokens. public static IReadOnlyList Decode(int[] data, LuaDocumentSnapshot? document, IReadOnlyList? tokenTypes, IReadOnlyList? tokenModifiers) { diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs index 6b061471be..df8318937d 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs @@ -2,4 +2,9 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Describes a Lua language server startup failure that should be surfaced to the UI. +/// +/// The user-facing failure message. +/// Whether IntelliSense is disabled until TombIDE restarts. internal readonly record struct LuaLanguageServerStartupFailure(string Message, bool IsPersistent); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs index d347061ff1..1e9095c392 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs @@ -22,6 +22,10 @@ internal static class LuaProcessJobObject private static IntPtr _jobHandle = IntPtr.Zero; private static bool _initializationFailed; + /// + /// Attempts to assign the supplied process to the shared kill-on-close Windows job object. + /// + /// The process to attach. public static void TryAssignProcess(Process process) { if (process is null) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs index d7969a55c8..71f8f39b39 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs @@ -5,9 +5,36 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; -internal sealed class LuaPublishedDiagnostics(string filePath, IReadOnlyList diagnostics, int version) +/// +/// Represents a diagnostics payload published by LuaLS for a specific document version. +/// +internal sealed class LuaPublishedDiagnostics { - public string FilePath { get; } = filePath; - public IReadOnlyList Diagnostics { get; } = diagnostics ?? []; - public int Version { get; } = version; + /// + /// Initializes a new instance of the class. + /// + /// The normalized file path associated with the diagnostics. + /// The parsed diagnostics for that file. + /// The synchronized document version that produced the diagnostics. + public LuaPublishedDiagnostics(string filePath, IReadOnlyList diagnostics, int version) + { + FilePath = filePath; + Diagnostics = diagnostics ?? []; + Version = version; + } + + /// + /// Gets the normalized file path associated with the diagnostics. + /// + public string FilePath { get; } + + /// + /// Gets the parsed diagnostics payload. + /// + public IReadOnlyList Diagnostics { get; } + + /// + /// Gets the synchronized document version that produced the diagnostics. + /// + public int Version { get; } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs index 8e366c5481..d31e80d1ae 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs @@ -2,9 +2,23 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Describes the text-document synchronization mode negotiated with LuaLS. +/// internal enum LuaTextDocumentSyncKind { + /// + /// No document synchronization is supported. + /// None = 0, + + /// + /// Each change sends the full document content. + /// Full = 1, + + /// + /// Each change sends an incremental range edit. + /// Incremental = 2 } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs index cee361cd51..2ff7f7d142 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs @@ -34,12 +34,21 @@ internal sealed class LuaWorkspaceFileWatcher : IDisposable private Timer? _debounceTimer; private volatile bool _isDisposed; + /// + /// Initializes a new instance of the class. + /// + /// The workspace root directory to watch. + /// The callback that forwards coalesced changes to LuaLS. public LuaWorkspaceFileWatcher(string workspaceRootDirectoryPath, Func dispatchAsync) { _workspaceRootDirectoryPath = workspaceRootDirectoryPath; _dispatchAsync = dispatchAsync; } + /// + /// Starts watching the configured workspace for external file changes. + /// + /// when the watcher is running; otherwise, . public bool Start() { if (_isDisposed || _luaWatcher is not null) @@ -159,6 +168,9 @@ private async Task DispatchPendingChangesAsync() } } + /// + /// Releases all native file-system watchers and pending dispatch resources. + /// public void Dispose() { if (_isDisposed) @@ -193,19 +205,48 @@ private static void TryDispose(IDisposable? disposable, string resourceName) } } +/// +/// Identifies the file-system change kind reported to LuaLS. +/// internal enum FileChangeKind { + /// + /// A file or directory was created. + /// Created = 1, + + /// + /// A file or directory changed in place. + /// Changed = 2, + + /// + /// A file or directory was deleted. + /// Deleted = 3 } +/// +/// Represents a coalesced batch of workspace file changes ready to forward to LuaLS. +/// internal sealed class FileChangeBatch { private readonly List<(string Path, FileChangeKind Kind)> _entries = []; + /// + /// Gets the number of coalesced entries in the batch. + /// public int Count => _entries.Count; + + /// + /// Gets the coalesced file-change entries. + /// public IReadOnlyList<(string Path, FileChangeKind Kind)> Entries => _entries; + /// + /// Adds a file-change entry to the batch. + /// + /// The changed local path. + /// The coalesced change kind. public void Add(string path, FileChangeKind kind) => _entries.Add((path, kind)); } diff --git a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs index a5eaf36b74..0cfb613e7c 100644 --- a/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs +++ b/TombLib/TombLib.Scripting.Lua/Highlighting/LuaSemanticTokensColorizer.cs @@ -9,6 +9,9 @@ namespace TombLib.Scripting.Lua.Highlighting; +/// +/// Applies Lua semantic-token styling on top of the editor's baseline syntax highlighting. +/// internal sealed class LuaSemanticTokensColorizer : DocumentColorizingTransformer { private static readonly TextDecorationCollection DeprecatedDecorations = CreateTextDecorations(TextDecorations.Strikethrough); @@ -25,12 +28,21 @@ internal sealed class LuaSemanticTokensColorizer : DocumentColorizingTransformer private IReadOnlyDictionary> _tokensByLine = EmptyTokensByLine; + /// + /// Initializes a new instance of the class. + /// + /// The text view that will be redrawn when semantic styles change. + /// The active Lua theme brush set. public LuaSemanticTokensColorizer(TextView textView, LuaThemeBrushSet themeBrushSet) { _textView = textView; _themeBrushSet = themeBrushSet; } + /// + /// Rebuilds the styled semantic-token cache for a new theme and redraws the text view. + /// + /// The new active theme brush set. public void UpdateTheme(LuaThemeBrushSet themeBrushSet) { _themeBrushSet = themeBrushSet; @@ -38,6 +50,10 @@ public void UpdateTheme(LuaThemeBrushSet themeBrushSet) _textView.Redraw(); } + /// + /// Replaces the semantic tokens currently applied to the text view. + /// + /// The semantic tokens to render. public void SetTokens(IReadOnlyList tokens) { if (tokens is null || tokens.Count == 0) @@ -51,6 +67,9 @@ public void SetTokens(IReadOnlyList tokens) _textView.Redraw(); } + /// + /// Removes all semantic-token styling from the text view. + /// public void ClearTokens() { if (_tokensByLine.Count == 0 && _rawTokens.Count == 0) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index ce39244bb5..6ffe94f30b 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -78,6 +78,7 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) try { + // Validate the request context up front, then dismiss competing transient UI before asking LuaLS. if (!IsIntellisenseAvailable()) return; @@ -99,6 +100,7 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) return; } + // Materialize the provider response into AvalonEdit completion rows using the current theme. var completionDataItems = new LuaCompletionData[items.Count]; var brushSet = GetThemeBrushSet(); @@ -108,6 +110,7 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) return; + // Recreate the popup from scratch so stale selection and tooltip state never leaks between requests. CloseCompletionWindow(); InitializeLuaCompletionWindow(); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index 57db0ea936..c2e0017651 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -15,6 +15,9 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Adapts a to AvalonEdit's completion-item UI contract. +/// internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChanged { private const double DescriptionMaxWidth = 540.0; @@ -34,6 +37,11 @@ internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChange private object? _cachedDescription; private Task? _resolveTask; + /// + /// Initializes a new instance of the class. + /// + /// The completion item being adapted. + /// The theme brushes used to render the item. public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet) { _item = item ?? throw new ArgumentNullException(nameof(item)); @@ -41,15 +49,44 @@ public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet) _displayDetail = FlattenSingleLineText(_item.Detail); } + /// + /// Occurs when a bindable completion-property value changes. + /// public event PropertyChangedEventHandler? PropertyChanged; + /// + /// Gets the icon image shown for the completion item. + /// public ImageSource Image => LuaCompletionIconFactory.GetIcon(_item.IconKind, _brushSet); + + /// + /// Gets the text used for filtering and matching. + /// public string Text => _item.FilterText; + + /// + /// Gets the primary label shown in the completion list. + /// public string DisplayText => _item.Label; + + /// + /// Gets the optional secondary detail shown inline in the completion list. + /// public string? DisplayDetail => _displayDetail; + + /// + /// Gets the visibility for the inline detail label. + /// public Visibility DetailVisibility => string.IsNullOrEmpty(_displayDetail) ? Visibility.Collapsed : Visibility.Visible; + + /// + /// Gets the content object used by AvalonEdit for the completion row. + /// public object Content => DisplayText; + /// + /// Gets the tooltip content for the completion item. + /// public object? Description { get @@ -61,12 +98,30 @@ public object? Description } } + /// + /// Gets the sort priority used by the completion list. + /// public double Priority => _item.Priority; + + /// + /// Gets a value indicating whether this item supports lazy resolve for richer detail. + /// public bool CanResolve => _item.CanResolve; + /// + /// Inserts the completion text into the editor. + /// + /// The target text area. + /// The segment to replace. + /// The insertion request context. public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) => textArea.Document.Replace(completionSegment, _item.InsertText); + /// + /// Resolves and returns the tooltip content for the completion item. + /// + /// A token that can cancel the lazy resolve request. + /// The tooltip content, or when no detail is available. public async Task GetDescriptionAsync(CancellationToken cancellationToken = default) { if (!CanResolve) diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs index a3729ec28e..f8a9a023a1 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionIconFactory.cs @@ -5,10 +5,19 @@ namespace TombLib.Scripting.Lua.Objects; // Geometry paths below are vendored from microsoft/vscode-codicons under the MIT license. +/// +/// Creates themed completion icons from the vendored Codicon geometry set. +/// internal static class LuaCompletionIconFactory { private static readonly ConcurrentDictionary Cache = new(); + /// + /// Gets the themed icon image for the supplied completion kind. + /// + /// The completion icon kind. + /// The brush set used to color the icon. + /// A cached frozen image for the requested icon. public static ImageSource GetIcon(LuaCompletionIconKind kind, LuaThemeBrushSet brushSet) => Cache.GetOrAdd(brushSet.ThemeName + ":" + kind, _ => CreateIcon(kind, brushSet)); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs index 68e1044b8a..7cab5d7392 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionWindowStyle.cs @@ -7,10 +7,18 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Applies the Lua-specific visual styling for AvalonEdit completion popups. +/// internal static class LuaCompletionWindowStyle { private static readonly Style ItemContainerStyle = CreateItemContainerStyle(); + /// + /// Applies the Lua completion-list styling to the supplied completion window. + /// + /// The completion window to style. + /// The theme brushes used by the completion UI. public static void Apply(CompletionWindow window, LuaThemeBrushSet brushSet) { if (window is null) diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs index d63269c3db..3643b6de92 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaEditorColorPalette.cs @@ -5,8 +5,16 @@ namespace TombLib.Scripting.Lua.Resources; +/// +/// Builds the frozen brush palette used by the Lua editor from a resolved theme definition. +/// internal static class LuaEditorColorPalette { + /// + /// Creates the editor brush set for the supplied Lua theme. + /// + /// The theme to materialize into brushes. + /// A frozen brush set ready for use by the editor UI. public static LuaThemeBrushSet Create(LuaTheme theme) { LuaTheme effectiveTheme = (theme ?? new LuaTheme()).Normalize(ConfigurationDefaults.SelectedThemeName); diff --git a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs index a4b23d7667..101f279415 100644 --- a/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs +++ b/TombLib/TombLib.Scripting.Lua/Resources/LuaThemeBrushSet.cs @@ -24,21 +24,84 @@ internal sealed class LuaThemeBrushSet( SolidColorBrush signatureActiveParam, SolidColorBrush signatureForeground) { + /// + /// Gets the canonical name of the theme that produced this brush set. + /// public string ThemeName { get; } = themeName; + + /// + /// Gets the editor background brush. + /// public SolidColorBrush EditorBackground { get; } = editorBackground; + + /// + /// Gets the editor foreground brush. + /// public SolidColorBrush EditorForeground { get; } = editorForeground; + + /// + /// Gets the muted text brush used for secondary completion details and similar metadata. + /// public SolidColorBrush MutedTextBrush { get; } = mutedText; + + /// + /// Gets the fallback brush used for uncategorized symbols. + /// public SolidColorBrush MiscBrush { get; } = misc; + + /// + /// Gets the brush used for methods and functions. + /// public SolidColorBrush MethodBrush { get; } = method; + + /// + /// Gets the brush used for variables and parameters. + /// public SolidColorBrush VariableBrush { get; } = variable; + + /// + /// Gets the brush used for properties and fields. + /// public SolidColorBrush PropertyBrush { get; } = property; + + /// + /// Gets the brush used for types and namespaces. + /// public SolidColorBrush TypeBrush { get; } = type; + + /// + /// Gets the brush used for keywords. + /// public SolidColorBrush KeywordBrush { get; } = keyword; + + /// + /// Gets the brush used for language-defined constants. + /// public SolidColorBrush LanguageConstantBrush { get; } = languageConstant; + + /// + /// Gets the brush used for user-defined constants and enum members. + /// public SolidColorBrush ConstantBrush { get; } = constant; + + /// + /// Gets the brush used for file and folder completion items. + /// public SolidColorBrush FileBrush { get; } = file; + + /// + /// Gets the brush used for signature-help parameter documentation. + /// public SolidColorBrush SignatureParamDocForeground { get; } = signatureParamDoc; + + /// + /// Gets the brush used to emphasize the active signature parameter. + /// public SolidColorBrush SignatureActiveParamForeground { get; } = signatureActiveParam; + + /// + /// Gets the base brush used for signature labels. + /// public SolidColorBrush SignatureForeground { get; } = signatureForeground; /// diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs index da22510783..ee12db69c8 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs @@ -4,18 +4,30 @@ namespace TombLib.Scripting.Lua.Utils; +/// +/// Caches per-line Lua parser continuation state so comment and long-string checks stay fast after edits. +/// internal sealed class LuaDocumentLineParserStateCache { private readonly object _syncRoot = new(); private readonly TextDocument _document; private readonly List _cachedLineStartStates = []; + /// + /// Initializes a new instance of the class. + /// + /// The document whose line-start parser state should be cached. public LuaDocumentLineParserStateCache(TextDocument document) { _document = document ?? throw new ArgumentNullException(nameof(document)); _document.Changed += Document_Changed; } + /// + /// Gets the parser continuation state that applies at the start of the specified one-based line. + /// + /// The one-based document line number. + /// The cached or computed line-start parser state. public LuaLineParserState GetLineStartState(int lineNumber) { if (lineNumber <= 1) diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs index 6a53cc1268..14db9db848 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -9,8 +9,19 @@ namespace TombLib.Scripting.Lua.Utils; /// internal enum LuaLineParserStateKind { + /// + /// The parser is not inside a multi-line Lua construct. + /// None, + + /// + /// The parser is inside a long-bracket string literal. + /// LongString, + + /// + /// The parser is inside a long-bracket comment. + /// LongComment } @@ -19,7 +30,14 @@ internal enum LuaLineParserStateKind /// internal readonly struct LuaLineParserState(LuaLineParserStateKind kind, int longBracketEqualsCount) { + /// + /// Gets the long-block parser mode that should continue onto the next line. + /// public LuaLineParserStateKind Kind { get; } = kind; + + /// + /// Gets the number of = characters used by the active long-bracket delimiter. + /// public int LongBracketEqualsCount { get; } = longBracketEqualsCount; } From 9655118fad5c042af75d8ae7bd11f35cfe8662a4 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Wed, 22 Apr 2026 23:47:50 +0100 Subject: [PATCH 24/34] Fix desync issues --- .../LuaIntellisenseDocumentManager.cs | 20 +++++++++ ...ageServerIntellisenseProvider.Documents.cs | 11 +++++ ...LanguageServerIntellisenseProviderTests.cs | 41 +++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs index 7c05bda5d9..ab952a366f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs @@ -295,6 +295,26 @@ public void StoreSemanticTokensDeltaState(string filePath, string? resultId, int } } + /// + /// Marks the specified document as needing a fresh server-side open/sync before incremental updates can resume. + /// + /// The normalized file path. + /// when the document was found and invalidated; otherwise, . + public bool InvalidateServerSynchronization(string filePath) + { + lock (_syncRoot) + { + if (!_documents.TryGetValue(filePath, out DocumentState? state)) + return false; + + state.IsOpen = false; + state.SemanticTokensVersion = 0; + state.SemanticTokensResultId = null; + state.SemanticTokensData = null; + return true; + } + } + private static bool IsStaleVersion(int currentVersion, int incomingVersion) => incomingVersion > 0 && currentVersion > 0 && incomingVersion < currentVersion; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs index eddad4aaad..1e605e8370 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs @@ -92,14 +92,25 @@ private async Task SynchronizeDocumentAsync(string filePath, string conten } catch (IOException) { + InvalidateDocumentSynchronization(filePath); return false; } catch (ObjectDisposedException) { + if (!_isDisposed) + InvalidateDocumentSynchronization(filePath); + return false; } } + private void InvalidateDocumentSynchronization(string filePath) + { + _startupSucceeded = false; + _documents.InvalidateServerSynchronization(filePath); + CancelSemanticTokenRequest(filePath); + } + private async Task<(bool Success, LuaDocumentSnapshot? Document)> SynchronizeDocumentCoreAsync( string filePath, string content, diff --git a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs index 2f4bf3e382..2df61f3a54 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs @@ -244,6 +244,38 @@ public async Task UpdateDocument_WaitsForEarlierOpenNotificationToFinish() client.GetSentMethodNames()); } + [TestMethod] + public async Task GetHoverAsync_ReopensDocumentAfterIncrementalChangeTransportFailure() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + ThrowIOExceptionOnNextDidChange = true + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + await provider.GetHoverAsync(filePath, "local value = 1", 0, 0); + provider.UpdateDocument(filePath, "local value = 2"); + + Assert.IsTrue(await client.WaitForNotificationAsync("textDocument/didChange", TimeSpan.FromSeconds(1))); + + await provider.GetHoverAsync(filePath, "local value = 2", 0, 0); + + CollectionAssert.AreEqual( + new[] + { + "textDocument/didOpen", + "textDocument/hover", + "textDocument/didChange", + "textDocument/didOpen", + "textDocument/hover" + }, + client.GetSentMethodNames()); + } + [TestMethod] public async Task CloseDocument_WaitsForQueuedOpenNotificationToFinish() { @@ -393,6 +425,7 @@ private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient public bool SupportsCompletionResolve { get; set; } public bool SupportsSemanticTokensDelta => false; public int StartCallCount { get; private set; } + public bool ThrowIOExceptionOnNextDidChange { get; set; } public event Action? DiagnosticsPublished; @@ -411,8 +444,16 @@ public Task SendNotificationAsync(string method, object parameters, Cancellation _sentNotifications.Add((method, JsonSerializer.SerializeToElement(parameters))); if (method == "textDocument/didChange") + { _changeNotificationObserved.TrySetResult(true); + if (ThrowIOExceptionOnNextDidChange) + { + ThrowIOExceptionOnNextDidChange = false; + throw new IOException("Simulated didChange transport failure."); + } + } + if (method == "textDocument/didClose") _closeNotificationObserved.TrySetResult(true); From b8f0d4c8129aac11ba80889ab3738fac78f85eb6 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Wed, 22 Apr 2026 23:56:05 +0100 Subject: [PATCH 25/34] Add debounce to prevent constant exceptions --- .../LuaEditor.Completion.cs | 70 +++++++++++++++---- .../LuaEditor.Intellisense.cs | 19 ++++- 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index 6ffe94f30b..01c2d8e45a 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -20,6 +20,7 @@ namespace TombLib.Scripting.Lua; public sealed partial class LuaEditor { + private const double CompletionRequestDebounceDelayInMilliseconds = 120.0; private const int CompletionWindowMinWidth = 420; private const int CompletionWindowMaxWidth = 920; private const int CompletionWindowHeight = 320; @@ -45,12 +46,26 @@ public sealed partial class LuaEditor private static FieldInfo? CompletionToolTipField => CompletionToolTipFieldAccessor.Value; private CancellationTokenSource? _completionCancellationTokenSource; - private CancellationTokenSource? _completionToolTipCancellationTokenSource; + private readonly DispatcherTimer _completionRequestTimer = new(); + private readonly DispatcherTimer _completionToolTipUpdateTimer = new(); private int _completionRequestToken; private int _completionToolTipUpdateToken; + private ToolTip? _pendingCompletionToolTip; + + private void InitializeCompletionScheduling() + { + _completionRequestTimer.Interval = TimeSpan.FromMilliseconds(CompletionRequestDebounceDelayInMilliseconds); + _completionRequestTimer.Tick -= CompletionRequestTimer_Tick; + _completionRequestTimer.Tick += CompletionRequestTimer_Tick; + + _completionToolTipUpdateTimer.Interval = TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds); + _completionToolTipUpdateTimer.Tick -= CompletionToolTipUpdateTimer_Tick; + _completionToolTipUpdateTimer.Tick += CompletionToolTipUpdateTimer_Tick; + } private void CloseCompletionWindow() { + CancelPendingCompletionRequest(); CancelCompletionToolTipUpdate(); if (_completionWindow is null) @@ -71,6 +86,28 @@ private void InitializeLuaCompletionWindow() MakeCompletionWindowNonActivatable(); } + private void ScheduleCompletionRequest() + { + _completionRequestTimer.Stop(); + _completionRequestTimer.Start(); + } + + private void CancelPendingCompletionRequest() + => _completionRequestTimer.Stop(); + + private async void CompletionRequestTimer_Tick(object? sender, EventArgs e) + { + _completionRequestTimer.Stop(); + + if (!AutocompleteEnabled || !IsIntellisenseAvailable()) + return; + + if (!LuaEditorInteractionRules.IsValidAutocompleteContext(Document, CaretOffset, triggerCharacter: null)) + return; + + await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); + } + private async Task RequestCompletionAsync(int offset, char? triggerCharacter) { CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionCancellationTokenSource); @@ -172,15 +209,23 @@ private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseBu private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) { - int updateToken = ++_completionToolTipUpdateToken; - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionToolTipCancellationTokenSource); + _pendingCompletionToolTip = tooltip; + _completionToolTipUpdateToken++; + _completionToolTipUpdateTimer.Stop(); + _completionToolTipUpdateTimer.Start(); + } + + private async void CompletionToolTipUpdateTimer_Tick(object? sender, EventArgs e) + { + _completionToolTipUpdateTimer.Stop(); - Dispatcher.BeginInvoke( - new Action(() => _ = UpdateCompletionTooltipAsync(tooltip, updateToken, cancellationToken)), - DispatcherPriority.Background); + if (_pendingCompletionToolTip is not ToolTip tooltip) + return; + + await UpdateCompletionTooltipAsync(tooltip, _completionToolTipUpdateToken).ConfigureAwait(true); } - private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken, CancellationToken cancellationToken) + private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken) { if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) return; @@ -202,12 +247,10 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) { - await Task.Delay(TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds), cancellationToken).ConfigureAwait(true); - if (updateToken != _completionToolTipUpdateToken) return; - object? resolvedDescription = await luaCompletionData.GetDescriptionAsync(cancellationToken).ConfigureAwait(true); + object? resolvedDescription = await luaCompletionData.GetDescriptionAsync().ConfigureAwait(true); if (updateToken != _completionToolTipUpdateToken) return; @@ -225,10 +268,6 @@ private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken tooltip.IsOpen = false; } } - catch (OperationCanceledException) - { - // Newer selection or close superseded this tooltip update. - } catch (Exception exception) { tooltip.IsOpen = false; @@ -305,7 +344,8 @@ private static void ApplyCompletionToolTipContent(ToolTip tooltip, object conten private void CancelCompletionToolTipUpdate() { _completionToolTipUpdateToken++; - _completionToolTipCancellationTokenSource?.Cancel(); + _pendingCompletionToolTip = null; + _completionToolTipUpdateTimer.Stop(); } private void ScheduleCloseIfEmpty() diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index 37019dc710..22498b1aff 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -14,6 +14,8 @@ public sealed partial class LuaEditor private void BindLuaIntellisenseEvents() { + InitializeCompletionScheduling(); + IsKeyboardFocusWithinChanged += LuaEditor_IsKeyboardFocusWithinChanged; Loaded += LuaEditor_Loaded; TextArea.TextEntering += TextArea_TextEntering; @@ -63,6 +65,7 @@ private void LuaEditor_Unloaded(object? sender, RoutedEventArgs e) _textMateHighlighting?.Dispose(); _textMateHighlighting = null; + CancelPendingCompletionRequest(); CancelAndDispose(ref _hoverCancellationTokenSource); CancelAndDispose(ref _completionCancellationTokenSource); @@ -91,6 +94,7 @@ private async void TextArea_TextEntering(object? sender, TextCompositionEventArg if (e.Text == " " && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) { e.Handled = true; + CancelPendingCompletionRequest(); if (LuaEditorInteractionRules.IsValidManualCompletionContext(Document, CaretOffset)) await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); @@ -104,6 +108,7 @@ private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs if (e.Text == "(" || e.Text == ",") { + CancelPendingCompletionRequest(); CloseCompletionWindow(); await RequestSignatureHelpAsync(CaretOffset).ConfigureAwait(true); return; @@ -111,6 +116,7 @@ private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs if (e.Text == ")") { + CancelPendingCompletionRequest(); CloseCompletionWindow(); DismissSignatureHelp(); return; @@ -118,6 +124,8 @@ private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs if (_completionWindow is not null) { + CancelPendingCompletionRequest(); + if (!ShouldKeepCompletionWindowOpen(e.Text)) { CloseCompletionWindow(); @@ -135,7 +143,15 @@ private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs if (TryGetCompletionTrigger(e.Text, out char? triggerCharacter) && LuaEditorInteractionRules.IsValidAutocompleteContext(Document, CaretOffset, triggerCharacter)) { - await RequestCompletionAsync(CaretOffset, triggerCharacter).ConfigureAwait(true); + if (triggerCharacter is null) + { + ScheduleCompletionRequest(); + } + else + { + CancelPendingCompletionRequest(); + await RequestCompletionAsync(CaretOffset, triggerCharacter).ConfigureAwait(true); + } } } @@ -166,6 +182,7 @@ private static bool ShouldKeepCompletionWindowOpen(string? inputText) private void DismissTransientToolTips() { + CancelPendingCompletionRequest(); CancelAndDispose(ref _hoverCancellationTokenSource); _hoverRequestToken++; DismissSignatureHelp(); From 19b7b3c705d057917080ce73a3cf66fc16a81a79 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Fri, 8 May 2026 19:46:38 +0100 Subject: [PATCH 26/34] Address Copilot comments --- .../Utils/LuaDocumentLineParserStateCache.cs | 14 ++++++++-- .../Workers/ErrorDetectionWorker.cs | 28 +++++++++++-------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs index ee12db69c8..9ede3feb86 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaDocumentLineParserStateCache.cs @@ -35,9 +35,14 @@ public LuaLineParserState GetLineStartState(int lineNumber) lock (_syncRoot) { + if (_document.LineCount == 0) + return default; + + int targetLineNumber = Math.Max(1, Math.Min(lineNumber, _document.LineCount)); + EnsureFirstLineStateCached(); - EnsureStatesCachedThrough(lineNumber); - return _cachedLineStartStates[lineNumber - 1]; + EnsureStatesCachedThrough(targetLineNumber); + return _cachedLineStartStates[targetLineNumber - 1]; } } @@ -67,7 +72,10 @@ private void EnsureFirstLineStateCached() private void EnsureStatesCachedThrough(int lineNumber) { - int targetLineNumber = Math.Max(1, Math.Min(lineNumber, _document.LineCount)); + int targetLineNumber = Math.Min(lineNumber, _document.LineCount); + + if (targetLineNumber <= 0) + return; while (_cachedLineStartStates.Count < targetLineNumber) { diff --git a/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs b/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs index bebc8be6db..0ad6d7f3cc 100644 --- a/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs +++ b/TombLib/TombLib.Scripting/Workers/ErrorDetectionWorker.cs @@ -1,4 +1,6 @@ -using System; +#nullable enable + +using System; using System.ComponentModel; using System.Windows.Threading; using TombLib.Scripting.Interfaces; @@ -10,7 +12,7 @@ public class ErrorDetectionWorker : BackgroundWorker { #region Properties - public IErrorDetector ErrorDetector { get; set; } + public IErrorDetector? ErrorDetector { get; set; } public TimeSpan IdleDelayInterval { @@ -24,7 +26,7 @@ public TimeSpan IdleDelayInterval #region Fields - private DispatcherTimer _errorUpdateTimer = new(); + private readonly DispatcherTimer _errorUpdateTimer = new(); private string _editorContent = string.Empty; @@ -34,9 +36,9 @@ public TimeSpan IdleDelayInterval public ErrorDetectionWorker() : this(null, new Version(0, 0)) { } - public ErrorDetectionWorker(IErrorDetector errorDetector, Version engineVersion) : this(errorDetector, engineVersion, new TimeSpan(500)) + public ErrorDetectionWorker(IErrorDetector? errorDetector, Version engineVersion) : this(errorDetector, engineVersion, new TimeSpan(500)) { } - public ErrorDetectionWorker(IErrorDetector errorDetector, Version engineVersion, TimeSpan idleDelayInterval) + public ErrorDetectionWorker(IErrorDetector? errorDetector, Version engineVersion, TimeSpan idleDelayInterval) { ErrorDetector = errorDetector; IdleDelayInterval = idleDelayInterval; @@ -53,32 +55,34 @@ protected override void OnDoWork(DoWorkEventArgs e) { base.OnDoWork(e); - if (ErrorDetector is null) + IErrorDetector? errorDetector = ErrorDetector; + + if (errorDetector is null) { e.Result = Array.Empty(); return; } string editorContent = e.Argument as string ?? string.Empty; - e.Result = ErrorDetector.FindErrors(editorContent, EngineVersion); + e.Result = errorDetector.FindErrors(editorContent, EngineVersion); } #endregion Override methods #region Public methods - public void RunErrorCheckOnIdle(string editorContent) + public void RunErrorCheckOnIdle(string? editorContent) { if (_errorUpdateTimer.IsEnabled) _errorUpdateTimer.Stop(); - _editorContent = editorContent; + _editorContent = editorContent ?? string.Empty; _errorUpdateTimer.Start(); } - public void CheckForErrorsAsync(string editorContent) + public void CheckForErrorsAsync(string? editorContent) { - if (ErrorDetector == null) + if (ErrorDetector is null) return; base.RunWorkerAsync(editorContent ?? string.Empty); @@ -88,7 +92,7 @@ public void CheckForErrorsAsync(string editorContent) #region Events - private void ErrorUpdateTimer_Tick(object sender, EventArgs e) + private void ErrorUpdateTimer_Tick(object? sender, EventArgs e) { if (!IsBusy) CheckForErrorsAsync(_editorContent); From c15fd5c068f606aa4f5cb6f9d75e92a7d1992246 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 10 May 2026 11:46:25 +0100 Subject: [PATCH 27/34] Actual improvements --- ExternalResources.md | 1 + LuaLS_Production_Readiness_Plan.md | 478 +++++++++++++++++ .../Controls/EditorTabControl.cs | 49 +- .../LuaStudio.Intellisense.cs | 65 ++- .../Objects/DocumentRenamedEventArgs.cs | 16 + .../ILuaLanguageServerClient.cs | 10 + .../LuaDocumentRenameRequest.cs | 11 + .../LuaIntellisenseDocumentManager.cs | 56 +- .../LuaLanguageServerClient.Protocol.cs | 56 +- .../LuaLanguageServerClient.Transport.cs | 107 ++-- .../LuaLanguageServerClient.cs | 285 +++++++---- ...ageServerIntellisenseProvider.Documents.cs | 98 +++- ...uageServerIntellisenseProvider.Requests.cs | 66 ++- ...rverIntellisenseProvider.SemanticTokens.cs | 57 ++- .../LuaLanguageServerIntellisenseProvider.cs | 100 +++- ...LanguageServerResponseParser.Completion.cs | 135 ++++- .../LuaWorkspaceFileWatcher.cs | 104 +++- .../LuaWorkspaceWatcherFailure.cs | 9 + .../TextEditors/ColorSchemes/Lua/Default.xml | 42 ++ .../LuaEditor.Completion.cs | 66 ++- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 3 +- .../LuaEditor.Intellisense.cs | 83 ++- .../LuaEditor.Navigation.cs | 18 +- .../LuaEditor.SignatureHelp.cs | 83 ++- TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 8 +- .../Objects/LuaCompletionData.cs | 126 ++++- .../Objects/LuaCompletionItem.cs | 123 ++++- .../Services/ILuaIntellisenseProvider.cs | 8 + .../TombLib.Scripting.Lua.csproj | 3 + .../Utils/LuaAutoIndentationStrategy.cs | 103 ++++ .../Utils/LuaIndentationStrategy.cs | 342 +++++++++++++ .../Utils/LuaLineParser.cs | 82 +++ .../TombLib.Scripting/Bases/TextEditorBase.cs | 8 +- .../LuaTextMateSyntaxHighlighting.cs | 19 + .../Highlighting/TextMateDocumentLineList.cs | 38 +- .../Properties/AssemblyInfo.cs | 2 + .../Rendering/MarkdownToolTipRenderer.cs | 94 ++-- .../TombLib.Test/LuaCompletionDataTests.cs | 74 +++ .../TombLib.Test/LuaCompletionItemTests.cs | 50 ++ .../LuaEditorIntellisenseStateTests.cs | 309 +++++++++++ .../LuaIndentationStrategyTests.cs | 52 ++ .../LuaLanguageServerClientTests.cs | 96 +++- ...LanguageServerIntellisenseProviderTests.cs | 482 +++++++++++++++++- .../LuaLanguageServerResponseParserTests.cs | 80 +++ TombLib/TombLib.Test/LuaLineParserTests.cs | 8 + .../LuaTextMateSyntaxHighlightingTests.cs | 17 + .../LuaWorkspaceFileWatcherTests.cs | 43 ++ .../MarkdownToolTipRendererTests.cs | 55 ++ .../TombLib.Test/TextMateHighlightingTests.cs | 83 +++ 49 files changed, 3966 insertions(+), 337 deletions(-) create mode 100644 LuaLS_Production_Readiness_Plan.md create mode 100644 TombIDE/TombIDE.ScriptingStudio/Objects/DocumentRenamedEventArgs.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentRenameRequest.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceWatcherFailure.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/LuaAutoIndentationStrategy.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs create mode 100644 TombLib/TombLib.Test/LuaCompletionDataTests.cs create mode 100644 TombLib/TombLib.Test/LuaCompletionItemTests.cs create mode 100644 TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs create mode 100644 TombLib/TombLib.Test/LuaIndentationStrategyTests.cs create mode 100644 TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs create mode 100644 TombLib/TombLib.Test/LuaWorkspaceFileWatcherTests.cs create mode 100644 TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs create mode 100644 TombLib/TombLib.Test/TextMateHighlightingTests.cs diff --git a/ExternalResources.md b/ExternalResources.md index 81a50f0d4c..00646af570 100644 --- a/ExternalResources.md +++ b/ExternalResources.md @@ -17,6 +17,7 @@ A big thank you to all the authors for making their work publicly available and | CH.SipHash | NuGet | 1.0.2 | Public Domain | https://github.com/tanglebones/ch-siphash | | FastColoredTextBox | NuGet | 2.16.21 | LGPLv3 | https://www.codeproject.com/Articles/161871/Fast-Colored-TextBox-for-syntax-highlighting | | System.Drawing.PSD | NuGet | 1.1 | BSD 3-clause | https://github.com/bizzehdee/System.Drawing.PSD | +| Lua Language Server | Bundled zip (`TIDE/LuaLS`) | 3.18.1 | MIT | https://github.com/LuaLS/lua-language-server | ### Main Software Documentation diff --git a/LuaLS_Production_Readiness_Plan.md b/LuaLS_Production_Readiness_Plan.md new file mode 100644 index 0000000000..e99913b3b4 --- /dev/null +++ b/LuaLS_Production_Readiness_Plan.md @@ -0,0 +1,478 @@ +# Lua IntelliSense Production Readiness Plan + +## Scope +This document is a clean-room handoff for the next agent. It re-verifies the current Lua IntelliSense concerns against the codebase as it exists now and turns them into a phased implementation plan. + +Date: 2026-05-09. + +## Executive Summary +The current blocker set is narrower than the original checklist, but a few items are real production-readiness problems and should be treated as the first slice: + +- LuaLS request timeouts do not trigger recovery, so a hung server can leave IntelliSense dead until restart. +- Old transport loops can still interact with the shared pending-request map after restart. +- Save As / external rename do not rebind tracked IntelliSense documents to the new path. +- Completion insertion does not honor LSP `textEdit` replacement semantics. +- Signature help dismissal and refresh are incomplete enough to produce visible UX failures. +- Stale diagnostics and semantic tokens survive normal edits until the delayed sync fires, which explains the shifted underline / stale color complaints better than a pure TextMate failure. + +The Lua indentation complaints are also real, but they belong in the completion / Enter-handling phase rather than the transport phase. + +## Re-Verification Matrix + +### 1. LuaLS Startup, Transport, And Recovery + +#### Concern: repeated request timeouts leave IntelliSense permanently dead. +Verdict: verified blocker. + +Evidence: + +- [SendBoundedRequestAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs#L185) times out after 10 seconds, logs, and returns `default`. +- That path does not mark the client unhealthy, invalidate startup state, or trigger restart. +- Restart today depends on `_client.IsReady` becoming false, which a hung but still-running process will not do. + +#### Concern: a restarted LuaLS receives all currently open documents again. +Verdict: already implemented and worth preserving. + +Evidence: + +- [EnsureStartedAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs#L159) calls `_documents.PrepareForRestart()` and then [ReopenTrackedDocumentsAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs#L102). +- Existing coverage: [GetHoverAsync_ReplaysTrackedDocumentsAfterLanguageServerRestart](TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs#L153). + +#### Concern: stale / old process read loops cannot fail requests belonging to a newer process. +Verdict: verified blocker. + +Evidence: + +- The client keeps one shared `_pendingRequests` map in [LuaLanguageServerClient](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L35). +- Requests are added in [SendRequestCoreAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs#L17). +- Old read loops can still call [FailPendingRequests](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L480) from [ReadLoopAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs#L18) after restart. +- `ResetProcessState()` clears streams and task references, but it does not replace the pending-request store or scope failures to a transport generation. + +#### Concern: disposal of LuaLS hangs on stderr / diagnostic pumps / background loops. +Verdict: not a blocker, but keep an eye on it. + +Evidence: + +- [Dispose](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L559) cancels lifetime, fails pending requests, and waits with [DisposeWaitTimeout](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L21). +- [WaitForBackgroundLoopsAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L506) is timeout-bounded and logs rather than hanging indefinitely. + +### 2. Document Lifetime And Tab Ownership + +#### Concern: Save As / rename must move diagnostics, semantic tokens, hover, completion, and definition to the new path. +Verdict: verified blocker. + +Evidence: + +- [SaveFileAs(TabPage)](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L363) directly changes `editor.FilePath` and saves, but it does not tell IntelliSense to close the old URI and open the new one. +- [RenameDocumentTabPage](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L691) also rewrites `editor.FilePath` only. +- Lua editors are wired through [LuaStudio.Intellisense.cs](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L76), but there is no rename/rekey hook. + +#### Concern: request-only hover / definition / signature documents are closed afterward. +Verdict: not a current UI blocker. + +Evidence: + +- Request paths use `acquireOpenReference: false` in [SendPositionRequestAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs#L145). +- In the actual UI flow, Lua editors are opened through [EditorTabControl_LuaFileOpened](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L76), which already calls `OpenDocument`. +- A non-UI caller could still create a request-only tracked document, but that is not the dominant production path. + +#### Concern: closing a tab while requests are in flight must not update a disposed editor. +Verdict: mixed. + +Evidence: + +- Completion and hover cancel tokens on unload in [LuaEditor_Unloaded](TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs#L60). +- Signature help and definition navigation still lack the same level of stale-result guarding. + +### 3. Stale Async Editor Requests + +#### Concern: stale completion / hover / signature / definition responses should be discarded after edits. +Verdict: partially verified, still missing in important paths. + +Evidence: + +- Completion uses `_completionRequestToken` in [RequestCompletionAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs#L92). +- Hover uses `_hoverRequestToken` in [HandleMouseHover](TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs#L27). +- Signature help in [RequestSignatureHelpAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs#L146) has cancellation only, no request-generation token. +- Definition navigation in [TryNavigateToDefinitionAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs#L55) has no generation/version guard at all. + +### 4. Completion Insertion + +#### Concern: `textEdit.range`, `textEdit.insert`, and `textEdit.replace` must be honored. +Verdict: verified blocker. + +Evidence: + +- [ParseCompletionItem](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs#L145) reads `textEdit.newText` only. +- It ignores `textEdit.range`, `textEdit.insert`, and `textEdit.replace` entirely. +- [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117) always replaces AvalonEdit's `completionSegment`, not an LSP-provided edit range. + +#### Concern: text edits must not apply after the document version changed. +Verdict: verified gap. + +Evidence: + +- `LuaCompletionItem` has no document version or request-generation metadata in [LuaCompletionItem](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs#L10). +- `LuaCompletionData.Complete` has no stale-version guard. + +#### Concern: snippets, `$0`, multiline insertion, and caret placement are correct. +Verdict: not correct if snippet or multiline completion text reaches the editor. + +Evidence: + +- [StripSnippetPlaceholders](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs#L359) strips `$1`, `${1:default}`, and `$0`, but it does not preserve caret intent. +- [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117) inserts plain text only. +- There is no Lua-aware multiline reindent pass anywhere in [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L562) or [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs#L10). + +Important nuance: + +- The client advertises `snippetSupport = false` in [LuaLanguageServerClient](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L280). +- Settings also set `callSnippet = "Disable"` in [LuaLanguageServerSettingsFactory](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs#L34). +- That lowers the frequency of snippet-shaped results, but it does not make the current insertion code correct if LuaLS still emits keyword snippets or multiline `newText`. + +#### Concern: completion-item resolve must preserve insertion text and ranges. +Verdict: future implementation requirement. + +Evidence: + +- Resolve reparses a new `LuaCompletionItem` in [ResolveCompletionItemAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs#L116). +- Once range metadata is added, resolve must merge detail/documentation onto the unresolved insertion metadata rather than replacing it blindly. + +### 5. Lua Enter / Indentation Strategy + +#### Concern: pressing Enter after `then` is missing one extra indent level. +Verdict: verified missing feature. + +Evidence: + +- [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L562) only implements bracket / quote auto-closing. +- There is no Lua-specific Enter handler, indentation strategy, or block-aware newline logic in [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs#L10) or its partials. + +#### Concern: `if ... then ... end` autocomplete puts `end` at the wrong indentation. +Verdict: verified gap for any multiline completion text. + +Evidence: + +- Multiline completion text is inserted verbatim by [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117). +- No reindent or caret-placement normalization exists before or after insertion. + +### 6. Signature Help And Navigation UX + +#### Concern: closing a method with `)` should dismiss signature help. +Verdict: verified UX bug. + +Evidence: + +- Lua dismisses signature help on `)` only in [TextArea_TextEntered](TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs#L104). +- The base editor can consume `)` earlier in [TryPerformElementSkip](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L596) when skipping over an auto-inserted close paren. +- That means the editor can move past `)` without the Lua-specific dismissal path running. + +#### Concern: signature help argument highlighting can desync. +Verdict: verified high-priority issue. + +Evidence: + +- Signature refresh happens on `(`, `,`, Backspace, and Delete only. See [TextArea_TextEntered](TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs#L87) and [TextEditor_KeyDown](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs#L21). +- Normal typing inside an argument list does not refresh signature help. +- Signature help also lacks a request token in [RequestSignatureHelpAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs#L146), so stale responses can repaint older active-parameter state. + +#### Concern: go-to-definition should not act on stale results. +Verdict: verified hardening need. + +Evidence: + +- [TryNavigateToDefinitionAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs#L55) has no generation or version check before invoking `DefinitionNavigationRequested`. + +### 7. Semantic Tokens, Syntax Coloring, And Diagnostic Lag + +#### Concern: quick edits like `local -> locl -> local` break colors, possibly due to autocomplete popup interaction. +Verdict: partially reclassified. + +Verified part: + +- Stale semantic tokens remain visible until the delayed document sync runs, because edits do not immediately clear semantic overlays. +- Lua semantic tokens are updated only after [TextChangedDelayed](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L92), which is driven by the 300 ms timer in [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L185). +- `ClearSemanticTokens()` is called on unload only, not on ordinary edits. See [LuaEditor.SemanticHighlighting](TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs#L16). + +Not directly proven: + +- The TextMate path itself looks change-driven and should retokenize lines through [TextMateDocumentLineList](TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs#L48) and [TextMateColorizingTransformer](TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs#L24). +- There is no strong code evidence that the completion popup itself blocks TextMate recoloring. + +Working conclusion: + +- Treat the reported recolor bug primarily as stale semantic-token / stale overlay behavior until a concrete TextMate-only repro proves otherwise. + +#### Concern: errors should clear immediately on text change because underlines can shift. +Verdict: verified high-priority UX defect. + +Evidence: + +- [TextEditor_TextChanged](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L269) only marks content changed and restarts the delayed timer. +- Diagnostics are not cleared on edit. +- Provider-side diagnostics are refreshed only through [LuaEditor_TextChangedDelayed](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L92). + +#### Concern: semantic-token version association / stale overwrite after rapid edits. +Verdict: normal version gating is present, but stale-visibility still exists. + +Evidence: + +- [TryStoreSemanticTokens](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs#L216) rejects older token versions. +- However, the old tokens remain painted until a newer token set arrives or the editor clears them. + +#### Concern: failed semantic-token delta requests should preserve or clear state intentionally. +Verdict: verified hardening issue. + +Evidence: + +- On delta failure, [DecodeSemanticTokensResponse](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs#L89) can return `previousData` paired with a new `resultId`. +- That is internally inconsistent and should be replaced by a forced full refresh path. + +### 8. TextMate And Highlighting Fallback + +#### Concern: Lua should remain highlighted if TextMate grammar install fails. +Verdict: verified gap in the main editor. + +Evidence: + +- [LuaTextMateSyntaxHighlighting.TryInstall](TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs#L14) returns false when grammar load fails. +- [LuaEditor.UpdateSettings](TombLib/TombLib.Scripting.Lua/LuaEditor.cs#L51) always sets `SyntaxHighlighting = null` after trying TextMate. +- Markdown tooltips do have a fallback in [MarkdownToolTipRenderer](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L309), but the main editor does not. + +### 9. Tooltips, Watcher, Disposal, And Packaging + +#### Concern: tooltip embedded editors can steal focus. +Verdict: worth hardening. + +Evidence: + +- The FlowDocument viewer and hyperlinks are made non-focusable in [MarkdownToolTipRenderer](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L85) and [MarkdownToolTipRenderer](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L218). +- The embedded `TextEditor` created in [CreateCodeBlockElement](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L309) is read-only but not explicitly made non-focusable. + +#### Concern: watcher recovery / disposal safety. +Verdict: watch coverage is good, disposal race is real, recovery behavior is limited. + +Evidence: + +- The watcher covers `*.lua`, `.API`, and `.luarc.*` in [LuaWorkspaceFileWatcher.Start](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs#L43). +- [DispatchPendingChangesAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs#L131) can still be in flight while `Dispose()` disposes `_dispatchGate`. +- `Error` currently logs only; it does not restart or visibly disable the watcher. + +#### Concern: event subscribers throwing exceptions should not starve others. +Verdict: mixed. + +Evidence: + +- Startup failures are protected in [ReportStartupFailure](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs#L320). +- The client diagnostics pump isolates handler exceptions in [PumpDiagnosticsAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs#L301). +- Provider fan-out for [DiagnosticsUpdated](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs#L271) and [SemanticTokensUpdated](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs#L59) is not wrapped. + +#### Concern: LuaLS attribution when bundled. +Verdict: verified documentation gap, not installer blocker. + +Evidence: + +- Bundling is build-backed in [TombIDE.Shared.csproj](TombIDE/TombIDE.Shared/TombIDE.Shared.csproj#L9). +- [ExternalResources.md](ExternalResources.md) does not currently list LuaLS. + +## Phase Plan + +### Phase 1: Transport Resilience Blockers +Goal: make restarts safe and automatic when LuaLS becomes unhealthy. + +Tasks: + +- Add a transport generation / session concept in [LuaLanguageServerClient](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs). +- Scope pending requests and read-loop failure propagation to that generation. +- Ensure an old read loop or process exit cannot fault requests created by a newer process. +- Add timeout health tracking in [LuaLanguageServerIntellisenseProvider.Requests.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs). +- Restart after a small threshold of consecutive request timeouts on the same generation. +- Preserve the existing tracked-document replay path. + +Tests: + +- Extend [LuaLanguageServerClientTests](TombLib/TombLib.Test/LuaLanguageServerClientTests.cs). +- Extend [LuaLanguageServerIntellisenseProviderTests](TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs). +- Add tests for timeout-triggered restart, document replay, and old-generation isolation. + +### Phase 2: Document Identity And Path Ownership +Goal: keep all IntelliSense state attached to the real file path. + +Tasks: + +- Add a provider-level rename / rekey API rather than hand-rolling `CloseDocument` + `OpenDocument` in multiple UI call sites. +- Wire Save As in [EditorTabControl.SaveFileAs(TabPage)](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L363). +- Wire external rename in [EditorTabControl.RenameDocumentTabPage](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L691). +- Preserve diagnostics / semantic-token cache ownership when the path changes. + +Tests: + +- Save As of an open Lua file. +- External rename of an open Lua file. +- Multiple tabs referencing the same Lua file. + +### Phase 3: Editor Request Freshness And Signature UX +Goal: stale results must never drive UI. + +Tasks: + +- Add a signature request token similar to completion / hover. +- Refresh signature help on more than `(`, `,`, Backspace, and Delete. +- Dismiss signature help when `)` is typed or skipped over through the base auto-close path. +- Make signature-help and definition-result application no-op once the editor has unloaded or is otherwise no longer valid. +- Add a generation / version guard to definition navigation. +- Keep the policy as cancel-and-discard rather than allow-finish-and-apply. + +Tests: + +- Typing `)` after an auto-inserted close paren dismisses signature help. +- Typing and deleting inside an argument list refreshes the highlighted parameter. +- Closing a tab during an in-flight signature or definition request does not reopen UI or navigate. +- Editing before a definition response returns does not navigate. + +### Phase 4: Completion Insertion Correctness +Goal: completion insertion must match LSP semantics, not AvalonEdit guesses. + +Tasks: + +- Extend `LuaCompletionItem` with edit metadata: document version, request generation, and edit range information. +- Parse `textEdit.range` and `InsertReplaceEdit` (`insert` / `replace`) in [LuaLanguageServerResponseParser.Completion.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs#L145). +- Apply those ranges in [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117). +- Reject stale completion application after a relevant document version change. +- When resolve is used, merge resolved detail/documentation into the unresolved insertion metadata. + +Tests: + +- Range replacement. +- Insert-vs-replace behavior. +- Stale version rejection. +- Resolve preserving insertion semantics. + +### Phase 5: Lua Indentation And Multiline Completion Behavior +Goal: Lua should indent blocks correctly whether the user presses Enter or commits a multiline completion. + +Tasks: + +- Introduce a Lua-specific Enter / indentation strategy in [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs). +- Indent one extra level after block openers such as `then`, `do`, `function`, `repeat`, and table / paren continuations as appropriate. +- Dedent on lines starting with `end`, `until`, `else`, or `elseif` as appropriate. +- Normalize multiline completion insertion indentation relative to the current line. +- Decide explicitly what to do with snippet `$0` intent when snippet support is disabled. + +Practical guidance: + +- Do not build a full tabstop snippet engine in this phase. +- Do preserve correct relative indentation and sensible caret placement for the common multiline Lua blocks users actually insert. + +Tests: + +- Pressing Enter after `then` increases indentation. +- `if ... then ... end` completion places `end` at the expected indentation. +- Multiline insertion preserves CRLF and caret placement intent as far as the plain-text model allows. + +### Phase 6: Immediate Stale-UI Cleanup During Editing +Goal: avoid showing obviously wrong colors and diagnostics while edits are in progress. + +Tasks: + +- Clear diagnostics immediately on text change in Lua editors. +- Decide whether to clear semantic tokens immediately on text change or keep them only when a lightweight remapping strategy exists. +- If immediate clearing is too visually noisy, add a very short debounce distinct from the 300 ms document sync. +- Keep provider-side version gating unchanged. + +Tests: + +- Underlines disappear immediately after edit. +- No stale semantic overlay remains after quick keyword edits. +- Rapid `local -> locl -> local` edits do not leave visually stale coloring. + +### Phase 7: Semantic Token And Highlighting Hardening +Goal: make fallback behavior intentional and deterministic. + +Tasks: + +- Fix delta-failure handling in [LuaLanguageServerIntellisenseProvider.SemanticTokens.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs#L89) so previous data is not paired with a new result id. +- Add a main-editor fallback highlighting path when TextMate install fails. +- Recheck lone-CR affected-line handling in [TextMateDocumentLineList](TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs#L164). +- Add resolver tests for the selector behavior the bundled themes actually depend on. + +Tests: + +- Failed delta forces full refresh. +- Main editor still has baseline Lua highlighting if TextMate is unavailable. +- CRLF, LF, and lone CR changes invalidate the correct line range. + +### Phase 8: Watcher, Disposal, Tooltip, And Packaging Hardening +Goal: finish the non-blocking safety and polish tasks. + +Tasks: + +- Make watcher disposal safe while dispatch is active. +- Decide whether watcher `Error` should restart, back off, or surface a disabled state. +- Wrap provider fan-out so one subscriber exception does not suppress later subscribers. +- Make tooltip code-block editors explicitly non-focusable and confirm resource lifetime behavior. +- Add LuaLS attribution to [ExternalResources.md](ExternalResources.md). + +Tests: + +- Watcher disposal during active dispatch. +- Subscriber exception isolation. +- Tooltip content does not steal focus. + +## Items Reclassified As Lower Priority Or Non-Blockers + +- Open-document replay after LuaLS restart is already present. +- Watch coverage for `*.lua`, `.luarc.*`, and `.API` is already present. +- Timeout-bounded LuaLS disposal is already present. +- The bundled themes do not currently rely on advanced TextMate parent-scope or excluded-selector semantics strongly enough to make that a first-wave blocker. +- A full snippet engine is not required for the first implementation pass. + +## Coverage Of Verified Issues + +Every concern below was re-verified as a real issue and has an explicit home in the plan: + +- Timeout-based server recovery: Phase 1. +- Old-generation transport isolation: Phase 1. +- Save As / rename document rekeying: Phase 2. +- Signature stale-response guards: Phase 3. +- Definition stale / disposed-editor guards: Phase 3. +- Signature-help dismissal on skipped `)`: Phase 3. +- Signature active-parameter refresh and desync: Phase 3. +- `textEdit.range` / `insert` / `replace` support: Phase 4. +- Completion stale-version application guard: Phase 4. +- Completion resolve preserving insertion metadata: Phase 4. +- Enter indentation after `then`: Phase 5. +- Multiline `if ... then ... end` completion indentation: Phase 5. +- Plain-text handling of snippet `$0` intent and caret placement: Phase 5. +- Immediate clearing of stale diagnostics after edit: Phase 6. +- Immediate handling of stale semantic overlays after edit: Phase 6. +- Semantic-token delta fallback consistency: Phase 7. +- Main-editor TextMate fallback: Phase 7. +- Watcher disposal / recovery hardening: Phase 8. +- Diagnostics / semantic-token fan-out isolation: Phase 8. +- Tooltip embedded-editor focus hardening: Phase 8. +- LuaLS attribution in packaged resources: Phase 8. + +The remaining concerns were intentionally not phased as defects because they were either already implemented, not reproduced as current production issues, or were narrower follow-on improvements rather than independently verified bugs. + +## Suggested Test Inventory + +- [LuaLanguageServerClientTests](TombLib/TombLib.Test/LuaLanguageServerClientTests.cs) +- [LuaLanguageServerIntellisenseProviderTests](TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs) +- [LuaLanguageServerResponseParserTests](TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs) +- [LuaIncrementalEditCalculatorTests](TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs) +- [LuaThemeConfigurationTests](TombLib/TombLib.Test/LuaThemeConfigurationTests.cs) + +Add one optional integration test that starts bundled LuaLS only when the executable exists in the test environment. + +## Recommended First Implementation Slice + +If the next agent wants the smallest safe slice with maximum user impact, do this order: + +1. Phase 1 transport resilience. +2. Phase 2 path rekeying. +3. Phase 3 signature / navigation stale guards. +4. Phase 4 completion `textEdit` correctness. +5. Phase 6 immediate diagnostic and semantic cleanup. + +That order addresses the largest correctness and survivability problems before moving into indentation polish and secondary hardening. diff --git a/TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs b/TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs index 4a0b82ad9e..2dcc4fd0e1 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs @@ -9,6 +9,7 @@ using System.Windows.Forms.Integration; using TombIDE.ScriptingStudio.Forms; using TombIDE.ScriptingStudio.Helpers; +using TombIDE.ScriptingStudio.Objects; using TombIDE.ScriptingStudio.Properties; using TombIDE.Shared; using TombIDE.Shared.SharedClasses; @@ -363,6 +364,7 @@ public FileSavingResult SaveFileAs() public FileSavingResult SaveFileAs(TabPage tab) { IEditorControl editor = GetEditorOfTab(tab); + string oldFilePath = editor.FilePath; string[] ignoredPaths = Array.Empty(); @@ -372,10 +374,37 @@ public FileSavingResult SaveFileAs(TabPage tab) using (var form = new FormFileCreation(ScriptRootDirectoryPath, FileCreationMode.SavingAs, editor.DefaultFileExtension, null, null, ignoredPaths)) if (form.ShowDialog(this) == DialogResult.OK) { + if (string.IsNullOrWhiteSpace(oldFilePath) + || oldFilePath.Equals(form.NewFilePath, StringComparison.OrdinalIgnoreCase)) + { + editor.FilePath = form.NewFilePath; + UpdateTabPageName(tab); + + return SaveFile(tab); + } + editor.FilePath = form.NewFilePath; UpdateTabPageName(tab); - return SaveFile(tab); + FileSavingResult result = SaveFile(tab); + + if (result == FileSavingResult.Success) + { + if (FindTabPagesOfFile(oldFilePath).Any()) + { + RenameDocumentTabPage(oldFilePath, form.NewFilePath); + SaveOtherTabPagesOfFile(editor); + } + else + OnDocumentRenamed(new DocumentRenamedEventArgs(oldFilePath, form.NewFilePath)); + } + else + { + editor.FilePath = oldFilePath; + UpdateTabPageName(tab); + } + + return result; } else return FileSavingResult.Canceled; @@ -520,6 +549,10 @@ public IEditorControl GetEditorOfTab(TabPage tab) protected virtual void OnFileOpened(EventArgs e) => FileOpened?.Invoke(CurrentEditor, e); + public event EventHandler DocumentRenamed; + protected virtual void OnDocumentRenamed(DocumentRenamedEventArgs e) + => DocumentRenamed?.Invoke(this, e); + protected override void OnTabClosing(TabControlCancelEventArgs e) { IEditorControl editorOfTab = GetEditorOfTab(e.TabPage); @@ -690,7 +723,17 @@ public void UpdateTabPageName(IEditorControl tabPageEditor) public void RenameDocumentTabPage(string oldFilePath, string newFilePath) { - IEnumerable tabPages = FindTabPagesOfFile(oldFilePath); + if (string.IsNullOrWhiteSpace(oldFilePath) + || string.IsNullOrWhiteSpace(newFilePath) + || oldFilePath.Equals(newFilePath, StringComparison.OrdinalIgnoreCase)) + { + return; + } + + List tabPages = FindTabPagesOfFile(oldFilePath).ToList(); + + if (tabPages.Count == 0) + return; foreach (TabPage tab in tabPages) { @@ -699,6 +742,8 @@ public void RenameDocumentTabPage(string oldFilePath, string newFilePath) UpdateTabPageName(editor); } + + OnDocumentRenamed(new DocumentRenamedEventArgs(oldFilePath, newFilePath)); } private string BuildTabPageTitleText(string filePath, EditorType editorType) diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 589dd9ad15..53ea336d23 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Windows.Forms; +using TombIDE.ScriptingStudio.Objects; using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombLib.Scripting.Bases; using TombLib.Scripting.Lua; @@ -25,6 +26,8 @@ private void HookLuaIntellisense() { EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; EditorTabControl.FileOpened += EditorTabControl_LuaFileOpened; + EditorTabControl.DocumentRenamed -= EditorTabControl_DocumentRenamed; + EditorTabControl.DocumentRenamed += EditorTabControl_DocumentRenamed; _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; _intellisenseProvider.DiagnosticsUpdated += IntellisenseProvider_DiagnosticsUpdated; @@ -35,17 +38,23 @@ private void HookLuaIntellisense() { languageServerProvider.StartupFailed -= IntellisenseProvider_StartupFailed; languageServerProvider.StartupFailed += IntellisenseProvider_StartupFailed; + languageServerProvider.WorkspaceWatcherFailed -= IntellisenseProvider_WorkspaceWatcherFailed; + languageServerProvider.WorkspaceWatcherFailed += IntellisenseProvider_WorkspaceWatcherFailed; } } private void DisposeLuaIntellisense() { EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; + EditorTabControl.DocumentRenamed -= EditorTabControl_DocumentRenamed; _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; if (_intellisenseProvider is LuaLanguageServerIntellisenseProvider languageServerProvider) + { languageServerProvider.StartupFailed -= IntellisenseProvider_StartupFailed; + languageServerProvider.WorkspaceWatcherFailed -= IntellisenseProvider_WorkspaceWatcherFailed; + } _intellisenseProvider.Dispose(); } @@ -61,7 +70,7 @@ private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() // Log a warning and surface a single non-blocking notification so the failure is visible. Log.Warn("Bundled Lua language server was not found; Lua IntelliSense (diagnostics, completion, hover, go-to-definition) will be unavailable for this session."); - DarkUI.Forms.DarkMessageBox.Show(this, + MessageBox.Show(this, "The bundled Lua language server (LuaLS) could not be located.\n\n" + "Lua IntelliSense - including diagnostics, completion, hover and go-to-definition - will be unavailable for this session.\n\n" + "Reinstall TombIDE to restore the bundled language server.", @@ -95,6 +104,25 @@ private void LuaEditor_TextChangedDelayed(object? sender, EventArgs e) _intellisenseProvider.UpdateDocument(editor.FilePath, editor.Text); } + private void EditorTabControl_DocumentRenamed(object? sender, DocumentRenamedEventArgs e) + { + LuaEditor? editor = null; + + foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(e.NewFilePath)) + { + if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor luaEditor) + { + editor = luaEditor; + break; + } + } + + if (editor is null) + return; + + _intellisenseProvider.RenameDocument(e.OldFilePath, e.NewFilePath, editor.Text); + } + private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyList diagnostics) { if (InvokeRequired) @@ -136,13 +164,31 @@ private void IntellisenseProvider_StartupFailed(LuaLanguageServerStartupFailure if (IsDisposed) return; - DarkUI.Forms.DarkMessageBox.Show(this, + MessageBox.Show(this, failure.Message, failure.IsPersistent ? "Lua IntelliSense disabled" : "Lua IntelliSense unavailable", MessageBoxButtons.OK, MessageBoxIcon.Warning); } + private void IntellisenseProvider_WorkspaceWatcherFailed(LuaWorkspaceWatcherFailure failure) + { + if (InvokeRequired) + { + BeginInvoke(new Action(IntellisenseProvider_WorkspaceWatcherFailed), failure); + return; + } + + if (IsDisposed) + return; + + MessageBox.Show(this, + failure.Message, + "Lua workspace watching disabled", + MessageBoxButtons.OK, + MessageBoxIcon.Warning); + } + private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) { if (definitionLocation is null || string.IsNullOrWhiteSpace(definitionLocation.FilePath) || !File.Exists(definitionLocation.FilePath)) @@ -169,4 +215,19 @@ private static void ApplyDiagnosticsToEditor(LuaEditor editor, IReadOnlyList semanticTokens) => editor.SetSemanticTokens(semanticTokens ?? []); + + private void ApplyTrackedDocumentStateToEditors(string filePath) + { + IReadOnlyList diagnostics = _intellisenseProvider.GetDiagnostics(filePath); + IReadOnlyList semanticTokens = _intellisenseProvider.GetSemanticTokens(filePath); + + foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) + { + if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) + { + ApplyDiagnosticsToEditor(editor, diagnostics); + ApplySemanticTokensToEditor(editor, semanticTokens); + } + } + } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Objects/DocumentRenamedEventArgs.cs b/TombIDE/TombIDE.ScriptingStudio/Objects/DocumentRenamedEventArgs.cs new file mode 100644 index 0000000000..c637c69921 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Objects/DocumentRenamedEventArgs.cs @@ -0,0 +1,16 @@ +using System; + +namespace TombIDE.ScriptingStudio.Objects +{ + public class DocumentRenamedEventArgs : EventArgs + { + public string OldFilePath { get; } + public string NewFilePath { get; } + + public DocumentRenamedEventArgs(string oldFilePath, string newFilePath) + { + OldFilePath = oldFilePath; + NewFilePath = newFilePath; + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs index 2d4024ccef..73ecb00f40 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs @@ -18,6 +18,11 @@ internal interface ILuaLanguageServerClient : IDisposable /// bool IsReady { get; } + /// + /// Gets the current transport generation for the active language-server session. + /// + long TransportGeneration { get; } + /// /// Gets the text-document synchronization mode negotiated with the language server. /// @@ -60,6 +65,11 @@ internal interface ILuaLanguageServerClient : IDisposable /// when the client is ready; otherwise, . Task StartAsync(CancellationToken cancellationToken); + /// + /// Marks the current transport unhealthy so the next startup check restarts the server session. + /// + void MarkTransportUnhealthy(); + /// /// Sends a JSON-RPC notification to the language server. /// diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentRenameRequest.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentRenameRequest.cs new file mode 100644 index 0000000000..7402052299 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentRenameRequest.cs @@ -0,0 +1,11 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Describes a tracked-document path rekey that may need to be mirrored to LuaLS as a close/open pair. +/// +internal readonly record struct LuaDocumentRenameRequest( + LuaDocumentSnapshot? PreviousDocument, + LuaDocumentSnapshot RenamedDocument, + bool ReopenServerDocument); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs index ab952a366f..3d28225390 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs @@ -15,8 +15,8 @@ internal sealed class LuaIntellisenseDocumentManager { private sealed class DocumentState { - public required string FilePath { get; init; } - public required string Uri { get; init; } + public required string FilePath { get; set; } + public required string Uri { get; set; } public string Content { get; set; } = string.Empty; public int Version { get; set; } public bool IsOpen { get; set; } @@ -120,6 +120,48 @@ public IReadOnlyList GetSemanticTokens(string filePath) } } + /// + /// Rekeys a tracked document to a new normalized file path and preserves any diagnostics or semantic tokens + /// that still match the current content. + /// + /// The current normalized file path. + /// The replacement normalized file path. + /// The latest editor content. + /// The rename request that should be mirrored to LuaLS, or when no document was tracked. + public LuaDocumentRenameRequest? Rename(string oldFilePath, string newFilePath, string? content = null) + { + if (string.Equals(oldFilePath, newFilePath, StringComparison.OrdinalIgnoreCase)) + return null; + + lock (_syncRoot) + { + if (!_documents.TryGetValue(oldFilePath, out DocumentState? state)) + return null; + + string safeContent = content ?? state.Content; + bool contentChanged = !string.Equals(state.Content, safeContent, StringComparison.Ordinal); + LuaDocumentSnapshot? previousDocument = state.IsOpen ? CreateSnapshot(state) : null; + + _documents.Remove(oldFilePath); + + if (_documents.ContainsKey(newFilePath)) + ClearCachedState(state); + + state.FilePath = newFilePath; + state.Uri = LuaLanguageServerPathHelper.CreateFileUri(newFilePath); + + if (contentChanged) + { + state.Content = safeContent; + state.Version++; + ClearCachedState(state); + } + + _documents[newFilePath] = state; + return new LuaDocumentRenameRequest(previousDocument, CreateSnapshot(state), previousDocument is not null); + } + } + /// /// Releases one open reference for . The document is only fully /// removed (and a `didClose` snapshot returned) once the reference count drops to zero, @@ -315,6 +357,16 @@ public bool InvalidateServerSynchronization(string filePath) } } + private static void ClearCachedState(DocumentState state) + { + state.Diagnostics = []; + state.DiagnosticsVersion = 0; + state.SemanticTokens = []; + state.SemanticTokensVersion = 0; + state.SemanticTokensData = null; + state.SemanticTokensResultId = null; + } + private static bool IsStaleVersion(int currentVersion, int incomingVersion) => incomingVersion > 0 && currentVersion > 0 && incomingVersion < currentVersion; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs index 3571de212d..8d2d68c2f7 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs @@ -14,46 +14,53 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; internal sealed partial class LuaLanguageServerClient { private Task SendNotificationCoreAsync(string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) - => WriteMessageAsync(new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken, allowDisposed); + => SendNotificationCoreAsync(GetRequiredActiveSession(allowDisposed), method, parameters, cancellationToken, allowDisposed); + + private Task SendNotificationCoreAsync(LuaLanguageServerTransportSession session, string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) + => WriteMessageAsync(session, new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken, allowDisposed); private async Task SendRequestCoreAsync(string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) - { - ThrowIfDisposed(allowDisposed); + => await SendRequestCoreAsync(GetRequiredActiveSession(allowDisposed), method, parameters, cancellationToken, allowDisposed).ConfigureAwait(false); + private async Task SendRequestCoreAsync(LuaLanguageServerTransportSession session, string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) + { long requestId = Interlocked.Increment(ref _requestId); var responseSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - if (!_pendingRequests.TryAdd(requestId, responseSource)) + if (!session.PendingRequests.TryAdd(requestId, responseSource)) throw new InvalidOperationException("Unable to track a new language server request."); await using var registration = cancellationToken.Register(() => responseSource.TrySetCanceled(cancellationToken)); try { - await WriteMessageAsync(new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken, allowDisposed).ConfigureAwait(false); + await WriteMessageAsync(session, new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken, allowDisposed).ConfigureAwait(false); return await responseSource.Task.ConfigureAwait(false); } catch (OperationCanceledException) { - SendCancelNotification(requestId); + SendCancelNotification(session, requestId); throw; } finally { - _pendingRequests.TryRemove(requestId, out _); + session.PendingRequests.TryRemove(requestId, out _); } } - private void SendCancelNotification(long requestId) + private void SendCancelNotification(LuaLanguageServerTransportSession session, long requestId) { - if (_isDisposed || _outputStream is null) + if (_isDisposed) return; Task.Run(async () => { try { - await WriteMessageAsync(new { jsonrpc = "2.0", method = "$/cancelRequest", @params = new { id = requestId } }, CancellationToken.None, allowDisposed: true).ConfigureAwait(false); + await WriteMessageAsync(session, + new { jsonrpc = "2.0", method = "$/cancelRequest", @params = new { id = requestId } }, + CancellationToken.None, + allowDisposed: true).ConfigureAwait(false); } catch { @@ -62,16 +69,16 @@ private void SendCancelNotification(long requestId) }); } - private async Task HandleServerRequestAsync(JsonElement idElement, string method, JsonElement parameters) + private async Task HandleServerRequestAsync(LuaLanguageServerTransportSession session, JsonElement idElement, string method, JsonElement parameters) { switch (method) { case "workspace/configuration": - await WriteResponseAsync(idElement, BuildConfigurationResponse(parameters)).ConfigureAwait(false); + await WriteResponseAsync(session, idElement, BuildConfigurationResponse(parameters)).ConfigureAwait(false); return; case "workspace/workspaceFolders": - await WriteResponseAsync(idElement, BuildWorkspaceFolderResponse()).ConfigureAwait(false); + await WriteResponseAsync(session, idElement, BuildWorkspaceFolderResponse()).ConfigureAwait(false); return; case "workspace/semanticTokens/refresh": @@ -84,28 +91,28 @@ private async Task HandleServerRequestAsync(JsonElement idElement, string method Log.Warn(exception, "Lua semantic-tokens refresh request handler threw; acknowledging the request anyway."); } - await WriteResponseAsync(idElement, result: null).ConfigureAwait(false); + await WriteResponseAsync(session, idElement, result: null).ConfigureAwait(false); return; case "client/registerCapability": case "client/unregisterCapability": case "window/workDoneProgress/create": // Acknowledge with a successful empty result so the server can proceed. - await WriteResponseAsync(idElement, result: null).ConfigureAwait(false); + await WriteResponseAsync(session, idElement, result: null).ConfigureAwait(false); return; default: // Reply with JSON-RPC "Method Not Found" (-32601) for everything else so the server does not block on us. - await WriteErrorResponseAsync(idElement, code: -32601, message: $"Method '{method}' is not supported by the client.").ConfigureAwait(false); + await WriteErrorResponseAsync(session, idElement, code: -32601, message: $"Method '{method}' is not supported by the client.").ConfigureAwait(false); return; } } - private Task WriteResponseAsync(JsonElement idElement, object? result) - => WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None, allowDisposed: true); + private Task WriteResponseAsync(LuaLanguageServerTransportSession session, JsonElement idElement, object? result) + => WriteMessageAsync(session, new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None, allowDisposed: true); - private Task WriteErrorResponseAsync(JsonElement idElement, int code, string message) - => WriteMessageAsync(new { jsonrpc = "2.0", id = idElement, error = new { code, message } }, CancellationToken.None, allowDisposed: true); + private Task WriteErrorResponseAsync(LuaLanguageServerTransportSession session, JsonElement idElement, int code, string message) + => WriteMessageAsync(session, new { jsonrpc = "2.0", id = idElement, error = new { code, message } }, CancellationToken.None, allowDisposed: true); private object[] BuildConfigurationResponse(JsonElement parameters) { @@ -165,13 +172,10 @@ private object[] BuildWorkspaceFolderResponse() => } ]; - private async Task WriteMessageAsync(object payload, CancellationToken cancellationToken, bool allowDisposed) + private async Task WriteMessageAsync(LuaLanguageServerTransportSession session, object payload, CancellationToken cancellationToken, bool allowDisposed) { ThrowIfDisposed(allowDisposed); - if (_outputStream is null) - throw new IOException("The Lua language server output stream is not available."); - byte[] payloadBytes = JsonSerializer.SerializeToUtf8Bytes(payload); // Header layout: "Content-Length: \r\n\r\n". Worst-case digits fit comfortably in 32 bytes. @@ -188,8 +192,8 @@ private async Task WriteMessageAsync(object payload, CancellationToken cancellat try { - await _outputStream.WriteAsync(frameBuffer.AsMemory(0, frameLength), cancellationToken).ConfigureAwait(false); - await _outputStream.FlushAsync(cancellationToken).ConfigureAwait(false); + await session.OutputStream.WriteAsync(frameBuffer.AsMemory(0, frameLength), cancellationToken).ConfigureAwait(false); + await session.OutputStream.FlushAsync(cancellationToken).ConfigureAwait(false); } finally { diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs index 332e7bea0b..59dab20c51 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs @@ -15,7 +15,7 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; internal sealed partial class LuaLanguageServerClient { - private async Task ReadLoopAsync() + private async Task ReadLoopAsync(LuaLanguageServerTransportSession session) { Exception? failure = null; @@ -23,18 +23,18 @@ private async Task ReadLoopAsync() { while (!_isDisposed) { - int? contentLengthValue = await ReadHeadersAsync().ConfigureAwait(false); + int? contentLengthValue = await ReadHeadersAsync(session).ConfigureAwait(false); if (contentLengthValue is null || !TryAcceptPayloadSize(contentLengthValue.Value, out int contentLength)) break; - byte[]? payloadBytes = await ReadPayloadAsync(contentLength).ConfigureAwait(false); + byte[]? payloadBytes = await ReadPayloadAsync(session, contentLength).ConfigureAwait(false); if (payloadBytes is null) break; using JsonDocument document = JsonDocument.Parse(payloadBytes); - await HandleMessageAsync(document.RootElement).ConfigureAwait(false); + await HandleMessageAsync(session, document.RootElement).ConfigureAwait(false); } } catch (Exception exception) @@ -43,20 +43,21 @@ private async Task ReadLoopAsync() } finally { - IsReady = false; + if (IsCurrentSession(session)) + IsReady = false; - if (!_pendingRequests.IsEmpty) - FailPendingRequests(failure ?? new IOException("The Lua language server connection was closed.")); + if (!session.PendingRequests.IsEmpty) + FailPendingRequests(session, failure ?? new IOException("The Lua language server connection was closed.")); } } - private async Task ReadStandardErrorLoopAsync() + private async Task ReadStandardErrorLoopAsync(LuaLanguageServerTransportSession session) { try { while (!_isDisposed) { - Process? process = _process; + Process? process = session.Process; if (process is null || process.HasExited) break; @@ -78,24 +79,24 @@ private async Task ReadStandardErrorLoopAsync() } } - private async Task ReadHeadersAsync() + private async Task ReadHeadersAsync(LuaLanguageServerTransportSession session) { while (true) { - int headerTerminatorIndex = FindHeaderTerminatorIndex(); + int headerTerminatorIndex = FindHeaderTerminatorIndex(session); if (headerTerminatorIndex >= 0) - return ConsumeHeaders(headerTerminatorIndex); + return ConsumeHeaders(session, headerTerminatorIndex); - if (!await ReadIntoReceiveBufferAsync().ConfigureAwait(false)) + if (!await ReadIntoReceiveBufferAsync(session).ConfigureAwait(false)) return null; } } - private int? ConsumeHeaders(int headerTerminatorIndex) + private int? ConsumeHeaders(LuaLanguageServerTransportSession session, int headerTerminatorIndex) { - string headerText = Encoding.ASCII.GetString(_receiveBuffer, 0, headerTerminatorIndex); - ConsumeReceiveBuffer(headerTerminatorIndex + HeaderTerminator.Length); + string headerText = Encoding.ASCII.GetString(session.ReceiveBuffer, 0, headerTerminatorIndex); + ConsumeReceiveBuffer(session, headerTerminatorIndex + HeaderTerminator.Length); return ExtractContentLength(headerText); } @@ -124,85 +125,79 @@ private async Task ReadStandardErrorLoopAsync() return null; } - private int FindHeaderTerminatorIndex() - => new ReadOnlySpan(_receiveBuffer, 0, _receiveBufferCount).IndexOf(HeaderTerminator); + private int FindHeaderTerminatorIndex(LuaLanguageServerTransportSession session) + => new ReadOnlySpan(session.ReceiveBuffer, 0, session.ReceiveBufferCount).IndexOf(HeaderTerminator); - private async Task ReadIntoReceiveBufferAsync() + private async Task ReadIntoReceiveBufferAsync(LuaLanguageServerTransportSession session) { - if (_inputStream is null) - return false; - - EnsureReceiveBufferCapacity(_receiveBufferCount + ReceiveChunkSize); + EnsureReceiveBufferCapacity(session, session.ReceiveBufferCount + ReceiveChunkSize); - int bytesAvailable = _receiveBuffer.Length - _receiveBufferCount; - int bytesRead = await _inputStream - .ReadAsync(_receiveBuffer.AsMemory(_receiveBufferCount, bytesAvailable), _lifetimeCts.Token) + int bytesAvailable = session.ReceiveBuffer.Length - session.ReceiveBufferCount; + int bytesRead = await session.InputStream + .ReadAsync(session.ReceiveBuffer.AsMemory(session.ReceiveBufferCount, bytesAvailable), _lifetimeCts.Token) .ConfigureAwait(false); if (bytesRead == 0) return false; - _receiveBufferCount += bytesRead; + session.ReceiveBufferCount += bytesRead; return true; } - private void EnsureReceiveBufferCapacity(int requiredCapacity) + private void EnsureReceiveBufferCapacity(LuaLanguageServerTransportSession session, int requiredCapacity) { - if (_receiveBuffer.Length >= requiredCapacity) + if (session.ReceiveBuffer.Length >= requiredCapacity) return; - int newCapacity = Math.Max(ReceiveChunkSize, _receiveBuffer.Length); + int newCapacity = Math.Max(ReceiveChunkSize, session.ReceiveBuffer.Length); while (newCapacity < requiredCapacity) newCapacity *= 2; byte[] newBuffer = ArrayPool.Shared.Rent(newCapacity); - if (_receiveBufferCount > 0) - Buffer.BlockCopy(_receiveBuffer, 0, newBuffer, 0, _receiveBufferCount); + if (session.ReceiveBufferCount > 0) + Buffer.BlockCopy(session.ReceiveBuffer, 0, newBuffer, 0, session.ReceiveBufferCount); - ReturnReceiveBuffer(); - _receiveBuffer = newBuffer; + ReturnReceiveBuffer(session); + session.ReceiveBuffer = newBuffer; } - private void ReturnReceiveBuffer() + private void ReturnReceiveBuffer(LuaLanguageServerTransportSession session) { - if (_receiveBuffer.Length == 0) + if (session.ReceiveBuffer.Length == 0) return; - ArrayPool.Shared.Return(_receiveBuffer, clearArray: false); - _receiveBuffer = []; + ArrayPool.Shared.Return(session.ReceiveBuffer, clearArray: false); + session.ReceiveBuffer = []; } - private void ConsumeReceiveBuffer(int bytesToConsume) + private void ConsumeReceiveBuffer(LuaLanguageServerTransportSession session, int bytesToConsume) { - int remainingBytes = _receiveBufferCount - bytesToConsume; + int remainingBytes = session.ReceiveBufferCount - bytesToConsume; if (remainingBytes > 0) - Buffer.BlockCopy(_receiveBuffer, bytesToConsume, _receiveBuffer, 0, remainingBytes); + Buffer.BlockCopy(session.ReceiveBuffer, bytesToConsume, session.ReceiveBuffer, 0, remainingBytes); - _receiveBufferCount = Math.Max(0, remainingBytes); + session.ReceiveBufferCount = Math.Max(0, remainingBytes); } - private async Task ReadPayloadAsync(int contentLength) + private async Task ReadPayloadAsync(LuaLanguageServerTransportSession session, int contentLength) { - if (_inputStream is null) - return null; - byte[] payloadBytes = new byte[contentLength]; int totalBytesRead = 0; - if (_receiveBufferCount > 0) + if (session.ReceiveBufferCount > 0) { - int bufferedBytesToCopy = Math.Min(contentLength, _receiveBufferCount); - Buffer.BlockCopy(_receiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); - ConsumeReceiveBuffer(bufferedBytesToCopy); + int bufferedBytesToCopy = Math.Min(contentLength, session.ReceiveBufferCount); + Buffer.BlockCopy(session.ReceiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); + ConsumeReceiveBuffer(session, bufferedBytesToCopy); totalBytesRead = bufferedBytesToCopy; } while (totalBytesRead < contentLength) { - int bytesRead = await _inputStream + int bytesRead = await session.InputStream .ReadAsync(payloadBytes.AsMemory(totalBytesRead, contentLength - totalBytesRead), _lifetimeCts.Token) .ConfigureAwait(false); @@ -215,14 +210,14 @@ private void ConsumeReceiveBuffer(int bytesToConsume) return payloadBytes; } - private async Task HandleMessageAsync(JsonElement message) + private async Task HandleMessageAsync(LuaLanguageServerTransportSession session, JsonElement message) { bool hasId = message.TryGetProperty("id", out JsonElement idElement); bool hasMethod = message.TryGetProperty("method", out JsonElement methodElement); if (hasId && !hasMethod) { - HandleServerResponse(idElement, message); + HandleServerResponse(session, idElement, message); return; } @@ -239,17 +234,17 @@ private async Task HandleMessageAsync(JsonElement message) : default; if (hasId) - await HandleServerRequestAsync(idElement.Clone(), method, parameters).ConfigureAwait(false); + await HandleServerRequestAsync(session, idElement.Clone(), method, parameters).ConfigureAwait(false); else HandleServerNotification(method, parameters); } - private void HandleServerResponse(JsonElement idElement, JsonElement message) + private void HandleServerResponse(LuaLanguageServerTransportSession session, JsonElement idElement, JsonElement message) { if (!idElement.TryGetInt64(out long requestId)) return; - if (!_pendingRequests.TryGetValue(requestId, out TaskCompletionSource? responseSource)) + if (!session.PendingRequests.TryGetValue(requestId, out TaskCompletionSource? responseSource)) { Log.Debug("Received Lua language server response with no matching pending request (id={RequestId}).", requestId); return; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs index 3bae99951f..cfefa1b60d 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs @@ -32,7 +32,6 @@ internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient private readonly SemaphoreSlim _startLock = new(1, 1); private readonly SemaphoreSlim _writeLock = new(1, 1); private readonly CancellationTokenSource _lifetimeCts = new(); - private readonly ConcurrentDictionary> _pendingRequests = new(); private readonly ConcurrentDictionary _pendingDiagnostics = new(StringComparer.OrdinalIgnoreCase); // Diagnostics arrive on the LSP read loop and are stored as the latest payload per file URI. @@ -65,16 +64,12 @@ internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient private long _requestId; private long _diagnosticsFallbackSequence; + private long _transportGeneration; + private long _activeTransportGeneration; private volatile bool _isDisposed; private volatile bool _isReady; - private Process? _process; - private Stream? _inputStream; - private Stream? _outputStream; - private byte[] _receiveBuffer = []; - private int _receiveBufferCount; - private Task? _readLoopTask; - private Task? _stderrLoopTask; + private LuaLanguageServerTransportSession? _activeSession; private LuaTextDocumentSyncKind _textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; private string[] _semanticTokenTypes = []; private string[] _semanticTokenModifiers = []; @@ -90,6 +85,11 @@ public bool IsReady private set => _isReady = value; } + /// + /// Gets the current transport generation for the active server session. + /// + public long TransportGeneration => Volatile.Read(ref _activeTransportGeneration); + /// /// Gets the text-document synchronization mode negotiated with the server. /// @@ -155,9 +155,12 @@ public async Task StartAsync(CancellationToken cancellationToken) if (IsReady) return true; - // Reset any stale transport state, then spawn the LuaLS process and attach the read loops. ThrowIfDisposed(allowDisposed: false); - ResetProcessState(); + + LuaLanguageServerTransportSession? previousSession = DetachActiveSession(); + + if (previousSession is not null) + await DisposeSessionAsync(previousSession).ConfigureAwait(false); var startInfo = new ProcessStartInfo { @@ -170,40 +173,45 @@ public async Task StartAsync(CancellationToken cancellationToken) RedirectStandardError = true }; - _process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }; - _process.Exited += Process_Exited; + var process = new Process { StartInfo = startInfo, EnableRaisingEvents = true }; - if (!_process.Start()) + if (!process.Start()) + { + process.Dispose(); return false; + } if (OperatingSystem.IsWindows()) - LuaProcessJobObject.TryAssignProcess(_process); + LuaProcessJobObject.TryAssignProcess(process); - _inputStream = _process.StandardOutput.BaseStream; - _outputStream = _process.StandardInput.BaseStream; - - _readLoopTask = Task.Run(ReadLoopAsync, CancellationToken.None); - _stderrLoopTask = Task.Run(ReadStandardErrorLoopAsync, CancellationToken.None); + LuaLanguageServerTransportSession session = CreateTransportSession(process); + SetActiveSession(session); _diagnosticsPumpTask ??= Task.Run(PumpDiagnosticsAsync, CancellationToken.None); // Complete the LSP handshake before marking the client ready for provider requests. using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); - JsonElement initializeResponse = await SendRequestAsync("initialize", BuildInitializeParams(), initializeTimeout.Token).ConfigureAwait(false); + JsonElement initializeResponse = await SendRequestCoreAsync(session, + "initialize", BuildInitializeParams(), initializeTimeout.Token, allowDisposed: false).ConfigureAwait(false); CaptureServerCapabilities(initializeResponse); IsReady = true; - await SendNotificationAsync("initialized", new { }, cancellationToken).ConfigureAwait(false); - await SendNotificationAsync("workspace/didChangeConfiguration", new { settings = _settingsProvider() }, cancellationToken).ConfigureAwait(false); + await SendNotificationCoreAsync(session, "initialized", new { }, cancellationToken, allowDisposed: false).ConfigureAwait(false); + + await SendNotificationCoreAsync(session, + "workspace/didChangeConfiguration", + new { settings = _settingsProvider() }, + cancellationToken, + allowDisposed: false).ConfigureAwait(false); return true; } catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { // Caller-driven cancellation should tear down the half-started process so later retries begin cleanly. - await DisposeProcessAsync().ConfigureAwait(false); + await DisposeActiveSessionAsync().ConfigureAwait(false); throw; } catch (Exception exception) @@ -211,7 +219,7 @@ public async Task StartAsync(CancellationToken cancellationToken) Log.Warn(exception, "Failed to start the Lua language server (executable='{Executable}', workspace='{Workspace}').", _serverExecutablePath, _workspaceRootDirectoryPath); - await DisposeProcessAsync().ConfigureAwait(false); + await DisposeActiveSessionAsync().ConfigureAwait(false); return false; } finally @@ -239,6 +247,17 @@ public Task SendNotificationAsync(string method, object parameters, Cancellation public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) => SendRequestCoreAsync(method, parameters, cancellationToken, allowDisposed: false); + /// + /// Marks the current transport unhealthy so the provider restarts it on the next request. + /// + public void MarkTransportUnhealthy() + { + if (_isDisposed) + return; + + IsReady = false; + } + private object BuildInitializeParams() => new { processId = Environment.ProcessId, @@ -430,18 +449,72 @@ private static string[] ReadStringArray(JsonElement parent, string propertyName) return [.. values]; } - private void Process_Exited(object? sender, EventArgs e) + private LuaLanguageServerTransportSession CreateTransportSession(Process process) + { + long generation = Interlocked.Increment(ref _transportGeneration); + var session = new LuaLanguageServerTransportSession(generation, + process, + process.StandardOutput.BaseStream, + process.StandardInput.BaseStream); + + session.ProcessExitedHandler = (_, _) => Process_Exited(session); + process.Exited += session.ProcessExitedHandler; + session.ReadLoopTask = Task.Run(() => ReadLoopAsync(session), CancellationToken.None); + session.StderrLoopTask = Task.Run(() => ReadStandardErrorLoopAsync(session), CancellationToken.None); + return session; + } + + private void SetActiveSession(LuaLanguageServerTransportSession session) + { + _activeSession = session; + Volatile.Write(ref _activeTransportGeneration, session.Generation); + } + + private LuaLanguageServerTransportSession GetRequiredActiveSession(bool allowDisposed) + { + ThrowIfDisposed(allowDisposed); + + LuaLanguageServerTransportSession? session = Volatile.Read(ref _activeSession); + + if (session is null) + throw new IOException("The Lua language server transport is not available."); + + return session; + } + + private LuaLanguageServerTransportSession? DetachActiveSession() { + LuaLanguageServerTransportSession? session = Interlocked.Exchange(ref _activeSession, null); IsReady = false; + return session; + } + + private async Task DisposeActiveSessionAsync() + { + LuaLanguageServerTransportSession? session = DetachActiveSession(); + + if (session is not null) + await DisposeSessionAsync(session).ConfigureAwait(false); + } + + private void Process_Exited(LuaLanguageServerTransportSession session) + { + bool isCurrentSession = IsCurrentSession(session); - int? exitCode = TryReadProcessExitCode(sender as Process ?? _process); + if (isCurrentSession) + IsReady = false; - if (!_isDisposed) + int? exitCode = TryReadProcessExitCode(session.Process); + + if (!_isDisposed && isCurrentSession) Log.Warn("Lua language server process exited unexpectedly{ExitCodeSuffix}.", exitCode is not null ? $" with code {exitCode.Value}" : string.Empty); - FailPendingRequests(new IOException("The Lua language server process exited unexpectedly.")); + FailPendingRequests(session, new IOException("The Lua language server process exited unexpectedly.")); } + private bool IsCurrentSession(LuaLanguageServerTransportSession session) + => ReferenceEquals(Volatile.Read(ref _activeSession), session); + private static int? TryReadProcessExitCode(Process? process) { if (process is null) @@ -475,26 +548,41 @@ private static bool TryAcceptPayloadSize(int parsedContentLength, out int conten return true; } - private void FailPendingRequests(Exception exception) + private void FailPendingRequests(LuaLanguageServerTransportSession session, Exception exception) { - foreach (KeyValuePair> pendingRequest in _pendingRequests) + foreach (KeyValuePair> pendingRequest in session.PendingRequests) pendingRequest.Value.TrySetException(exception); } - private async Task DisposeProcessAsync() + private async Task DisposeSessionAsync(LuaLanguageServerTransportSession session) { - Task? readLoopTask = _readLoopTask; - Task? stderrLoopTask = _stderrLoopTask; + Task? readLoopTask = session.ReadLoopTask; + Task? stderrLoopTask = session.StderrLoopTask; + Exception pendingRequestFailure = _isDisposed + ? new ObjectDisposedException(nameof(LuaLanguageServerClient)) + : new IOException("The Lua language server transport was closed."); + + FailPendingRequests(session, pendingRequestFailure); try { - if (_process is not null && !_process.HasExited) + if (session.Process is not null && session.ProcessExitedHandler is not null) + session.Process.Exited -= session.ProcessExitedHandler; + } + catch + { + // Ignore event detach failures. + } + + try + { + if (session.Process is not null && !session.Process.HasExited) { - await TrySendShutdownAsync().ConfigureAwait(false); - await TrySendExitNotificationAsync().ConfigureAwait(false); + await TrySendShutdownAsync(session).ConfigureAwait(false); + await TrySendExitNotificationAsync(session).ConfigureAwait(false); - if (!_process.HasExited) - _process.Kill(true); + if (!session.Process.HasExited) + session.Process.Kill(true); } } catch @@ -503,20 +591,38 @@ private async Task DisposeProcessAsync() } finally { - ResetProcessState(); - IsReady = false; + CleanupSessionResources(session); } - await WaitForBackgroundLoopsAsync(readLoopTask, stderrLoopTask, _diagnosticsPumpTask).ConfigureAwait(false); + await WaitForBackgroundLoopsAsync(readLoopTask, stderrLoopTask).ConfigureAwait(false); } - private async Task TrySendShutdownAsync() + private void CleanupSessionResources(LuaLanguageServerTransportSession session) + { + try + { + session.InputStream.Dispose(); + session.OutputStream.Dispose(); + session.Process?.Dispose(); + } + catch + { + // Ignore stream disposal failures. + } + + ReturnReceiveBuffer(session); + session.ReceiveBufferCount = 0; + session.ReadLoopTask = null; + session.StderrLoopTask = null; + } + + private async Task TrySendShutdownAsync(LuaLanguageServerTransportSession session) { using var shutdownTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); try { - await SendRequestCoreAsync("shutdown", new { }, shutdownTimeout.Token, allowDisposed: true).ConfigureAwait(false); + await SendRequestCoreAsync(session, "shutdown", new { }, shutdownTimeout.Token, allowDisposed: true).ConfigureAwait(false); } catch { @@ -524,13 +630,13 @@ private async Task TrySendShutdownAsync() } } - private async Task TrySendExitNotificationAsync() + private async Task TrySendExitNotificationAsync(LuaLanguageServerTransportSession session) { using var exitTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); try { - await SendNotificationCoreAsync("exit", new { }, exitTimeout.Token, allowDisposed: true).ConfigureAwait(false); + await SendNotificationCoreAsync(session, "exit", new { }, exitTimeout.Token, allowDisposed: true).ConfigureAwait(false); } catch { @@ -538,12 +644,11 @@ private async Task TrySendExitNotificationAsync() } } - private static async Task WaitForBackgroundLoopsAsync(Task? readLoopTask, Task? stderrLoopTask, Task? diagnosticsPumpTask) + private static async Task WaitForBackgroundLoopsAsync(Task? readLoopTask, Task? stderrLoopTask) { Task combined = Task.WhenAll( readLoopTask ?? Task.CompletedTask, - stderrLoopTask ?? Task.CompletedTask, - diagnosticsPumpTask ?? Task.CompletedTask); + stderrLoopTask ?? Task.CompletedTask); try { @@ -559,43 +664,6 @@ private static async Task WaitForBackgroundLoopsAsync(Task? readLoopTask, Task? } } - private void ResetProcessState() - { - try - { - if (_process is not null) - _process.Exited -= Process_Exited; - } - catch - { - // Ignore event detach failures. - } - - try - { - _inputStream?.Dispose(); - _outputStream?.Dispose(); - _process?.Dispose(); - } - catch - { - // Ignore stream disposal failures. - } - - _inputStream = null; - _outputStream = null; - _process = null; - ReturnReceiveBuffer(); - _receiveBufferCount = 0; - _readLoopTask = null; - _stderrLoopTask = null; - _textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; - _supportsCompletionResolve = false; - _supportsSemanticTokensDelta = false; - _semanticTokenTypes = []; - _semanticTokenModifiers = []; - } - private void ThrowIfDisposed(bool allowDisposed) { if (!allowDisposed) @@ -611,7 +679,6 @@ public void Dispose() return; _isDisposed = true; - FailPendingRequests(new ObjectDisposedException(nameof(LuaLanguageServerClient))); _diagnosticsSignal.Writer.TryComplete(); try @@ -625,7 +692,7 @@ public void Dispose() { // DisposeProcessAsync also waits for the read/stderr loops, so by the time it returns no // background task should still be holding the write semaphore. We then release the locks. - if (!DisposeProcessAsync().Wait(DisposeWaitTimeout)) + if (!DisposeActiveSessionAsync().Wait(DisposeWaitTimeout)) Log.Warn("Disposing Lua language server timed out; abandoning background tasks."); } catch (AggregateException exception) @@ -633,8 +700,52 @@ public void Dispose() Log.Warn(exception.Flatten(), "Disposing Lua language server raised exceptions."); } + if (_diagnosticsPumpTask is not null) + { + try + { + if (!_diagnosticsPumpTask.Wait(DisposeWaitTimeout)) + Log.Warn("Lua language server diagnostics pump did not complete within the dispose timeout."); + } + catch (AggregateException exception) + { + Log.Warn(exception.Flatten(), "Disposing the Lua language server diagnostics pump raised exceptions."); + } + } + _lifetimeCts.Dispose(); _startLock.Dispose(); _writeLock.Dispose(); } + + private sealed class LuaLanguageServerTransportSession + { + public LuaLanguageServerTransportSession(long generation, Process? process, Stream inputStream, Stream outputStream) + { + Generation = generation; + Process = process; + InputStream = inputStream; + OutputStream = outputStream; + } + + public long Generation { get; } + + public Process? Process { get; } + + public Stream InputStream { get; } + + public Stream OutputStream { get; } + + public EventHandler? ProcessExitedHandler { get; set; } + + public ConcurrentDictionary> PendingRequests { get; } = new(); + + public byte[] ReceiveBuffer { get; set; } = []; + + public int ReceiveBufferCount { get; set; } + + public Task? ReadLoopTask { get; set; } + + public Task? StderrLoopTask { get; set; } + } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs index 1e605e8370..ac0e419bee 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs @@ -111,6 +111,56 @@ private void InvalidateDocumentSynchronization(string filePath) CancelSemanticTokenRequest(filePath); } + public void RenameDocument(string oldFilePath, string newFilePath, string content) + => ObserveBackgroundTask(TryRenameDocumentAsync(oldFilePath, newFilePath, content, CancellationToken.None), "Document rename"); + + private Task TryRenameDocumentAsync(string oldFilePath, string newFilePath, string content, CancellationToken cancellationToken) + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(oldFilePath, out string normalizedOldFilePath) + || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(newFilePath, out string normalizedNewFilePath) + || string.Equals(normalizedOldFilePath, normalizedNewFilePath, StringComparison.OrdinalIgnoreCase)) + { + return Task.FromResult(false); + } + + return RenameDocumentAsync(normalizedOldFilePath, normalizedNewFilePath, content, cancellationToken); + } + + private async Task RenameDocumentAsync(string oldFilePath, string newFilePath, string content, CancellationToken cancellationToken) + { + if (_isDisposed || _client is null) + return false; + + try + { + LuaDocumentRenameRequest? request = await EnqueueDocumentOperationAsync( + token => RenameDocumentCoreAsync(oldFilePath, newFilePath, content, token), + cancellationToken).ConfigureAwait(false); + + if (request is not { } renameRequest) + return false; + + PublishTrackedDocumentState(renameRequest.RenamedDocument.FilePath); + return true; + } + catch (OperationCanceledException) + { + throw; + } + catch (IOException) + { + InvalidateDocumentSynchronization(newFilePath); + return false; + } + catch (ObjectDisposedException) + { + if (!_isDisposed) + InvalidateDocumentSynchronization(newFilePath); + + return false; + } + } + private async Task<(bool Success, LuaDocumentSnapshot? Document)> SynchronizeDocumentCoreAsync( string filePath, string content, @@ -129,6 +179,46 @@ private void InvalidateDocumentSynchronization(string filePath) return (true, pendingRequest.Document); } + private async Task RenameDocumentCoreAsync( + string oldFilePath, + string newFilePath, + string content, + CancellationToken cancellationToken) + { + if (_client is null) + return null; + + LuaDocumentRenameRequest? request = _documents.Rename(oldFilePath, newFilePath, content); + + if (request is not { } renameRequest) + return null; + + CancelSemanticTokenRequest(oldFilePath); + CancelSemanticTokenRequest(newFilePath); + + if (!renameRequest.ReopenServerDocument) + return renameRequest; + + if (!_startupSucceeded || !_client.IsReady) + { + _documents.InvalidateServerSynchronization(newFilePath); + return renameRequest; + } + + if (renameRequest.PreviousDocument is not null) + { + await _client.SendNotificationAsync("textDocument/didClose", + new { textDocument = new { uri = renameRequest.PreviousDocument.Uri } }, + cancellationToken).ConfigureAwait(false); + } + + await SendDocumentSynchronizationNotificationAsync( + new LuaDocumentSynchronizationRequest(LuaDocumentSynchronizationKind.Open, renameRequest.RenamedDocument), + cancellationToken).ConfigureAwait(false); + + return renameRequest; + } + private async Task ReopenTrackedDocumentsAsync(IReadOnlyList documents, CancellationToken cancellationToken) { for (int i = 0; i < documents.Count; i++) @@ -268,7 +358,13 @@ private void HandleDiagnosticsPublished(JsonElement parameters) if (!_documents.TryStoreDiagnostics(publishedDiagnostics)) return; - DiagnosticsUpdated?.Invoke(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); + RaiseDiagnosticsUpdated(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); + } + + private void PublishTrackedDocumentState(string filePath) + { + RaiseDiagnosticsUpdated(filePath, _documents.GetDiagnostics(filePath)); + RaiseSemanticTokensUpdated(filePath, _documents.GetSemanticTokens(filePath)); } private static void ObserveBackgroundTask(Task task, string operation) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs index 0c849ea19d..f93f109315 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs @@ -135,7 +135,7 @@ private async Task ResolveCompletionItemAsync(LuaCompletionIt LuaCompletionItem? parsedItem = LuaLanguageServerResponseParser.ParseCompletionItem(resolvedItem, itemIndex); if (parsedItem is not null) - return parsedItem; + return unresolvedItem.WithResolvedContent(parsedItem); } } catch (OperationCanceledException) @@ -182,19 +182,75 @@ private async Task SendPositionRequestAsync( return parseResponse(response); } - private static async Task SendBoundedRequestAsync(ILuaLanguageServerClient client, string method, object parameters, CancellationToken cancellationToken) + private async Task SendBoundedRequestAsync(ILuaLanguageServerClient client, string method, object parameters, CancellationToken cancellationToken) { + long transportGeneration = client.TransportGeneration; using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); - timeoutCts.CancelAfter(RequestTimeout); + timeoutCts.CancelAfter(_requestTimeout); try { - return await client.SendRequestAsync(method, parameters, timeoutCts.Token).ConfigureAwait(false); + JsonElement response = await client.SendRequestAsync(method, parameters, timeoutCts.Token).ConfigureAwait(false); + ResetRequestTimeoutTracking(transportGeneration); + return response; } catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) { - Log.Debug("Lua language server request '{Method}' timed out after {Timeout}s.", method, RequestTimeout.TotalSeconds); + RecordRequestTimeout(client, method, transportGeneration); return default; } } + + private void RecordRequestTimeout(ILuaLanguageServerClient client, string method, long transportGeneration) + { + int timeoutCount; + bool shouldMarkTransportUnhealthy = false; + + lock (_requestTimeoutSyncRoot) + { + if (_timedOutRequestGeneration != transportGeneration) + { + _timedOutRequestGeneration = transportGeneration; + _consecutiveRequestTimeouts = 0; + _restartRequestedGeneration = -1; + } + + timeoutCount = ++_consecutiveRequestTimeouts; + + if (timeoutCount >= _requestTimeoutRestartThreshold && _restartRequestedGeneration != transportGeneration) + { + _restartRequestedGeneration = transportGeneration; + shouldMarkTransportUnhealthy = true; + } + } + + if (shouldMarkTransportUnhealthy) + { + Log.Warn("Lua language server request '{Method}' timed out after {Timeout}s {Count} times on transport generation {Generation}; the transport will restart on the next IntelliSense request.", + method, + _requestTimeout.TotalSeconds, + timeoutCount, + transportGeneration); + + client.MarkTransportUnhealthy(); + return; + } + + Log.Debug("Lua language server request '{Method}' timed out after {Timeout}s (consecutive {Count}/{Threshold}, generation {Generation}).", + method, + _requestTimeout.TotalSeconds, + timeoutCount, + _requestTimeoutRestartThreshold, + transportGeneration); + } + + private void ResetRequestTimeoutTracking(long transportGeneration) + { + lock (_requestTimeoutSyncRoot) + { + _timedOutRequestGeneration = transportGeneration; + _consecutiveRequestTimeouts = 0; + _restartRequestedGeneration = -1; + } + } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs index d08375fe1c..ca58bbe0e5 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs @@ -37,26 +37,32 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc { (string? previousResultId, int[]? previousData) = _documents.GetSemanticTokensDeltaState(document.FilePath); bool useDelta = _client.SupportsSemanticTokensDelta && previousResultId is not null && previousData is not null; - - string method = useDelta ? "textDocument/semanticTokens/full/delta" : "textDocument/semanticTokens/full"; - object parameters = useDelta - ? new { textDocument = new { uri = document.Uri }, previousResultId } - : new { textDocument = new { uri = document.Uri } }; - - JsonElement response = await SendBoundedRequestAsync(_client, method, parameters, effectiveToken).ConfigureAwait(false); + JsonElement response = await SendSemanticTokensRequestAsync(document, previousResultId, useDelta, effectiveToken).ConfigureAwait(false); if (response.ValueKind == JsonValueKind.Undefined) return; - (IReadOnlyList semanticTokens, int[]? newData, string? newResultId) = + (IReadOnlyList semanticTokens, int[]? newData, string? newResultId, bool retryWithFullRefresh) = DecodeSemanticTokensResponse(response, document, previousData, useDelta); + if (retryWithFullRefresh) + { + _documents.StoreSemanticTokensDeltaState(document.FilePath, null, null); + + JsonElement fullResponse = await SendSemanticTokensRequestAsync(document, previousResultId: null, useDelta: false, effectiveToken).ConfigureAwait(false); + + if (fullResponse.ValueKind == JsonValueKind.Undefined) + return; + + (semanticTokens, newData, newResultId, _) = DecodeSemanticTokensResponse(fullResponse, document, previousData: null, deltaWasRequested: false); + } + _documents.StoreSemanticTokensDeltaState(document.FilePath, newResultId, newData); if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, semanticTokens)) return; - SemanticTokensUpdated?.Invoke(document.FilePath, semanticTokens); + RaiseSemanticTokensUpdated(document.FilePath, semanticTokens); } catch (OperationCanceledException) when (effectiveToken.IsCancellationRequested && !cancellationToken.IsCancellationRequested) { @@ -86,11 +92,28 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc } } - private (IReadOnlyList Tokens, int[]? Data, string? ResultId) DecodeSemanticTokensResponse( + private Task SendSemanticTokensRequestAsync( + LuaDocumentSnapshot document, + string? previousResultId, + bool useDelta, + CancellationToken cancellationToken) + { + if (_client is null) + return Task.FromResult(default(JsonElement)); + + string method = useDelta ? "textDocument/semanticTokens/full/delta" : "textDocument/semanticTokens/full"; + object parameters = useDelta + ? new { textDocument = new { uri = document.Uri }, previousResultId } + : new { textDocument = new { uri = document.Uri } }; + + return SendBoundedRequestAsync(_client, method, parameters, cancellationToken); + } + + private (IReadOnlyList Tokens, int[]? Data, string? ResultId, bool RetryWithFullRefresh) DecodeSemanticTokensResponse( JsonElement response, LuaDocumentSnapshot document, int[]? previousData, bool deltaWasRequested) { if (_client is null) - return ([], null, null); + return ([], null, null, false); if (deltaWasRequested) { @@ -104,10 +127,11 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc { IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( patchedData, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); - return (tokens, patchedData, delta.ResultId); + return (tokens, patchedData, delta.ResultId, false); } Log.Debug("Lua semantic-tokens delta edits could not be applied for '{FilePath}'; falling back to a full reparse.", document.FilePath); + return ([], null, null, true); } if (delta.Data is { } fullData) @@ -115,10 +139,11 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( fullData, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); - return (tokens, fullData, delta.ResultId); + return (tokens, fullData, delta.ResultId, false); } - return ([], previousData, delta.ResultId); + Log.Debug("Lua semantic-tokens delta response for '{FilePath}' did not contain usable data; requesting a full refresh.", document.FilePath); + return ([], null, null, true); } LuaSemanticTokensDeltaResponse fullResponse = LuaLanguageServerSemanticTokensDeltaParser.Parse(response); @@ -128,10 +153,10 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( data, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); - return (tokens, data, fullResponse.ResultId); + return (tokens, data, fullResponse.ResultId, false); } - return ([], null, fullResponse.ResultId); + return ([], null, fullResponse.ResultId, false); } private CancellationToken ReplaceSemanticTokenRequest(string filePath, CancellationToken cancellationToken, out CancellationTokenSource? linkedSource) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs index b71dcab156..7dc300ba18 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs @@ -20,7 +20,8 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); - private static readonly TimeSpan RequestTimeout = TimeSpan.FromSeconds(10); + private static readonly TimeSpan DefaultRequestTimeout = TimeSpan.FromSeconds(10); + private const int DefaultRequestTimeoutRestartThreshold = 2; private const int HardStartupFailureThreshold = 3; private readonly string _workspaceApiDirectoryPath; @@ -28,15 +29,22 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell private readonly ILuaLanguageServerClient? _client; private readonly LuaIntellisenseDocumentManager _documents = new(); private readonly object _documentOperationSyncRoot = new(); + private readonly object _requestTimeoutSyncRoot = new(); private readonly ConcurrentDictionary _semanticTokenRequests = new(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _startLock = new(1, 1); + private readonly TimeSpan _requestTimeout; + private readonly int _requestTimeoutRestartThreshold; private LuaWorkspaceFileWatcher? _workspaceFileWatcher; private Task _queuedDocumentOperation = Task.CompletedTask; private bool _startupSucceeded; private int _consecutiveStartupFailures; + private int _consecutiveRequestTimeouts; + private long _timedOutRequestGeneration = -1; + private long _restartRequestedGeneration = -1; private bool _permanentStartupFailureReported; private bool _transientStartupFailureReported; + private int _workspaceWatcherFailureReported; private volatile bool _isDisposed; /// @@ -60,20 +68,31 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell /// public event Action? StartupFailed; + /// + /// Occurs when the external workspace watcher becomes unavailable for the rest of the session. + /// + public event Action? WorkspaceWatcherFailed; + /// /// Initializes a new instance of the class. /// /// The root directory of the current Lua script workspace. /// The LuaLS executable path, or when unavailable. public LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, string? serverExecutablePath) - : this(workspaceRootDirectoryPath, CreateClient(workspaceRootDirectoryPath, serverExecutablePath)) + : this(workspaceRootDirectoryPath, + CreateClient(workspaceRootDirectoryPath, serverExecutablePath), + DefaultRequestTimeout, + DefaultRequestTimeoutRestartThreshold) { } - internal LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, ILuaLanguageServerClient? client) + internal LuaLanguageServerIntellisenseProvider(string workspaceRootDirectoryPath, ILuaLanguageServerClient? client, + TimeSpan? requestTimeout = null, int requestTimeoutRestartThreshold = DefaultRequestTimeoutRestartThreshold) { _workspaceRootDirectoryPath = LuaLanguageServerPathHelper.NormalizeLocalPath(workspaceRootDirectoryPath); _workspaceApiDirectoryPath = Path.Combine(_workspaceRootDirectoryPath, ".API"); _client = client; + _requestTimeout = requestTimeout ?? DefaultRequestTimeout; + _requestTimeoutRestartThreshold = Math.Max(1, requestTimeoutRestartThreshold); if (_client is not null) { @@ -159,6 +178,11 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) if (_client is null || _consecutiveStartupFailures >= HardStartupFailureThreshold) return false; + bool shieldCancellationForRestart = _startupSucceeded && !_client.IsReady; + CancellationToken startupCancellationToken = shieldCancellationForRestart + ? CancellationToken.None + : cancellationToken; + // Fast path: once the client is healthy, keep the workspace watcher alive and avoid taking the startup lock. if (_startupSucceeded && _client.IsReady) { @@ -166,7 +190,7 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) return true; } - await _startLock.WaitAsync(cancellationToken).ConfigureAwait(false); + await _startLock.WaitAsync(startupCancellationToken).ConfigureAwait(false); try { @@ -189,11 +213,11 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) } // Start the transport, then replay tracked documents when this is a restart rather than a cold start. - _startupSucceeded = await _client.StartAsync(cancellationToken).ConfigureAwait(false); + _startupSucceeded = await _client.StartAsync(startupCancellationToken).ConfigureAwait(false); if (_startupSucceeded && documentsToReopen.Count > 0) { - _startupSucceeded = await ReopenTrackedDocumentsAsync(documentsToReopen, cancellationToken).ConfigureAwait(false); + _startupSucceeded = await ReopenTrackedDocumentsAsync(documentsToReopen, startupCancellationToken).ConfigureAwait(false); if (!_startupSucceeded) Log.Warn("Failed to replay tracked documents after Lua language server restart."); @@ -202,6 +226,7 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) if (_startupSucceeded) { _consecutiveStartupFailures = 0; + ResetRequestTimeoutTracking(_client.TransportGeneration); _transientStartupFailureReported = false; _permanentStartupFailureReported = false; EnsureWorkspaceFileWatcherStarted(); @@ -239,7 +264,7 @@ private void EnsureWorkspaceFileWatcherStarted() if (_workspaceFileWatcher is not null || _client is null || string.IsNullOrEmpty(_workspaceRootDirectoryPath)) return; - var watcher = new LuaWorkspaceFileWatcher(_workspaceRootDirectoryPath, DispatchWorkspaceFileChangesAsync); + var watcher = new LuaWorkspaceFileWatcher(_workspaceRootDirectoryPath, DispatchWorkspaceFileChangesAsync, HandleWorkspaceWatcherFailed); if (!watcher.Start()) return; @@ -334,13 +359,62 @@ private void ReportStartupFailure(bool isPermanentFailure) "The bundled Lua language server failed to start. Lua IntelliSense will remain unavailable until TombIDE can start the server successfully. TombIDE will retry automatically when Lua IntelliSense is requested again.", false); - try - { - StartupFailed?.Invoke(failure); - } - catch (Exception exception) + RaiseStartupFailed(failure); + } + + private void HandleWorkspaceWatcherFailed(Exception? exception) + { + if (_isDisposed || Interlocked.Exchange(ref _workspaceWatcherFailureReported, 1) != 0) + return; + + Log.Warn(exception, + "Lua workspace watching is disabled for '{Workspace}'. Open editors will keep working, but external Lua workspace changes will not be forwarded until TombIDE is restarted.", + _workspaceRootDirectoryPath); + + RaiseWorkspaceWatcherFailed(new LuaWorkspaceWatcherFailure( + "The Lua workspace file watcher encountered an internal error and has been disabled for this session.\n\n" + + "Lua IntelliSense will continue to work for files edited inside TombIDE, but external workspace changes - such as Git pull updates, generated .API files, or .luarc changes - will no longer be forwarded until TombIDE is restarted.")); + } + + private void RaiseDiagnosticsUpdated(string filePath, IReadOnlyList diagnostics) + => InvokeSubscribersSafely( + DiagnosticsUpdated, + handler => ((Action>)handler)(filePath, diagnostics), + "Lua diagnostics subscriber"); + + private void RaiseSemanticTokensUpdated(string filePath, IReadOnlyList semanticTokens) + => InvokeSubscribersSafely( + SemanticTokensUpdated, + handler => ((Action>)handler)(filePath, semanticTokens), + "Lua semantic-token subscriber"); + + private void RaiseStartupFailed(LuaLanguageServerStartupFailure failure) + => InvokeSubscribersSafely( + StartupFailed, + handler => ((Action)handler)(failure), + "Lua IntelliSense startup-failure subscriber"); + + private void RaiseWorkspaceWatcherFailed(LuaWorkspaceWatcherFailure failure) + => InvokeSubscribersSafely( + WorkspaceWatcherFailed, + handler => ((Action)handler)(failure), + "Lua workspace-watcher subscriber"); + + private void InvokeSubscribersSafely(Delegate? handlers, Action invoke, string subscriberDescription) + { + if (handlers is null) + return; + + foreach (Delegate handler in handlers.GetInvocationList()) { - Log.Debug(exception, "Lua IntelliSense startup-failure notification handler threw."); + try + { + invoke(handler); + } + catch (Exception exception) + { + Log.Warn(exception, "{SubscriberDescription} threw; later subscribers will still be notified.", subscriberDescription); + } } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs index 5e33976f14..3731c1c6db 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs @@ -155,17 +155,23 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< if (string.IsNullOrWhiteSpace(label)) return null; - string insertText = itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) - && textEditElement.TryGetProperty("newText", out JsonElement newTextElement) - ? newTextElement.GetString() ?? label - : itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) - ? insertTextElement.GetString() ?? label - : label; + LuaCompletionTextEdit? textEdit = ExtractCompletionTextEdit(itemElement, out string? textEditText); + + string insertText = textEditText ?? string.Empty; + + if (string.IsNullOrWhiteSpace(insertText)) + { + insertText = itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) + ? insertTextElement.GetString() ?? label + : label; + } + + int? insertCaretOffset = null; if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) { - insertText = StripSnippetPlaceholders(insertText); + (insertText, insertCaretOffset) = StripSnippetPlaceholders(insertText); } string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) @@ -190,7 +196,86 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< BuildCompletionPriority(itemElement, textAnalysis, itemIndex), BuildCompletionIconKind(completionKind, textAnalysis), description.IsMarkdown, - resolveAsync); + resolveAsync, + textEdit, + insertCaretOffset: insertCaretOffset); + } + + private static LuaCompletionTextEdit? ExtractCompletionTextEdit(JsonElement itemElement, out string? textEditText) + { + textEditText = null; + + if (!itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) + || textEditElement.ValueKind != JsonValueKind.Object) + { + return null; + } + + textEditText = textEditElement.TryGetProperty("newText", out JsonElement newTextElement) + ? newTextElement.GetString() + : null; + + return ParseCompletionTextEdit(textEditElement); + } + + private static LuaCompletionTextEdit? ParseCompletionTextEdit(JsonElement textEditElement) + { + if (textEditElement.ValueKind != JsonValueKind.Object) + return null; + + if (textEditElement.TryGetProperty("range", out JsonElement rangeElement) + && TryParseCompletionRange(rangeElement, out LuaCompletionRange range)) + { + return new LuaCompletionTextEdit(range); + } + + if (textEditElement.TryGetProperty("insert", out JsonElement insertRangeElement) + && textEditElement.TryGetProperty("replace", out JsonElement replaceRangeElement) + && TryParseCompletionRange(insertRangeElement, out LuaCompletionRange insertRange) + && TryParseCompletionRange(replaceRangeElement, out LuaCompletionRange replaceRange)) + { + return new LuaCompletionTextEdit(insertRange, replaceRange); + } + + return null; + } + + private static bool TryParseCompletionRange(JsonElement rangeElement, out LuaCompletionRange range) + { + range = default; + + if (!TryParseCompletionPosition(rangeElement, "start", out LuaCompletionPosition start) + || !TryParseCompletionPosition(rangeElement, "end", out LuaCompletionPosition end)) + { + return false; + } + + range = new LuaCompletionRange(start, end); + return true; + } + + private static bool TryParseCompletionPosition(JsonElement parentElement, string propertyName, out LuaCompletionPosition position) + { + position = default; + + if (!parentElement.TryGetProperty(propertyName, out JsonElement positionElement) + || positionElement.ValueKind != JsonValueKind.Object) + { + return false; + } + + if (!positionElement.TryGetProperty("line", out JsonElement lineElement) + || !lineElement.TryGetInt32(out int line) + || !positionElement.TryGetProperty("character", out JsonElement characterElement) + || !characterElement.TryGetInt32(out int character) + || line < 0 + || character < 0) + { + return false; + } + + position = new LuaCompletionPosition(line, character); + return true; } private static class CompletionPriorityWeights @@ -356,12 +441,13 @@ private static MarkupContent BuildCompletionDescription(JsonElement itemElement) : new MarkupContent(normalizedText, documentation.IsMarkdown); } - private static string StripSnippetPlaceholders(string snippet) + private static (string Text, int? CaretOffset) StripSnippetPlaceholders(string snippet) { if (string.IsNullOrWhiteSpace(snippet)) - return snippet; + return (snippet, null); var builder = new StringBuilder(snippet.Length); + int? caretOffset = null; int index = 0; while (index < snippet.Length) @@ -376,20 +462,43 @@ private static string StripSnippetPlaceholders(string snippet) { string placeholder = snippet[(index + 2)..endIndex]; int separatorIndex = placeholder.IndexOf(':'); + ReadOnlySpan placeholderNumber = separatorIndex >= 0 + ? placeholder.AsSpan(0, separatorIndex) + : placeholder.AsSpan(); - if (separatorIndex >= 0 && separatorIndex < placeholder.Length - 1) - builder.Append(placeholder[(separatorIndex + 1)..]); + if (int.TryParse(placeholderNumber, out int placeholderIndex)) + { + if (separatorIndex >= 0 && separatorIndex < placeholder.Length - 1) + builder.Append(placeholder[(separatorIndex + 1)..]); + if (placeholderIndex == 0) + caretOffset ??= builder.Length; + + index = endIndex + 1; + continue; + } + + builder.Append(snippet, index, endIndex - index + 1); index = endIndex + 1; continue; } } index++; + int placeholderStart = index; while (index < snippet.Length && char.IsDigit(snippet[index])) index++; + if (placeholderStart < index) + { + if (index - placeholderStart == 1 && snippet[placeholderStart] == '0') + caretOffset ??= builder.Length; + + continue; + } + + builder.Append('$'); continue; } @@ -397,6 +506,6 @@ private static string StripSnippetPlaceholders(string snippet) index++; } - return builder.ToString(); + return (builder.ToString(), caretOffset); } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs index 2ff7f7d142..44cb321be7 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs @@ -24,6 +24,7 @@ internal sealed class LuaWorkspaceFileWatcher : IDisposable private readonly string _workspaceRootDirectoryPath; private readonly Func _dispatchAsync; + private readonly Action? _watcherFailed; private readonly ConcurrentDictionary _pendingChanges = new(StringComparer.OrdinalIgnoreCase); private readonly SemaphoreSlim _dispatchGate = new(1, 1); private readonly CancellationTokenSource _lifetimeCts = new(); @@ -32,6 +33,9 @@ internal sealed class LuaWorkspaceFileWatcher : IDisposable private FileSystemWatcher? _apiDirectoryWatcher; private FileSystemWatcher? _configWatcher; private Timer? _debounceTimer; + private int _activeDispatchCount; + private int _dispatchResourcesDisposed; + private int _watcherFailureReported; private volatile bool _isDisposed; /// @@ -39,10 +43,12 @@ internal sealed class LuaWorkspaceFileWatcher : IDisposable /// /// The workspace root directory to watch. /// The callback that forwards coalesced changes to LuaLS. - public LuaWorkspaceFileWatcher(string workspaceRootDirectoryPath, Func dispatchAsync) + public LuaWorkspaceFileWatcher(string workspaceRootDirectoryPath, Func dispatchAsync, + Action? watcherFailed = null) { _workspaceRootDirectoryPath = workspaceRootDirectoryPath; _dispatchAsync = dispatchAsync; + _watcherFailed = watcherFailed; } /// @@ -92,7 +98,7 @@ private FileSystemWatcher CreateWatcher(string filter, bool includeSubdirectorie QueueChange(e.OldFullPath, FileChangeKind.Deleted); QueueChange(e.FullPath, FileChangeKind.Created); }; - watcher.Error += (_, e) => Log.Debug(e.GetException(), "Lua workspace file watcher reported an error."); + watcher.Error += (_, e) => HandleWatcherError(e.GetException()); watcher.EnableRaisingEvents = true; return watcher; } @@ -129,6 +135,21 @@ private void OnDebounceTick(object? _) } private async Task DispatchPendingChangesAsync() + { + Interlocked.Increment(ref _activeDispatchCount); + + try + { + await DispatchPendingChangesCoreAsync().ConfigureAwait(false); + } + finally + { + if (Interlocked.Decrement(ref _activeDispatchCount) == 0 && _isDisposed) + DisposeDispatchResources(); + } + } + + private async Task DispatchPendingChangesCoreAsync() { bool dispatchGateHeld = false; @@ -164,10 +185,52 @@ private async Task DispatchPendingChangesAsync() finally { if (dispatchGateHeld) - _dispatchGate.Release(); + { + try + { + _dispatchGate.Release(); + } + catch (ObjectDisposedException) + { } + } } } + private void HandleWatcherError(Exception? exception) + { + if (_isDisposed) + return; + + StopWatching(); + + if (!_pendingChanges.IsEmpty) + _ = DispatchPendingChangesAsync(); + + if (Interlocked.Exchange(ref _watcherFailureReported, 1) != 0) + return; + + Log.Warn(exception, + "Lua workspace file watcher was disabled for '{Workspace}'. External workspace changes will no longer be forwarded to LuaLS until TombIDE is restarted.", + _workspaceRootDirectoryPath); + + try + { + _watcherFailed?.Invoke(exception); + } + catch (Exception callbackException) + { + Log.Warn(callbackException, "Lua workspace watcher failure handler threw."); + } + } + + private void StopWatching() + { + TryDisposeAndClear(ref _apiDirectoryWatcher, nameof(_apiDirectoryWatcher)); + TryDisposeAndClear(ref _luaWatcher, nameof(_luaWatcher)); + TryDisposeAndClear(ref _configWatcher, nameof(_configWatcher)); + TryDisposeAndClear(ref _debounceTimer, nameof(_debounceTimer)); + } + /// /// Releases all native file-system watchers and pending dispatch resources. /// @@ -178,31 +241,52 @@ public void Dispose() _isDisposed = true; - TryDispose(_apiDirectoryWatcher, nameof(_apiDirectoryWatcher)); - TryDispose(_luaWatcher, nameof(_luaWatcher)); - TryDispose(_configWatcher, nameof(_configWatcher)); - TryDispose(_debounceTimer, nameof(_debounceTimer)); + StopWatching(); try { _lifetimeCts.Cancel(); } catch (ObjectDisposedException) { } + if (Volatile.Read(ref _activeDispatchCount) == 0) + DisposeDispatchResources(); + } + + private void DisposeDispatchResources() + { + if (Interlocked.Exchange(ref _dispatchResourcesDisposed, 1) != 0) + return; + _lifetimeCts.Dispose(); _dispatchGate.Dispose(); } - private static void TryDispose(IDisposable? disposable, string resourceName) + private static void TryDisposeAndClear(ref T? disposable, string resourceName) where T : class, IDisposable { - if (disposable is null) + T? value = disposable; + disposable = null; + + if (value is null) return; try { - disposable.Dispose(); + value.Dispose(); } catch (Exception exception) { Log.Debug(exception, "Failed to dispose Lua workspace watcher resource '{ResourceName}'.", resourceName); } } + + internal void QueueChangeForTest(string filePath, FileChangeKind kind) + => QueueChange(filePath, kind); + + internal Task DispatchPendingChangesForTestAsync() + => DispatchPendingChangesAsync(); + + internal void ReportErrorForTest(Exception? exception) + => HandleWatcherError(exception); + + internal bool HasActiveWatchers + => _apiDirectoryWatcher is not null || _luaWatcher is not null || _configWatcher is not null; } /// diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceWatcherFailure.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceWatcherFailure.cs new file mode 100644 index 0000000000..f5e02946f4 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceWatcherFailure.cs @@ -0,0 +1,9 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Describes a workspace-watcher failure that should be surfaced to the UI. +/// +/// The user-facing failure message. +internal readonly record struct LuaWorkspaceWatcherFailure(string Message); \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml new file mode 100644 index 0000000000..5a635c67ab --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Configs/TextEditors/ColorSchemes/Lua/Default.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + and + break + do + else + elseif + end + false + for + function + goto + if + in + local + nil + not + or + repeat + return + then + true + until + while + + + \b(?:0[xX][0-9A-Fa-f]+|\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b + + diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs index 01c2d8e45a..7f803d9917 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs @@ -45,7 +45,6 @@ public sealed partial class LuaEditor private static FieldInfo? CompletionToolTipField => CompletionToolTipFieldAccessor.Value; - private CancellationTokenSource? _completionCancellationTokenSource; private readonly DispatcherTimer _completionRequestTimer = new(); private readonly DispatcherTimer _completionToolTipUpdateTimer = new(); private int _completionRequestToken; @@ -64,6 +63,15 @@ private void InitializeCompletionScheduling() } private void CloseCompletionWindow() + { + InvalidateCompletionRequests(); + CloseCompletionWindowCore(); + } + + private void CloseCompletionWindowForRefresh() + => CloseCompletionWindowCore(); + + private void CloseCompletionWindowCore() { CancelPendingCompletionRequest(); CancelCompletionToolTipUpdate(); @@ -78,6 +86,9 @@ private void CloseCompletionWindow() _completionWindow = null; } + private void InvalidateCompletionRequests() + => _completionRequestToken++; + private void InitializeLuaCompletionWindow() { InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); @@ -110,8 +121,10 @@ private async void CompletionRequestTimer_Tick(object? sender, EventArgs e) private async Task RequestCompletionAsync(int offset, char? triggerCharacter) { - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _completionCancellationTokenSource); + CancellationToken cancellationToken = CancellationToken.None; int requestToken = ++_completionRequestToken; + int requestDocumentVersion = _editorDocumentVersion; + int requestGeneration = _editorRequestGeneration; try { @@ -128,7 +141,8 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) .GetCompletionItemsAsync(FilePath, Text, Line, Column, triggerCharacter, cancellationToken) .ConfigureAwait(true); - if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + if (!IsAsyncEditorResultCurrent(cancellationToken, requestToken, _completionRequestToken, + requestDocumentVersion, requestGeneration)) return; if (items is null || items.Count == 0) @@ -142,13 +156,17 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) var brushSet = GetThemeBrushSet(); for (int i = 0; i < items.Count; i++) - completionDataItems[i] = new LuaCompletionData(items[i], brushSet); + { + LuaCompletionItem completionItem = items[i].WithRequestContext(requestDocumentVersion, requestGeneration); + completionDataItems[i] = new LuaCompletionData(completionItem, brushSet, CanApplyCompletionItem); + } - if (cancellationToken.IsCancellationRequested || requestToken != _completionRequestToken) + if (!IsAsyncEditorResultCurrent(cancellationToken, requestToken, _completionRequestToken, + requestDocumentVersion, requestGeneration)) return; // Recreate the popup from scratch so stale selection and tooltip state never leaks between requests. - CloseCompletionWindow(); + CloseCompletionWindowForRefresh(); InitializeLuaCompletionWindow(); ResizeCompletionWindow(completionDataItems); @@ -172,6 +190,42 @@ private async Task RequestCompletionAsync(int offset, char? triggerCharacter) } } + private bool CanApplyCompletionItem(LuaCompletionItem item) + => IsCompletionItemCurrent(item.RequestDocumentVersion, _editorDocumentVersion, + item.RequestGeneration, _editorRequestGeneration, IsLoaded, IsIntellisenseAvailable()); + + private void RebaseOpenCompletionItems() + { + if (_completionWindow?.CompletionList?.CompletionData is null) + return; + + for (int i = 0; i < _completionWindow.CompletionList.CompletionData.Count; i++) + { + if (_completionWindow.CompletionList.CompletionData[i] is LuaCompletionData completionData) + completionData.RebaseForCurrentDocument(_editorDocumentVersion, _editorRequestGeneration); + } + } + + private static bool IsCompletionItemCurrent(int? requestDocumentVersion, + int currentDocumentVersion, + int? requestGeneration, + int currentGeneration, + bool isEditorLoaded, + bool isIntellisenseAvailable) + { + if (!isEditorLoaded || !isIntellisenseAvailable) + return false; + + if (!requestDocumentVersion.HasValue && !requestGeneration.HasValue) + return true; + + if (!requestDocumentVersion.HasValue || !requestGeneration.HasValue) + return false; + + return requestDocumentVersion.Value == currentDocumentVersion + && requestGeneration.Value == currentGeneration; + } + private void StyleCompletionTooltip() { if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs index fe70b149c9..eafa643931 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs @@ -24,7 +24,7 @@ protected override async void HandleMouseHover(MouseEventArgs e) if (hoveredOffset == -1) return; - bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity); + bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity, allowLineFallback: false); bool canShowDiagnosticFallback = _completionWindow is null && !_signaturePopup.IsOpen; if (!TryGetHoverRequestOffset(hoveredOffset, out int hoverOffset) || !IsIntellisenseAvailable()) @@ -51,6 +51,7 @@ protected override async void HandleMouseHover(MouseEventArgs e) return; } + hasDiagnostic = TryGetDiagnosticInfo(currentHoveredOffset, out diagnosticMessage, out diagnosticSeverity, allowLineFallback: false); ShowBestHoverToolTip(hoverInfo, hasDiagnostic, diagnosticMessage, diagnosticSeverity); } catch (OperationCanceledException) diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index 22498b1aff..61feb6cf1a 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -16,8 +16,10 @@ private void BindLuaIntellisenseEvents() { InitializeCompletionScheduling(); + Document.Changed += LuaEditor_DocumentChanged; IsKeyboardFocusWithinChanged += LuaEditor_IsKeyboardFocusWithinChanged; Loaded += LuaEditor_Loaded; + TextChanged += LuaEditor_TextChanged; TextArea.TextEntering += TextArea_TextEntering; TextArea.TextEntered += TextArea_TextEntered; AddHandler(PreviewKeyDownEvent, new KeyEventHandler(TextEditor_KeyDown), true); @@ -29,6 +31,15 @@ private void BindLuaIntellisenseEvents() private void LuaEditor_Loaded(object? sender, RoutedEventArgs e) => AttachHostWindowHandlers(); + private void LuaEditor_DocumentChanged(object? sender, DocumentChangeEventArgs e) + => ClearDiagnostics(); + + private void LuaEditor_TextChanged(object? sender, EventArgs e) + { + _editorDocumentVersion++; + RebaseOpenCompletionItems(); + } + private void LuaEditor_IsKeyboardFocusWithinChanged(object? sender, DependencyPropertyChangedEventArgs e) { if (e.NewValue is bool hasKeyboardFocus && !hasKeyboardFocus) @@ -64,14 +75,14 @@ private void LuaEditor_Unloaded(object? sender, RoutedEventArgs e) { _textMateHighlighting?.Dispose(); _textMateHighlighting = null; + InvalidateAsyncEditorRequests(); CancelPendingCompletionRequest(); CancelAndDispose(ref _hoverCancellationTokenSource); - CancelAndDispose(ref _completionCancellationTokenSource); CancelCompletionToolTipUpdate(); - CancelAndDispose(ref _signatureCancellationTokenSource); + CancelAndDispose(ref _definitionCancellationTokenSource); CloseCompletionWindow(); if (_hostWindow is not null) @@ -110,6 +121,7 @@ private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs { CancelPendingCompletionRequest(); CloseCompletionWindow(); + CancelPendingSignatureHelpRefresh(); await RequestSignatureHelpAsync(CaretOffset).ConfigureAwait(true); return; } @@ -137,6 +149,9 @@ private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs } } + if (ShouldRefreshSignatureHelpAfterTextInput(e.Text)) + ScheduleSignatureHelpRefresh(); + if (!AutocompleteEnabled) return; @@ -216,4 +231,68 @@ private static void CancelAndDispose(ref CancellationTokenSource? cancellationTo private static void LogEditorFailure(string area, Exception exception) => Log.Warn(exception, "Lua editor operation '{Area}' failed.", area); + + protected override void OnAutoClosingElementSkipped(string element) + { + if (!ShouldDismissSignatureHelpOnAutoClosingSkip(element, ParenthesesClosingString)) + return; + + CancelPendingCompletionRequest(); + CloseCompletionWindow(); + DismissSignatureHelp(); + } + + private void InvalidateAsyncEditorRequests() + { + _editorRequestGeneration++; + _completionRequestToken++; + _hoverRequestToken++; + _signatureRequestToken++; + _definitionRequestToken++; + } + + private bool IsAsyncEditorResultCurrent(CancellationToken cancellationToken, + int requestToken, + int currentRequestToken, + int requestDocumentVersion, + int requestGeneration) + { + return IsAsyncEditorResultCurrent( + cancellationToken.IsCancellationRequested, + requestToken, + currentRequestToken, + requestDocumentVersion, + _editorDocumentVersion, + requestGeneration, + _editorRequestGeneration, + IsLoaded, + IsIntellisenseAvailable()); + } + + private static bool IsAsyncEditorResultCurrent(bool isCancellationRequested, + int requestToken, + int currentRequestToken, + int requestDocumentVersion, + int currentDocumentVersion, + int requestGeneration, + int currentGeneration, + bool isEditorLoaded, + bool isIntellisenseAvailable) + { + return !isCancellationRequested + && requestToken == currentRequestToken + && requestDocumentVersion == currentDocumentVersion + && requestGeneration == currentGeneration + && isEditorLoaded + && isIntellisenseAvailable; + } + + private bool ShouldRefreshSignatureHelpAfterTextInput(string? inputText) + => ShouldRefreshSignatureHelpAfterTextInput(inputText, _signaturePopup.IsOpen || _signatureRequestInFlight || _signatureRefreshPending); + + private static bool ShouldRefreshSignatureHelpAfterTextInput(string? inputText, bool isSignatureHelpActiveOrPending) + => isSignatureHelpActiveOrPending && inputText?.Length == 1; + + private static bool ShouldDismissSignatureHelpOnAutoClosingSkip(string element, string parenthesesClosingString) + => string.Equals(element, parenthesesClosingString, StringComparison.Ordinal); } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index 9f4d43d6c4..75da8b7a49 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -9,6 +9,9 @@ namespace TombLib.Scripting.Lua; public sealed partial class LuaEditor { + private CancellationTokenSource? _definitionCancellationTokenSource; + private int _definitionRequestToken; + private async void TextEditor_KeyDown(object? sender, KeyEventArgs e) { if (e.Key == Key.Escape && (_completionWindow is not null || _signaturePopup.IsOpen || _specialToolTip.IsOpen)) @@ -62,12 +65,25 @@ private async Task TryNavigateToDefinitionAsync(int offset, CancellationTo if (!LuaEditorInteractionRules.TryGetDefinitionStartOffset(Document, offset, out int definitionOffset)) return false; + CancellationToken definitionCancellationToken = ResetCancellationTokenSource(ref _definitionCancellationTokenSource); + using CancellationTokenSource? linkedCancellationTokenSource = cancellationToken.CanBeCanceled + ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, definitionCancellationToken) + : null; + + CancellationToken effectiveCancellationToken = linkedCancellationTokenSource?.Token ?? definitionCancellationToken; + int requestToken = ++_definitionRequestToken; + int requestDocumentVersion = _editorDocumentVersion; + int requestGeneration = _editorRequestGeneration; + (int Line, int Column) = GetPositionFromOffset(definitionOffset); LuaDefinitionLocation? definitionLocation = await IntellisenseProvider - .GetDefinitionAsync(FilePath, Text, Line, Column, cancellationToken) + .GetDefinitionAsync(FilePath, Text, Line, Column, effectiveCancellationToken) .ConfigureAwait(true); + if (!IsAsyncEditorResultCurrent(effectiveCancellationToken, requestToken, _definitionRequestToken, requestDocumentVersion, requestGeneration)) + return false; + if (definitionLocation is null) return false; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs index d6dbcfd7cd..3c176a5f3e 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs @@ -6,6 +6,7 @@ using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Media; +using System.Windows.Threading; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Resources; @@ -14,12 +15,17 @@ namespace TombLib.Scripting.Lua; public sealed partial class LuaEditor { private const double SignaturePopupFontSize = 14.0; + private const double SignatureHelpRefreshDebounceDelayInMilliseconds = 50.0; - private CancellationTokenSource? _signatureCancellationTokenSource; + private int _signatureRequestToken; + private int _pendingSignatureHelpOffset = -1; + private bool _signatureRefreshPending; + private bool _signatureRequestInFlight; private readonly Popup _signaturePopup = new(); private readonly Border _signaturePopupBorder = new(); private readonly ContentPresenter _signaturePopupPresenter = new(); + private readonly DispatcherTimer _signatureRefreshTimer = new(); private void InitializeSignaturePopup() { @@ -37,11 +43,16 @@ private void InitializeSignaturePopup() _signaturePopupBorder.Child = _signaturePopupPresenter; _signaturePopup.Child = _signaturePopupBorder; + + _signatureRefreshTimer.Interval = TimeSpan.FromMilliseconds(SignatureHelpRefreshDebounceDelayInMilliseconds); + _signatureRefreshTimer.Tick -= SignatureRefreshTimer_Tick; + _signatureRefreshTimer.Tick += SignatureRefreshTimer_Tick; } private void DismissSignatureHelp() { - CancelAndDispose(ref _signatureCancellationTokenSource); + CancelPendingSignatureHelpRefresh(); + InvalidateSignatureHelpRequests(); if (_signaturePopup.IsOpen) _signaturePopup.IsOpen = false; @@ -73,15 +84,13 @@ private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), panel.DesiredSize.Height + popupVerticalPadding); - if (_signaturePopup.IsOpen) - _signaturePopup.IsOpen = false; - _signaturePopupPresenter.Content = panel; _signaturePopupPresenter.InvalidateMeasure(); _signaturePopupBorder.InvalidateMeasure(); PositionSignaturePopup(popupSize); - _signaturePopup.IsOpen = true; + if (!_signaturePopup.IsOpen) + _signaturePopup.IsOpen = true; } private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double contentMaxWidth) @@ -145,13 +154,26 @@ private void PositionSignaturePopup(Size popupSize) private async Task RequestSignatureHelpAsync(int offset) { + if (_signatureRequestInFlight) + { + _pendingSignatureHelpOffset = offset; + _signatureRefreshPending = true; + return; + } + + _signatureRequestInFlight = true; + if (!IsIntellisenseAvailable()) { + _signatureRequestInFlight = false; DismissSignatureHelp(); return; } - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _signatureCancellationTokenSource); + CancellationToken cancellationToken = CancellationToken.None; + int requestToken = ++_signatureRequestToken; + int requestDocumentVersion = _editorDocumentVersion; + int requestGeneration = _editorRequestGeneration; try { @@ -161,7 +183,7 @@ private async Task RequestSignatureHelpAsync(int offset) .GetSignatureHelpAsync(FilePath, Text, Line, Column, cancellationToken) .ConfigureAwait(true); - if (cancellationToken.IsCancellationRequested) + if (!IsAsyncEditorResultCurrent(cancellationToken, requestToken, _signatureRequestToken, requestDocumentVersion, requestGeneration)) return; if (signatureInfo is null) @@ -178,10 +200,53 @@ private async Task RequestSignatureHelpAsync(int offset) { LogEditorFailure("Signature help", exception); } + finally + { + _signatureRequestInFlight = false; + + if (_signatureRefreshPending && _pendingSignatureHelpOffset >= 0) + { + _signatureRefreshTimer.Stop(); + _signatureRefreshTimer.Start(); + } + } } private void ScheduleSignatureHelpRefresh() - => Dispatcher.BeginInvoke(new Action(() => _ = RequestSignatureHelpAsync(CaretOffset))); + { + _pendingSignatureHelpOffset = CaretOffset; + _signatureRefreshPending = true; + _signatureRefreshTimer.Stop(); + _signatureRefreshTimer.Start(); + } + + private void CancelPendingSignatureHelpRefresh() + { + _signatureRefreshTimer.Stop(); + _signatureRefreshPending = false; + _pendingSignatureHelpOffset = -1; + } + + private void InvalidateSignatureHelpRequests() + { + _signatureRequestToken++; + _signatureRequestInFlight = false; + } + + private async void SignatureRefreshTimer_Tick(object? sender, EventArgs e) + { + _signatureRefreshTimer.Stop(); + + if (!_signatureRefreshPending || _pendingSignatureHelpOffset < 0) + return; + + if (_signatureRequestInFlight) + return; + + int offset = _pendingSignatureHelpOffset; + _signatureRefreshPending = false; + await RequestSignatureHelpAsync(offset).ConfigureAwait(true); + } private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo, LuaThemeBrushSet brushSet) { diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index e43234a6d3..77db7e6744 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -5,6 +5,7 @@ using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Resources; using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Lua.Utils; namespace TombLib.Scripting.Lua; @@ -22,6 +23,8 @@ public sealed partial class LuaEditor : TextEditorBase private LuaTextMateInstallation? _textMateHighlighting; private LuaThemeBrushSet? _themeBrushSet; + private int _editorDocumentVersion; + private int _editorRequestGeneration; /// /// Gets or sets the IntelliSense provider used to supply completions, hover text, diagnostics, and navigation results. @@ -40,6 +43,7 @@ public sealed partial class LuaEditor : TextEditorBase public LuaEditor(Version engineVersion) : base(engineVersion) { CommentPrefix = "--"; + TextArea.IndentationStrategy = new LuaAutoIndentationStrategy(Options); InitializeSignaturePopup(); BindLuaIntellisenseEvents(); } @@ -57,7 +61,9 @@ public override void UpdateSettings(Bases.ConfigurationBase configuration) _textMateHighlighting = null; LuaTextMateSyntaxHighlighting.TryInstall(this, theme.TextMateTheme, out _textMateHighlighting); - SyntaxHighlighting = null; + SyntaxHighlighting = _textMateHighlighting is null + ? LuaTextMateSyntaxHighlighting.LoadFallbackHighlighting() + : null; EnsureSemanticTokensColorizerAttached(); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index c2e0017651..d54cf9c437 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -3,6 +3,7 @@ using ICSharpCode.AvalonEdit.Editing; using System; using System.ComponentModel; +using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -10,6 +11,7 @@ using System.Windows.Controls; using System.Windows.Media; using TombLib.Scripting.Lua.Resources; +using TombLib.Scripting.Lua.Utils; using TombLib.Scripting.Rendering; using TombLib.Scripting.Resources; @@ -28,10 +30,12 @@ internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChange private static readonly SolidColorBrush DescriptionForegroundBrush = TextEditorColorPalette.ToolTipForeground; private static readonly object NoDescriptionSentinel = new(); + private static readonly PropertyInfo? OverstrikeModeProperty = typeof(TextArea).GetProperty("OverstrikeMode"); private readonly object _resolveSync = new(); private readonly LuaThemeBrushSet _brushSet; + private readonly Func? _canApplyItem; private LuaCompletionItem _item; private string? _displayDetail; private object? _cachedDescription; @@ -42,10 +46,12 @@ internal sealed class LuaCompletionData : ICompletionData, INotifyPropertyChange /// /// The completion item being adapted. /// The theme brushes used to render the item. - public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet) + /// Validates whether the completion item may still be applied. + public LuaCompletionData(LuaCompletionItem item, LuaThemeBrushSet brushSet, Func? canApplyItem = null) { _item = item ?? throw new ArgumentNullException(nameof(item)); _brushSet = brushSet ?? throw new ArgumentNullException(nameof(brushSet)); + _canApplyItem = canApplyItem; _displayDetail = FlattenSingleLineText(_item.Detail); } @@ -115,7 +121,42 @@ public object? Description /// The segment to replace. /// The insertion request context. public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) - => textArea.Document.Replace(completionSegment, _item.InsertText); + { + ArgumentNullException.ThrowIfNull(textArea); + ArgumentNullException.ThrowIfNull(completionSegment); + ArgumentNullException.ThrowIfNull(insertionRequestEventArgs); + + if (!CanApplyCompletionItem(_item, _canApplyItem)) + return; + + TextDocument document = textArea.Document; + string insertText = _item.InsertText; + int? insertCaretOffset = _item.InsertCaretOffset; + (int replacementOffset, int replacementLength) = ResolveCompletionSegment( + document, + completionSegment.Offset, + completionSegment.Length, + _item.TextEdit, + ShouldUseReplaceRange(textArea)); + + if (ContainsLineBreak(insertText)) + { + (string normalizedText, int? normalizedCaretOffset) = LuaIndentationStrategy.NormalizeCompletionInsertion( + insertText, + insertCaretOffset, + GetCurrentLineIndentation(document, replacementOffset), + LuaIndentationStrategy.CreateIndentationUnit( + textArea.Options.ConvertTabsToSpaces, + textArea.Options.IndentationSize, + 4)); + + insertText = normalizedText; + insertCaretOffset = normalizedCaretOffset; + } + + document.Replace(replacementOffset, replacementLength, insertText); + textArea.Caret.Offset = replacementOffset + (insertCaretOffset ?? insertText.Length); + } /// /// Resolves and returns the tooltip content for the completion item. @@ -173,6 +214,14 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in } } + internal void RebaseForCurrentDocument(int requestDocumentVersion, int requestGeneration) + { + _item = _item.WithFilteredCommitContext(requestDocumentVersion, requestGeneration); + + lock (_resolveSync) + _resolveTask = null; + } + private static string? FlattenSingleLineText(string? text) { if (string.IsNullOrWhiteSpace(text)) @@ -182,6 +231,79 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in return lines.Length == 0 ? null : string.Join(" ", lines).Trim(); } + private static bool CanApplyCompletionItem(LuaCompletionItem item, Func? canApplyItem) + => canApplyItem?.Invoke(item) ?? true; + + private static bool ContainsLineBreak(string text) + => text.IndexOfAny(['\r', '\n']) >= 0; + + private static string GetCurrentLineIndentation(TextDocument document, int offset) + { + ArgumentNullException.ThrowIfNull(document); + + DocumentLine line = document.GetLineByOffset(Math.Clamp(offset, 0, document.TextLength)); + return LuaIndentationStrategy.GetLeadingWhitespace(document.GetText(line)); + } + + private static (int Offset, int Length) ResolveCompletionSegment(TextDocument document, + int fallbackOffset, + int fallbackLength, + LuaCompletionTextEdit? textEdit, + bool useReplaceRange) + { + ArgumentNullException.ThrowIfNull(document); + + var fallbackSegment = (fallbackOffset, fallbackLength); + + if (textEdit is not LuaCompletionTextEdit completionTextEdit) + return fallbackSegment; + + LuaCompletionRange range = useReplaceRange + ? completionTextEdit.ReplacementRange + : completionTextEdit.InsertRange; + + return TryCreateCompletionSegment(document, range, out (int Offset, int Length) replacementSegment) + ? replacementSegment + : fallbackSegment; + } + + private static bool TryCreateCompletionSegment(TextDocument document, + LuaCompletionRange range, + out (int Offset, int Length) segment) + { + segment = default; + + if (!TryGetCompletionOffset(document, range.Start, out int startOffset) + || !TryGetCompletionOffset(document, range.End, out int endOffset) + || endOffset < startOffset) + { + return false; + } + + segment = (startOffset, endOffset - startOffset); + return true; + } + + private static bool TryGetCompletionOffset(TextDocument document, LuaCompletionPosition position, out int offset) + { + offset = 0; + int lineNumber = position.Line + 1; + + if (lineNumber < 1 || lineNumber > document.LineCount) + return false; + + DocumentLine line = document.GetLineByNumber(lineNumber); + + if (position.Character < 0 || position.Character > line.Length) + return false; + + offset = line.Offset + position.Character; + return true; + } + + private static bool ShouldUseReplaceRange(TextArea textArea) + => OverstrikeModeProperty?.GetValue(textArea) is true; + private Border? BuildDescriptionContent() { bool hasDetail = !string.IsNullOrWhiteSpace(_item.Detail); diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs index 569be5a797..95c12ccd85 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs @@ -4,6 +4,27 @@ namespace TombLib.Scripting.Lua.Objects; +/// +/// Represents a zero-based document position used by LSP completion text edits. +/// +public readonly record struct LuaCompletionPosition(int Line, int Character); + +/// +/// Represents a zero-based document range used by LSP completion text edits. +/// +public readonly record struct LuaCompletionRange(LuaCompletionPosition Start, LuaCompletionPosition End); + +/// +/// Describes the insert/replace ranges supplied by an LSP completion item. +/// +public readonly record struct LuaCompletionTextEdit(LuaCompletionRange InsertRange, LuaCompletionRange? ReplaceRange = null) +{ + /// + /// Gets the effective replacement range, falling back to when no distinct replace range exists. + /// + public LuaCompletionRange ReplacementRange => ReplaceRange ?? InsertRange; +} + /// /// Represents a single completion entry returned by a Lua IntelliSense provider. /// @@ -23,6 +44,10 @@ public sealed class LuaCompletionItem /// The icon category shown for the item. /// Whether should be rendered as Markdown. /// Optional callback that lazily resolves additional item data. + /// The optional LSP insert/replace edit metadata. + /// The editor document version associated with the completion request. + /// The editor request generation associated with the completion request. + /// The optional caret offset within after plain-text insertion. public LuaCompletionItem( string label, string? insertText = null, @@ -32,7 +57,11 @@ public LuaCompletionItem( double priority = 0.0, LuaCompletionIconKind iconKind = LuaCompletionIconKind.Misc, bool isDescriptionMarkdown = false, - Func>? resolveAsync = null) + Func>? resolveAsync = null, + LuaCompletionTextEdit? textEdit = null, + int? requestDocumentVersion = null, + int? requestGeneration = null, + int? insertCaretOffset = null) { Label = label; InsertText = string.IsNullOrWhiteSpace(insertText) ? label : insertText; @@ -42,6 +71,10 @@ public LuaCompletionItem( Priority = priority; IconKind = iconKind; IsDescriptionMarkdown = isDescriptionMarkdown; + TextEdit = textEdit; + RequestDocumentVersion = requestDocumentVersion; + RequestGeneration = requestGeneration; + InsertCaretOffset = insertCaretOffset; _resolveAsync = resolveAsync; } @@ -85,6 +118,26 @@ public LuaCompletionItem( /// public bool IsDescriptionMarkdown { get; } + /// + /// Gets the optional LSP insert/replace edit metadata. + /// + public LuaCompletionTextEdit? TextEdit { get; } + + /// + /// Gets the editor document version associated with the originating completion request. + /// + public int? RequestDocumentVersion { get; } + + /// + /// Gets the editor request generation associated with the originating completion request. + /// + public int? RequestGeneration { get; } + + /// + /// Gets the optional caret offset within after plain-text insertion. + /// + public int? InsertCaretOffset { get; } + /// /// Gets a value indicating whether additional item details can be resolved lazily. /// @@ -108,5 +161,71 @@ public Task ResolveAsync(CancellationToken cancellationToken /// The lazy resolve callback. /// A new completion item with the resolve callback attached. public LuaCompletionItem WithResolveCallback(Func> resolveAsync) - => new(Label, InsertText, Detail, Description, FilterText, Priority, IconKind, IsDescriptionMarkdown, resolveAsync); + => new(Label, InsertText, Detail, Description, FilterText, Priority, IconKind, IsDescriptionMarkdown, + resolveAsync, TextEdit, RequestDocumentVersion, RequestGeneration, InsertCaretOffset); + + /// + /// Returns a copy of this item with editor request metadata attached. + /// + /// The editor document version for the completion request. + /// The editor request generation for the completion request. + /// A new completion item with request metadata attached. + public LuaCompletionItem WithRequestContext(int requestDocumentVersion, int requestGeneration) + { + if (RequestDocumentVersion == requestDocumentVersion && RequestGeneration == requestGeneration) + return this; + + Func>? resolveAsync = _resolveAsync is null + ? null + : async cancellationToken => + (await _resolveAsync(cancellationToken).ConfigureAwait(false)) + .WithRequestContext(requestDocumentVersion, requestGeneration); + + return new LuaCompletionItem(Label, InsertText, Detail, Description, FilterText, Priority, IconKind, + IsDescriptionMarkdown, resolveAsync, TextEdit, requestDocumentVersion, requestGeneration, InsertCaretOffset); + } + + /// + /// Returns a copy of this item rebound to the current filtered popup state. + /// + /// The current editor document version. + /// The current editor request generation. + /// A new completion item that commits against the current completion segment. + public LuaCompletionItem WithFilteredCommitContext(int requestDocumentVersion, int requestGeneration) + { + if (RequestDocumentVersion == requestDocumentVersion + && RequestGeneration == requestGeneration + && TextEdit is null) + { + return this; + } + + Func>? resolveAsync = _resolveAsync is null + ? null + : async cancellationToken => + (await _resolveAsync(cancellationToken).ConfigureAwait(false)) + .WithFilteredCommitContext(requestDocumentVersion, requestGeneration); + + return new LuaCompletionItem(Label, InsertText, Detail, Description, FilterText, Priority, IconKind, + IsDescriptionMarkdown, resolveAsync, textEdit: null, requestDocumentVersion, requestGeneration, InsertCaretOffset); + } + + /// + /// Returns a copy of this item with resolved detail and documentation merged onto the original insertion metadata. + /// + /// The lazily resolved item. + /// A new completion item with resolved presentation data and preserved insertion metadata. + public LuaCompletionItem WithResolvedContent(LuaCompletionItem resolvedItem) + { + ArgumentNullException.ThrowIfNull(resolvedItem); + + string? detail = string.IsNullOrWhiteSpace(resolvedItem.Detail) ? Detail : resolvedItem.Detail; + string? description = string.IsNullOrWhiteSpace(resolvedItem.Description) ? Description : resolvedItem.Description; + bool isDescriptionMarkdown = string.IsNullOrWhiteSpace(resolvedItem.Description) + ? IsDescriptionMarkdown + : resolvedItem.IsDescriptionMarkdown; + + return new LuaCompletionItem(Label, InsertText, detail, description, FilterText, Priority, IconKind, + isDescriptionMarkdown, resolveAsync: null, TextEdit, RequestDocumentVersion, RequestGeneration, InsertCaretOffset); + } } diff --git a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs index 89fccc1768..49bb2eb55c 100644 --- a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs +++ b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs @@ -61,6 +61,14 @@ public interface ILuaIntellisenseProvider : IDisposable /// The document path. void CloseDocument(string filePath); + /// + /// Rekeys a tracked document to a new path while preserving any provider-side state that still applies. + /// + /// The previous document path. + /// The new document path. + /// The current document content. + void RenameDocument(string oldFilePath, string newFilePath, string content); + /// /// Requests completion items for a position within a Lua document. /// diff --git a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj index d3fc4dbd90..91479ed453 100644 --- a/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj +++ b/TombLib/TombLib.Scripting.Lua/TombLib.Scripting.Lua.csproj @@ -23,6 +23,9 @@ + + PreserveNewest + PreserveNewest diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaAutoIndentationStrategy.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaAutoIndentationStrategy.cs new file mode 100644 index 0000000000..5bfc82055c --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaAutoIndentationStrategy.cs @@ -0,0 +1,103 @@ +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Indentation; +using System; + +namespace TombLib.Scripting.Lua.Utils; + +internal sealed class LuaAutoIndentationStrategy : IIndentationStrategy +{ + private readonly TextEditorOptions _options; + + public LuaAutoIndentationStrategy(TextEditorOptions options) + { + ArgumentNullException.ThrowIfNull(options); + _options = options; + } + + public void IndentLine(TextDocument document, DocumentLine line) + { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(line); + + string lineText = document.GetText(line); + string desiredIndentation = GetDesiredIndentation(document, line, lineText); + ReplaceLeadingWhitespace(document, line, lineText, desiredIndentation); + } + + public void IndentLines(TextDocument document, int beginLine, int endLine) + { + ArgumentNullException.ThrowIfNull(document); + + if (document.LineCount == 0) + return; + + int startLine = Math.Max(1, Math.Min(beginLine, document.LineCount)); + int lastLine = Math.Max(startLine, Math.Min(endLine, document.LineCount)); + + document.BeginUpdate(); + + try + { + for (int lineNumber = startLine; lineNumber <= lastLine; lineNumber++) + IndentLine(document, document.GetLineByNumber(lineNumber)); + } + finally + { + document.EndUpdate(); + } + } + + private string GetDesiredIndentation(TextDocument document, DocumentLine line, string lineText) + { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(line); + + if (line.PreviousLine is null) + return LuaIndentationStrategy.GetLeadingWhitespace(lineText); + + DocumentLine previousLine = line.PreviousLine; + string previousLineText = document.GetText(previousLine); + string previousLineIndentation = LuaIndentationStrategy.GetLeadingWhitespace(previousLineText); + + return LuaIndentationStrategy.GetDesiredIndentation( + previousLineText, + lineText, + previousLineIndentation, + LuaIndentationStrategy.CreateIndentationUnit(_options.ConvertTabsToSpaces, _options.IndentationSize, 4), + ShouldUseSmartIndent(document, previousLine)); + } + + private static bool ShouldUseSmartIndent(TextDocument document, DocumentLine previousLine) + { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(previousLine); + + if (previousLine.Length == 0) + return true; + + return !LuaEditorInteractionRules.IsInsideCommentOrString(document, previousLine.EndOffset - 1); + } + + private static void ReplaceLeadingWhitespace(TextDocument document, DocumentLine line, string lineText, string desiredIndentation) + { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(line); + + int leadingWhitespaceLength = 0; + + while (leadingWhitespaceLength < lineText.Length + && (lineText[leadingWhitespaceLength] == ' ' || lineText[leadingWhitespaceLength] == '\t')) + { + leadingWhitespaceLength++; + } + + if (leadingWhitespaceLength == desiredIndentation.Length + && string.CompareOrdinal(lineText, 0, desiredIndentation, 0, leadingWhitespaceLength) == 0) + { + return; + } + + document.Replace(line.Offset, leadingWhitespaceLength, desiredIndentation); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs new file mode 100644 index 0000000000..3c0d5649ee --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs @@ -0,0 +1,342 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TombLib.Scripting.Lua.Utils; + +/// +/// Computes Lua-specific newline indentation and multiline completion normalization. +/// +internal static class LuaIndentationStrategy +{ + private readonly record struct TextLine(string Content, string Delimiter, int StartOffset); + + /// + /// Creates the indentation unit that should be appended for one extra indent level. + /// + public static string CreateIndentationUnit(bool convertTabsToSpaces, int indentationSize, int tabSize) + { + if (!convertTabsToSpaces) + return "\t"; + + int size = indentationSize > 0 + ? indentationSize + : tabSize > 0 + ? tabSize + : 4; + + return new string(' ', size); + } + + /// + /// Gets the leading whitespace prefix for the supplied line. + /// + public static string GetLeadingWhitespace(string lineText) + => string.IsNullOrEmpty(lineText) + ? string.Empty + : lineText[..GetLeadingWhitespaceLength(lineText)]; + + /// + /// Computes the indentation that should be applied to the current line based on the previous Lua line. + /// + public static string GetDesiredIndentation( + string previousLineText, + string currentLineText, + string previousLineIndentation, + string indentationUnit, + bool useSmartIndent) + { + previousLineText ??= string.Empty; + currentLineText ??= string.Empty; + previousLineIndentation ??= string.Empty; + indentationUnit ??= string.Empty; + + string indentation = previousLineIndentation; + + if (!useSmartIndent) + return indentation; + + if (ShouldIncreaseIndentAfterLine(previousLineText)) + indentation += indentationUnit; + + if (StartsWithDedentToken(currentLineText)) + indentation = RemoveSingleIndentLevel(indentation, indentationUnit); + + return indentation; + } + + /// + /// Builds the text that should be inserted when Enter is pressed inside Lua code. + /// + public static (string Text, int CaretOffset, int RemoveFollowingWhitespaceLength) BuildEnterInsertion( + string lineTextBeforeCaret, + string lineTextAfterCaret, + string currentLineIndentation, + string indentationUnit, + string newLineText, + bool useSmartIndent) + { + lineTextBeforeCaret ??= string.Empty; + lineTextAfterCaret ??= string.Empty; + currentLineIndentation ??= string.Empty; + indentationUnit ??= string.Empty; + newLineText = string.IsNullOrEmpty(newLineText) ? Environment.NewLine : newLineText; + + string nextLineIndentation = currentLineIndentation; + + if (useSmartIndent && ShouldIncreaseIndentAfterLine(lineTextBeforeCaret)) + nextLineIndentation += indentationUnit; + + bool shouldSplitBeforeDedent = useSmartIndent + && nextLineIndentation.Length > currentLineIndentation.Length + && StartsWithDedentToken(lineTextAfterCaret); + + if (!shouldSplitBeforeDedent) + { + string text = newLineText + nextLineIndentation; + return (text, text.Length, 0); + } + + string splitText = newLineText + nextLineIndentation + newLineText + currentLineIndentation; + return (splitText, newLineText.Length + nextLineIndentation.Length, GetLeadingWhitespaceLength(lineTextAfterCaret)); + } + + /// + /// Normalizes multiline completion insertion relative to the current line indentation. + /// + public static (string Text, int? CaretOffset) NormalizeCompletionInsertion( + string text, + int? caretOffset, + string currentLineIndentation, + string indentationUnit) + { + if (string.IsNullOrEmpty(text) || !ContainsLineBreak(text)) + return (text, caretOffset); + + List lines = SplitLines(text); + var builder = new StringBuilder(text.Length + Math.Max(0, lines.Count - 1) * currentLineIndentation.Length); + int? normalizedCaretOffset = null; + int relativeIndentLevel = 0; + + for (int i = 0; i < lines.Count; i++) + { + TextLine line = lines[i]; + int originalLeadingWhitespaceLength = GetLeadingWhitespaceLength(line.Content); + string trimmedContent = line.Content[originalLeadingWhitespaceLength..]; + int currentIndentLevel = i == 0 + ? 0 + : Math.Max(0, relativeIndentLevel - GetDedentLevel(trimmedContent)); + string normalizedIndentation = i == 0 + ? string.Empty + : BuildIndentation(currentLineIndentation, indentationUnit, currentIndentLevel); + string normalizedLineContent = trimmedContent.Length == 0 + ? normalizedIndentation + : normalizedIndentation + trimmedContent; + + if (caretOffset.HasValue + && caretOffset.Value >= line.StartOffset + && caretOffset.Value <= line.StartOffset + line.Content.Length) + { + int caretColumn = caretOffset.Value - line.StartOffset; + int normalizedLeadingWhitespaceLength = normalizedLineContent.Length - trimmedContent.Length; + int contentColumn = Math.Max(0, caretColumn - originalLeadingWhitespaceLength); + normalizedCaretOffset = builder.Length + normalizedLeadingWhitespaceLength + contentColumn; + } + + builder.Append(normalizedLineContent); + builder.Append(line.Delimiter); + relativeIndentLevel = currentIndentLevel + GetIndentIncrease(trimmedContent); + } + + if (caretOffset == text.Length) + normalizedCaretOffset = builder.Length; + + return (builder.ToString(), normalizedCaretOffset ?? caretOffset); + } + + private static string BuildIndentation(string currentLineIndentation, string indentationUnit, int indentLevel) + { + if (indentLevel <= 0) + return currentLineIndentation; + + var builder = new StringBuilder(currentLineIndentation.Length + indentationUnit.Length * indentLevel); + builder.Append(currentLineIndentation); + + for (int i = 0; i < indentLevel; i++) + builder.Append(indentationUnit); + + return builder.ToString(); + } + + private static string RemoveSingleIndentLevel(string indentation, string indentationUnit) + { + if (string.IsNullOrEmpty(indentation)) + return string.Empty; + + if (indentationUnit == "\t" && indentation[^1] == '\t') + return indentation[..^1]; + + int removeLength = indentationUnit.Length > 0 + ? Math.Min(indentationUnit.Length, indentation.Length) + : 1; + + return indentation[..^removeLength]; + } + + private static int GetDedentLevel(string lineText) + { + string codeText = LuaLineParser.ExtractCodeText(lineText).TrimStart(); + + if (string.IsNullOrEmpty(codeText)) + return 0; + + return StartsWithDedentToken(codeText) ? 1 : 0; + } + + private static int GetIndentIncrease(string lineText) + { + string codeText = LuaLineParser.ExtractCodeText(lineText).Trim(); + + if (string.IsNullOrEmpty(codeText)) + return 0; + + return ShouldIncreaseIndentAfterCode(codeText) ? 1 : 0; + } + + private static bool ShouldIncreaseIndentAfterLine(string lineText) + => ShouldIncreaseIndentAfterCode(LuaLineParser.ExtractCodeText(lineText).Trim()); + + private static bool ShouldIncreaseIndentAfterCode(string codeText) + { + if (string.IsNullOrEmpty(codeText)) + return false; + + if (StartsWithWord(codeText, "repeat") + || StartsWithWord(codeText, "else") + || StartsWithWord(codeText, "elseif") + || EndsWithWord(codeText, "then") + || EndsWithWord(codeText, "do") + || ContainsWord(codeText, "function")) + { + return true; + } + + return HasPositiveDelimiterBalance(codeText); + } + + private static bool StartsWithDedentToken(string lineText) + { + string codeText = LuaLineParser.ExtractCodeText(lineText).TrimStart(); + + if (string.IsNullOrEmpty(codeText)) + return false; + + return StartsWithWord(codeText, "end") + || StartsWithWord(codeText, "until") + || StartsWithWord(codeText, "else") + || StartsWithWord(codeText, "elseif") + || StartsWithClosingDelimiter(codeText[0]); + } + + private static bool HasPositiveDelimiterBalance(string codeText) + { + int balance = 0; + + foreach (char character in codeText) + { + balance += character switch + { + '(' or '{' or '[' => 1, + ')' or '}' or ']' => -1, + _ => 0 + }; + } + + return balance > 0; + } + + private static bool StartsWithClosingDelimiter(char character) + => character is ')' or '}' or ']'; + + private static bool StartsWithWord(string text, string word) + => text.StartsWith(word, StringComparison.Ordinal) + && (text.Length == word.Length || !LuaLineParser.IsIdentifierCharacter(text[word.Length])); + + private static bool EndsWithWord(string text, string word) + { + if (!text.EndsWith(word, StringComparison.Ordinal)) + return false; + + int wordStart = text.Length - word.Length; + return wordStart == 0 || !LuaLineParser.IsIdentifierCharacter(text[wordStart - 1]); + } + + private static bool ContainsWord(string text, string word) + { + int searchIndex = 0; + + while (searchIndex < text.Length) + { + int wordIndex = text.IndexOf(word, searchIndex, StringComparison.Ordinal); + + if (wordIndex < 0) + return false; + + bool hasLeadingBoundary = wordIndex == 0 || !LuaLineParser.IsIdentifierCharacter(text[wordIndex - 1]); + int wordEnd = wordIndex + word.Length; + bool hasTrailingBoundary = wordEnd == text.Length || !LuaLineParser.IsIdentifierCharacter(text[wordEnd]); + + if (hasLeadingBoundary && hasTrailingBoundary) + return true; + + searchIndex = wordIndex + word.Length; + } + + return false; + } + + private static bool ContainsLineBreak(string text) + => text.IndexOfAny(['\r', '\n']) >= 0; + + private static int GetLeadingWhitespaceLength(string text) + { + int length = 0; + + while (length < text.Length && char.IsWhiteSpace(text[length]) && text[length] != '\r' && text[length] != '\n') + length++; + + return length; + } + + private static List SplitLines(string text) + { + var lines = new List(); + int lineStart = 0; + int index = 0; + + while (index < text.Length) + { + if (text[index] == '\r' || text[index] == '\n') + { + int delimiterStart = index; + + if (text[index] == '\r' && index + 1 < text.Length && text[index + 1] == '\n') + index++; + + lines.Add(new TextLine( + text[lineStart..delimiterStart], + text[delimiterStart..(index + 1)], + lineStart)); + + index++; + lineStart = index; + continue; + } + + index++; + } + + lines.Add(new TextLine(text[lineStart..], string.Empty, lineStart)); + return lines; + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs index 14db9db848..8a6e270115 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaLineParser.cs @@ -257,6 +257,88 @@ public static string StripLineComment(string lineText) return builder.ToString(); } + /// + /// Extracts the code-visible characters from a line while skipping comment and string contents. + /// + /// The line text to process. + /// The characters that remain visible to Lua block-indentation heuristics. + public static string ExtractCodeText(string lineText) + { + if (string.IsNullOrEmpty(lineText)) + return string.Empty; + + var builder = new StringBuilder(lineText.Length); + ParserState state = ParserState.None; + int longBracketEqualsCount = 0; + + for (int i = 0; i < lineText.Length; i++) + { + char currentChar = lineText[i]; + + if (state == ParserState.LongComment || state == ParserState.LongString) + { + if (TryMatchLongBracketEnd(lineText, i, longBracketEqualsCount, out int endTokenLength)) + { + i += endTokenLength - 1; + state = ParserState.None; + longBracketEqualsCount = 0; + } + + continue; + } + + if (state == ParserState.SingleQuotedString || state == ParserState.DoubleQuotedString) + { + if (currentChar == '\\' && i + 1 < lineText.Length) + { + i++; + continue; + } + + if ((state == ParserState.SingleQuotedString && currentChar == '\'') + || (state == ParserState.DoubleQuotedString && currentChar == '"')) + { + state = ParserState.None; + } + + continue; + } + + if (TryMatchLongCommentStart(lineText, i, out longBracketEqualsCount, out int longCommentStartLength)) + { + state = ParserState.LongComment; + i += longCommentStartLength - 1; + continue; + } + + if (IsLineCommentStart(lineText, i)) + break; + + if (TryMatchLongBracketStart(lineText, i, out longBracketEqualsCount, out int longStringStartLength)) + { + state = ParserState.LongString; + i += longStringStartLength - 1; + continue; + } + + if (currentChar == '\'') + { + state = ParserState.SingleQuotedString; + continue; + } + + if (currentChar == '"') + { + state = ParserState.DoubleQuotedString; + continue; + } + + builder.Append(currentChar); + } + + return builder.ToString(); + } + /// /// Enumerates structural characters that remain after stripping comments and string content from a line. /// diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 2cedebca9b..29e345de27 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -506,7 +506,7 @@ private void HandleErrorToolTips(MouseEventArgs e) TryShowDiagnosticToolTip(hoveredOffset); } - protected bool TryGetDiagnosticInfo(int hoveredOffset, out string message, out TextEditorDiagnosticSeverity severity) + protected bool TryGetDiagnosticInfo(int hoveredOffset, out string message, out TextEditorDiagnosticSeverity severity, bool allowLineFallback = true) { message = null; severity = TextEditorDiagnosticSeverity.Error; @@ -516,7 +516,7 @@ protected bool TryGetDiagnosticInfo(int hoveredOffset, out string message, out T List hoveredDiagnostics = GetDiagnosticsAtOffset(hoveredOffset); - if (hoveredDiagnostics.Count == 0) + if (hoveredDiagnostics.Count == 0 && allowLineFallback) hoveredDiagnostics = GetDiagnosticsForLine(Document.GetLineByOffset(hoveredOffset)); if (hoveredDiagnostics.Count == 0) @@ -609,9 +609,13 @@ private void TryPerformElementSkip(TextCompositionEventArgs e, string element) { CaretOffset++; e.Handled = true; + OnAutoClosingElementSkipped(element); } } + protected virtual void OnAutoClosingElementSkipped(string element) + { } + #endregion Auto bracket closing #region Multiline commenting diff --git a/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs index 922aa76b0f..b866d12e33 100644 --- a/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs +++ b/TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs @@ -2,16 +2,20 @@ using System.Collections.Generic; using System.IO; using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.Highlighting; +using ICSharpCode.AvalonEdit.Highlighting.Xshd; using TextMateSharp.Grammars; using TextMateSharp.Model; using TextMateSharp.Registry; using TextMateSharp.Themes; +using System.Xml; namespace TombLib.Scripting.Highlighting { public static class LuaTextMateSyntaxHighlighting { private static readonly Lazy GrammarState = new Lazy(LoadGrammarState); + private static readonly Lazy FallbackHighlightingState = new Lazy(LoadFallbackHighlightingCore); private static readonly TextMateTokenTheme DefaultTheme = LuaBuiltInTextMateThemeDefaults.CreateDefaultTextMateTheme(); public static bool TryInstall(TextEditor editor, out LuaTextMateInstallation installation) @@ -40,6 +44,9 @@ public static bool TryInstall(TextEditor editor, TextMateTokenTheme theme, out L return true; } + public static IHighlightingDefinition LoadFallbackHighlighting() + => FallbackHighlightingState.Value; + private static IGrammar LoadGrammarState() { string grammarFilePath = Path.Combine(AppContext.BaseDirectory, "Configs", "TextEditors", "Grammars", "Lua", "lua.tmLanguage.json"); @@ -51,6 +58,18 @@ private static IGrammar LoadGrammarState() return registry.LoadGrammarFromPathSync(grammarFilePath, 0, new Dictionary()); } + private static IHighlightingDefinition LoadFallbackHighlightingCore() + { + string fallbackFilePath = Path.Combine(AppContext.BaseDirectory, "Configs", "TextEditors", "ColorSchemes", "Lua", "Default.xml"); + + if (!File.Exists(fallbackFilePath)) + return null; + + using var stream = File.OpenRead(fallbackFilePath); + using var reader = XmlReader.Create(stream); + return HighlightingLoader.Load(reader, HighlightingManager.Instance); + } + } public sealed class LuaTextMateInstallation : IDisposable diff --git a/TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs b/TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs index c57296e732..01692f4feb 100644 --- a/TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs +++ b/TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs @@ -57,9 +57,7 @@ public override void Dispose() private void Document_Changed(object sender, DocumentChangeEventArgs e) { - int startLineIndex = GetStartLineIndex(e.Offset); - int removedLineCount = GetAffectedLineCount(e.RemovedText?.Text); - int insertedLineCount = GetAffectedLineCount(e.InsertedText?.Text); + (int startLineIndex, int removedLineCount, int insertedLineCount) = GetChangeInfo(_document, e); int lineDelta = insertedLineCount - removedLineCount; lock (_syncRoot) @@ -86,6 +84,20 @@ private void Document_Changed(object sender, DocumentChangeEventArgs e) } } + internal static (int StartLineIndex, int RemovedLineCount, int InsertedLineCount) GetChangeInfo(TextDocument document, DocumentChangeEventArgs change) + { + if (document is null) + throw new ArgumentNullException(nameof(document)); + + if (change is null) + throw new ArgumentNullException(nameof(change)); + + return ( + GetStartLineIndex(document, change.Offset), + GetAffectedLineCount(change.RemovedText?.Text), + GetAffectedLineCount(change.InsertedText?.Text)); + } + private void InitializeSnapshot() { lock (_syncRoot) @@ -133,13 +145,13 @@ private string ReadDocumentLineText(int lineIndex) return _document.GetText(line.Offset, line.TotalLength); } - private int GetStartLineIndex(int offset) + private static int GetStartLineIndex(TextDocument document, int offset) { - if (_document.LineCount == 0) + if (document.LineCount == 0) return 0; - int safeOffset = Math.Max(0, Math.Min(offset, _document.TextLength)); - DocumentLine line = _document.GetLineByOffset(safeOffset); + int safeOffset = Math.Max(0, Math.Min(offset, document.TextLength)); + DocumentLine line = document.GetLineByOffset(safeOffset); return Math.Max(0, line.LineNumber - 1); } @@ -152,10 +164,18 @@ private static int CountLineBreaks(string text) for (int i = 0; i < text.Length; i++) { - if (text[i] != '\n') + if (text[i] == '\r') + { + count++; + + if (i + 1 < text.Length && text[i + 1] == '\n') + i++; + continue; + } - count++; + if (text[i] == '\n') + count++; } return count; diff --git a/TombLib/TombLib.Scripting/Properties/AssemblyInfo.cs b/TombLib/TombLib.Scripting/Properties/AssemblyInfo.cs index 96afce423d..727a7541cb 100644 --- a/TombLib/TombLib.Scripting/Properties/AssemblyInfo.cs +++ b/TombLib/TombLib.Scripting/Properties/AssemblyInfo.cs @@ -1,5 +1,6 @@ using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; using System.Runtime.Versioning; // General Information about an assembly is controlled through the following @@ -35,3 +36,4 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: InternalsVisibleTo("TombLib.Test")] diff --git a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs index 3d74755fec..1a0b2d0eec 100644 --- a/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs +++ b/TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using System.Collections.Generic; using System.Diagnostics; @@ -43,7 +45,7 @@ public static class MarkdownToolTipRenderer Uri.UriSchemeHttp, Uri.UriSchemeHttps }; - private static readonly Lazy LuaHighlighting = new Lazy(LoadLuaHighlighting); + private static readonly Lazy LuaHighlighting = new Lazy(LoadLuaHighlighting); public static FrameworkElement CreateContent(string content, Brush foreground, Brush background, bool allowScrolling = true) { @@ -252,7 +254,8 @@ private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionar { Block nextBlock = currentBlock.NextBlock; - if (TryCreateReplacementBlock(currentBlock, fencedCodeBlocks, foreground, background, allowScrolling, out Block replacementBlock)) + if (TryCreateReplacementBlock(currentBlock, fencedCodeBlocks, foreground, background, allowScrolling, out Block? replacementBlock) + && replacementBlock is not null) { blocks.InsertBefore(currentBlock, replacementBlock); blocks.Remove(currentBlock); @@ -283,7 +286,7 @@ private static void ReplaceCodeBlocks(BlockCollection blocks, IReadOnlyDictionar } } - private static bool TryCreateReplacementBlock(Block block, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background, bool allowScrolling, out Block replacementBlock) + private static bool TryCreateReplacementBlock(Block block, IReadOnlyDictionary fencedCodeBlocks, Brush foreground, Brush background, bool allowScrolling, out Block? replacementBlock) { replacementBlock = null; @@ -293,7 +296,8 @@ private static bool TryCreateReplacementBlock(Block block, IReadOnlyDictionary maxVisibleHeight + ? ScrollBarVisibility.Auto + : ScrollBarVisibility.Hidden; + + if (allowScrolling) + editor.PreviewMouseWheel += ScrollHost_PreviewMouseWheel; + + return new Border + { + Background = CreateCodeBackground(background), + BorderBrush = CreateCodeBorder(background), + BorderThickness = new Thickness(1.0), + CornerRadius = new CornerRadius(3.0), + Padding = new Thickness(8.0, 6.0, 8.0, 6.0), + Margin = new Thickness(0.0, 4.0, 0.0, 6.0), + MaxWidth = ToolTipTextMaxWidth, + Child = editor + }; + } + + internal static TextEditor CreateCodeBlockEditor(string? language, string code, Brush foreground) { string normalizedCode = NormalizeCodeBlockText(code); @@ -326,7 +360,9 @@ private static FrameworkElement CreateCodeBlockElement(string language, string c FontFamily = CodeFontFamily, FontSize = CodeFontSize, ShowLineNumbers = false, - WordWrap = true + WordWrap = true, + Focusable = false, + IsTabStop = false }; editor.Options.AllowScrollBelowDocument = false; @@ -335,36 +371,20 @@ private static FrameworkElement CreateCodeBlockElement(string language, string c editor.Options.HighlightCurrentLine = false; editor.Options.ShowBoxForControlCharacters = false; editor.TextArea.Margin = new Thickness(0.0); + editor.TextArea.Focusable = false; + editor.TextArea.IsTabStop = false; + KeyboardNavigation.SetIsTabStop(editor, false); + KeyboardNavigation.SetIsTabStop(editor.TextArea, false); + // Tooltip code-block editors are intentionally passive: they reuse TextMate highlighting when available, + // but do not own any unload-driven disposal hook because tooltip hosts can unload and reuse the same editor. if (!string.Equals(language?.Trim(), "lua", StringComparison.OrdinalIgnoreCase) || !LuaTextMateSyntaxHighlighting.TryInstall(editor, out _)) { editor.SyntaxHighlighting = ResolveHighlighting(language); } - double lineHeight = GetEditorLineHeight(editor); - double maxVisibleHeight = Math.Max(lineHeight + 4.0, Math.Ceiling(MaxVisibleCodeBlockLines * lineHeight) + 2.0); - double desiredHeight = Math.Max(lineHeight + 4.0, MeasureWrappedCodeHeight(normalizedCode, ToolTipTextMaxWidth, lineHeight)); - - editor.Height = Math.Min(desiredHeight, maxVisibleHeight); - editor.VerticalScrollBarVisibility = allowScrolling && desiredHeight > maxVisibleHeight - ? ScrollBarVisibility.Auto - : ScrollBarVisibility.Hidden; - - if (allowScrolling) - editor.PreviewMouseWheel += ScrollHost_PreviewMouseWheel; - - return new Border - { - Background = CreateCodeBackground(background), - BorderBrush = CreateCodeBorder(background), - BorderThickness = new Thickness(1.0), - CornerRadius = new CornerRadius(3.0), - Padding = new Thickness(8.0, 6.0, 8.0, 6.0), - Margin = new Thickness(0.0, 4.0, 0.0, 6.0), - MaxWidth = ToolTipTextMaxWidth, - Child = editor - }; + return editor; } private static double GetEditorLineHeight(TextEditor editor) @@ -520,15 +540,15 @@ private static FrameworkElement CreateFallbackContent(string content, Brush fore private static void HyperlinkHost_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { - Hyperlink hyperlink = (e.OriginalSource as DependencyObject)?.FindAncestorOrSelf(); + Hyperlink? hyperlink = (e.OriginalSource as DependencyObject)?.FindAncestorOrSelf(); if (hyperlink is not null && TryOpenHyperlink(hyperlink.NavigateUri)) e.Handled = true; } - private static bool TryOpenHyperlink(Uri uri) + private static bool TryOpenHyperlink(Uri? uri) { - if (!IsSupportedHyperlink(uri)) + if (uri is null || !IsSupportedHyperlink(uri)) return false; try @@ -542,12 +562,12 @@ private static bool TryOpenHyperlink(Uri uri) } } - private static bool IsSupportedHyperlink(Uri uri) + private static bool IsSupportedHyperlink(Uri? uri) => uri is not null && uri.IsAbsoluteUri && SupportedHyperlinkSchemes.Contains(uri.Scheme); private static void ScrollHost_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { - ScrollViewer scrollViewer = sender as ScrollViewer ?? (sender as DependencyObject)?.FindVisualDescendant(); + ScrollViewer? scrollViewer = sender as ScrollViewer ?? (sender as DependencyObject)?.FindVisualDescendant(); if (scrollViewer is null || scrollViewer.ScrollableHeight <= 0.0) return; @@ -565,7 +585,7 @@ private static string NormalizeLineEndings(string text) .Replace("\r\n", "\n", StringComparison.Ordinal) .Replace('\r', '\n'); - private static IHighlightingDefinition ResolveHighlighting(string language) + private static IHighlightingDefinition? ResolveHighlighting(string? language) { if (string.IsNullOrWhiteSpace(language)) return null; @@ -575,7 +595,7 @@ private static IHighlightingDefinition ResolveHighlighting(string language) if (normalizedLanguage == "lua") return LuaHighlighting.Value; - IHighlightingDefinition definition = HighlightingManager.Instance.GetDefinition(normalizedLanguage); + IHighlightingDefinition? definition = HighlightingManager.Instance.GetDefinition(normalizedLanguage); if (definition is not null) return definition; @@ -598,7 +618,7 @@ private static IHighlightingDefinition ResolveHighlighting(string language) }; } - private static IHighlightingDefinition LoadLuaHighlighting() + private static IHighlightingDefinition? LoadLuaHighlighting() { string xmlFilePath = Path.Combine(AppContext.BaseDirectory, "Configs", "TextEditors", "ColorSchemes", "Lua", "Default.xml"); diff --git a/TombLib/TombLib.Test/LuaCompletionDataTests.cs b/TombLib/TombLib.Test/LuaCompletionDataTests.cs new file mode 100644 index 0000000000..51709af244 --- /dev/null +++ b/TombLib/TombLib.Test/LuaCompletionDataTests.cs @@ -0,0 +1,74 @@ +using ICSharpCode.AvalonEdit.Document; +using System.Reflection; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaCompletionDataTests +{ + [TestMethod] + public void ResolveCompletionSegment_UsesInsertRangeByDefault() + { + (int offset, int length) = InvokeResolveCompletionSegment( + new TextDocument("abcdef"), + fallbackOffset: 1, + fallbackLength: 2, + new LuaCompletionTextEdit( + new LuaCompletionRange(new LuaCompletionPosition(0, 2), new LuaCompletionPosition(0, 3)), + new LuaCompletionRange(new LuaCompletionPosition(0, 2), new LuaCompletionPosition(0, 5))), + useReplaceRange: false); + + Assert.AreEqual(2, offset); + Assert.AreEqual(1, length); + } + + [TestMethod] + public void ResolveCompletionSegment_UsesReplaceRangeWhenRequested() + { + (int offset, int length) = InvokeResolveCompletionSegment( + new TextDocument("abcdef"), + fallbackOffset: 1, + fallbackLength: 2, + new LuaCompletionTextEdit( + new LuaCompletionRange(new LuaCompletionPosition(0, 2), new LuaCompletionPosition(0, 3)), + new LuaCompletionRange(new LuaCompletionPosition(0, 2), new LuaCompletionPosition(0, 5))), + useReplaceRange: true); + + Assert.AreEqual(2, offset); + Assert.AreEqual(3, length); + } + + [TestMethod] + public void ResolveCompletionSegment_FallsBackWhenTextEditRangeIsInvalid() + { + (int offset, int length) = InvokeResolveCompletionSegment( + new TextDocument("abc"), + fallbackOffset: 1, + fallbackLength: 2, + new LuaCompletionTextEdit( + new LuaCompletionRange(new LuaCompletionPosition(4, 0), new LuaCompletionPosition(4, 1))), + useReplaceRange: false); + + Assert.AreEqual(1, offset); + Assert.AreEqual(2, length); + } + + private static (int Offset, int Length) InvokeResolveCompletionSegment(TextDocument document, + int fallbackOffset, + int fallbackLength, + LuaCompletionTextEdit? textEdit, + bool useReplaceRange) + { + MethodInfo method = typeof(LuaCompletionData).GetMethod( + "ResolveCompletionSegment", + BindingFlags.NonPublic | BindingFlags.Static, + binder: null, + [typeof(TextDocument), typeof(int), typeof(int), typeof(LuaCompletionTextEdit?), typeof(bool)], + modifiers: null) + ?? throw new InvalidOperationException("Private static method 'ResolveCompletionSegment' was not found."); + + return ((int Offset, int Length))(method.Invoke(null, [document, fallbackOffset, fallbackLength, textEdit, useReplaceRange]) + ?? throw new InvalidOperationException("Private static method 'ResolveCompletionSegment' returned null.")); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaCompletionItemTests.cs b/TombLib/TombLib.Test/LuaCompletionItemTests.cs new file mode 100644 index 0000000000..80509ee937 --- /dev/null +++ b/TombLib/TombLib.Test/LuaCompletionItemTests.cs @@ -0,0 +1,50 @@ +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaCompletionItemTests +{ + [TestMethod] + public async Task WithRequestContext_PreservesRequestMetadataAcrossResolve() + { + var item = new LuaCompletionItem( + "spawn", + insertText: "spawn", + resolveAsync: _ => Task.FromResult(new LuaCompletionItem("spawn", detail: "function", insertCaretOffset: 2)), + insertCaretOffset: 2) + .WithRequestContext(4, 7); + + LuaCompletionItem resolvedItem = await item.ResolveAsync(); + + Assert.AreEqual(4, resolvedItem.RequestDocumentVersion); + Assert.AreEqual(7, resolvedItem.RequestGeneration); + Assert.AreEqual("function", resolvedItem.Detail); + Assert.AreEqual(2, resolvedItem.InsertCaretOffset); + } + + [TestMethod] + public async Task WithFilteredCommitContext_DropsTextEditAndPreservesResolveMetadata() + { + LuaCompletionTextEdit textEdit = new( + new LuaCompletionRange(new LuaCompletionPosition(0, 2), new LuaCompletionPosition(0, 5))); + + var item = new LuaCompletionItem( + "Color", + insertText: "Color", + textEdit: textEdit, + resolveAsync: _ => Task.FromResult(new LuaCompletionItem("Color", detail: "enum", textEdit: textEdit))) + .WithFilteredCommitContext(6, 2); + + Assert.AreEqual(6, item.RequestDocumentVersion); + Assert.AreEqual(2, item.RequestGeneration); + Assert.IsNull(item.TextEdit); + + LuaCompletionItem resolvedItem = await item.ResolveAsync(); + + Assert.AreEqual("enum", resolvedItem.Detail); + Assert.IsNull(resolvedItem.TextEdit); + Assert.AreEqual(6, resolvedItem.RequestDocumentVersion); + Assert.AreEqual(2, resolvedItem.RequestGeneration); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs new file mode 100644 index 0000000000..59a7887c4e --- /dev/null +++ b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs @@ -0,0 +1,309 @@ +using System; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Threading; +using TombLib.Scripting.Lua; + +namespace TombLib.Test; + +[TestClass] +public class LuaEditorIntellisenseStateTests +{ + [TestMethod] + public void ShouldRefreshSignatureHelpAfterTextInput_ReturnsTrueWhenSignatureHelpIsActiveOrPending() + { + bool shouldRefresh = InvokePrivateStaticBooleanMethod( + "ShouldRefreshSignatureHelpAfterTextInput", + [typeof(string), typeof(bool)], + "a", + true); + + Assert.IsTrue(shouldRefresh); + } + + [TestMethod] + public void ShouldRefreshSignatureHelpAfterTextInput_ReturnsFalseWhenSignatureHelpIsInactive() + { + bool shouldRefresh = InvokePrivateStaticBooleanMethod( + "ShouldRefreshSignatureHelpAfterTextInput", + [typeof(string), typeof(bool)], + "a", + false); + + Assert.IsFalse(shouldRefresh); + } + + [TestMethod] + public void ShouldDismissSignatureHelpOnAutoClosingSkip_ReturnsTrueOnlyForMatchingParenthesis() + { + bool shouldDismissMatchingParenthesis = InvokePrivateStaticBooleanMethod( + "ShouldDismissSignatureHelpOnAutoClosingSkip", + [typeof(string), typeof(string)], + ")", + ")"); + + bool shouldDismissOtherElement = InvokePrivateStaticBooleanMethod( + "ShouldDismissSignatureHelpOnAutoClosingSkip", + [typeof(string), typeof(string)], + "]", + ")"); + + Assert.IsTrue(shouldDismissMatchingParenthesis); + Assert.IsFalse(shouldDismissOtherElement); + } + + [TestMethod] + public void IsAsyncEditorResultCurrent_ReturnsTrueForCurrentLoadedAvailableRequest() + { + bool isCurrent = InvokePrivateStaticBooleanMethod( + "IsAsyncEditorResultCurrent", + [typeof(bool), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)], + false, + 3, + 3, + 8, + 8, + 2, + 2, + true, + true); + + Assert.IsTrue(isCurrent); + } + + [TestMethod] + public void IsAsyncEditorResultCurrent_RejectsCanceledOrStaleResults() + { + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsAsyncEditorResultCurrent", + [typeof(bool), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)], + true, + 3, + 3, + 8, + 8, + 2, + 2, + true, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsAsyncEditorResultCurrent", + [typeof(bool), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)], + false, + 3, + 4, + 8, + 8, + 2, + 2, + true, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsAsyncEditorResultCurrent", + [typeof(bool), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)], + false, + 3, + 3, + 8, + 9, + 2, + 2, + true, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsAsyncEditorResultCurrent", + [typeof(bool), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)], + false, + 3, + 3, + 8, + 8, + 2, + 3, + true, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsAsyncEditorResultCurrent", + [typeof(bool), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)], + false, + 3, + 3, + 8, + 8, + 2, + 2, + false, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsAsyncEditorResultCurrent", + [typeof(bool), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(bool)], + false, + 3, + 3, + 8, + 8, + 2, + 2, + true, + false)); + } + + [TestMethod] + public void IsCompletionItemCurrent_ReturnsTrueForMatchingMetadata() + { + bool isCurrent = InvokePrivateStaticBooleanMethod( + "IsCompletionItemCurrent", + [typeof(int?), typeof(int), typeof(int?), typeof(int), typeof(bool), typeof(bool)], + 8, + 8, + 2, + 2, + true, + true); + + Assert.IsTrue(isCurrent); + } + + [TestMethod] + public void IsCompletionItemCurrent_AllowsUnstampedItemsButRejectsStaleOrIncompleteMetadata() + { + Assert.IsTrue(InvokePrivateStaticBooleanMethod( + "IsCompletionItemCurrent", + [typeof(int?), typeof(int), typeof(int?), typeof(int), typeof(bool), typeof(bool)], + null, + 8, + null, + 2, + true, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsCompletionItemCurrent", + [typeof(int?), typeof(int), typeof(int?), typeof(int), typeof(bool), typeof(bool)], + 8, + 9, + 2, + 2, + true, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsCompletionItemCurrent", + [typeof(int?), typeof(int), typeof(int?), typeof(int), typeof(bool), typeof(bool)], + 8, + 8, + null, + 2, + true, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsCompletionItemCurrent", + [typeof(int?), typeof(int), typeof(int?), typeof(int), typeof(bool), typeof(bool)], + 8, + 8, + 2, + 2, + false, + true)); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "IsCompletionItemCurrent", + [typeof(int?), typeof(int), typeof(int?), typeof(int), typeof(bool), typeof(bool)], + 8, + 8, + 2, + 2, + true, + false)); + } + + [TestMethod] + public void CloseCompletionWindow_InvalidatesPendingRequests_ButRefreshCloseDoesNot() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + + SetPrivateField(editor, "_completionRequestToken", 5); + InvokePrivateInstanceMethod(editor, "CloseCompletionWindow"); + Assert.AreEqual(6, GetPrivateField(editor, "_completionRequestToken")); + + InvokePrivateInstanceMethod(editor, "CloseCompletionWindowForRefresh"); + Assert.AreEqual(6, GetPrivateField(editor, "_completionRequestToken")); + }); + } + + private static bool InvokePrivateStaticBooleanMethod(string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = typeof(LuaEditor).GetMethod(methodName, + BindingFlags.Static | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Private static method '{methodName}' was not found."); + + return (bool)(method.Invoke(null, arguments) + ?? throw new InvalidOperationException($"Private static method '{methodName}' returned null.")); + } + + private static void InvokePrivateInstanceMethod(object instance, string methodName) + { + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private instance method '{methodName}' was not found."); + + method.Invoke(instance, null); + } + + private static T GetPrivateField(object instance, string fieldName) + { + FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return (T)(field.GetValue(instance) + ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); + } + + private static void SetPrivateField(object instance, string fieldName, object value) + { + FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + field.SetValue(instance, value); + } + + private static void RunInSta(Action action) + { + Exception? capturedException = null; + using var completed = new ManualResetEventSlim(false); + + var thread = new Thread(() => + { + try + { + action(); + } + catch (Exception exception) + { + capturedException = exception; + } + finally + { + completed.Set(); + } + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + completed.Wait(); + thread.Join(); + + if (capturedException is not null) + ExceptionDispatchInfo.Capture(capturedException).Throw(); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaIndentationStrategyTests.cs b/TombLib/TombLib.Test/LuaIndentationStrategyTests.cs new file mode 100644 index 0000000000..6bb1b5a672 --- /dev/null +++ b/TombLib/TombLib.Test/LuaIndentationStrategyTests.cs @@ -0,0 +1,52 @@ +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.Document; +using TombLib.Scripting.Lua.Utils; + +namespace TombLib.Test; + +[TestClass] +public class LuaIndentationStrategyTests +{ + [TestMethod] + public void IndentLine_AfterThen_AddsIndentToNewLine() + { + var strategy = new LuaAutoIndentationStrategy(new TextEditorOptions + { + ConvertTabsToSpaces = true, + IndentationSize = 4 + }); + var document = new TextDocument("if value then\r\n"); + + strategy.IndentLine(document, document.GetLineByNumber(2)); + + Assert.AreEqual("if value then\r\n ", document.Text); + } + + [TestMethod] + public void IndentLine_BeforeEnd_DedentsCurrentLineWithoutExtraInsertion() + { + var strategy = new LuaAutoIndentationStrategy(new TextEditorOptions + { + ConvertTabsToSpaces = true, + IndentationSize = 4 + }); + var document = new TextDocument("if value then\r\n end"); + + strategy.IndentLine(document, document.GetLineByNumber(2)); + + Assert.AreEqual("if value then\r\nend", document.Text); + } + + [TestMethod] + public void NormalizeCompletionInsertion_DedentsEndLineAndPreservesCaretAndCrLf() + { + (string text, int? caretOffset) = LuaIndentationStrategy.NormalizeCompletionInsertion( + "if condition then\r\n\t\r\nend", + "if condition then\r\n\t".Length, + " ", + " "); + + Assert.AreEqual("if condition then\r\n \r\n end", text); + Assert.AreEqual("if condition then\r\n ".Length, caretOffset); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs index 43405b0a91..7d4def92ce 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs @@ -54,10 +54,9 @@ public void Dispose_WritesGracefulShutdownMessages() using Process process = StartDisposableProcess(); using var outputStream = new RecordingStream(); using var client = new LuaLanguageServerClient(@"C:\Workspace", process.StartInfo.FileName, static () => new { }); + object session = CreateTransportSession(1, process, Stream.Null, outputStream); - SetPrivateField(client, "_process", process); - SetPrivateField(client, "_inputStream", Stream.Null); - SetPrivateField(client, "_outputStream", outputStream); + SetActiveSession(client, session); client.Dispose(); @@ -72,12 +71,13 @@ public async Task HandleServerRequestAsync_SemanticTokensRefresh_AcknowledgesAnd { await using var outputStream = new RecordingStream(); using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + object session = CreateTransportSession(1, process: null, Stream.Null, outputStream); bool refreshRequested = false; - SetPrivateField(client, "_outputStream", outputStream); client.SemanticTokensRefreshRequested += () => refreshRequested = true; await InvokePrivateTaskAsync(client, "HandleServerRequestAsync", + session, JsonSerializer.SerializeToElement(7L), "workspace/semanticTokens/refresh", default(JsonElement)).ConfigureAwait(false); @@ -118,11 +118,10 @@ public async Task ReadHeadersAndPayloadAsync_ReadsChunkedFrameAcrossBoundaries() using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); string payloadJson = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"value\":42}}"; byte[] frame = CreateLspFrame(payloadJson); + object session = CreateTransportSession(1, process: null, new ChunkedReadStream(SplitBytes(frame, 5, 7, 11, 3)), Stream.Null); - SetPrivateField(client, "_inputStream", new ChunkedReadStream(SplitBytes(frame, 5, 7, 11, 3))); - - int? contentLength = await InvokePrivateTaskAsync(client, "ReadHeadersAsync").ConfigureAwait(false); - byte[]? payload = await InvokePrivateTaskAsync(client, "ReadPayloadAsync", contentLength!.Value).ConfigureAwait(false); + int? contentLength = await InvokePrivateTaskAsync(client, "ReadHeadersAsync", session).ConfigureAwait(false); + byte[]? payload = await InvokePrivateTaskAsync(client, "ReadPayloadAsync", session, contentLength!.Value).ConfigureAwait(false); Assert.AreEqual(Encoding.UTF8.GetByteCount(payloadJson), contentLength); Assert.IsNotNull(payload); @@ -136,12 +135,11 @@ public async Task ReadLoopAsync_HandlesChunkedSemanticTokensRefreshRequest() using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); bool refreshRequested = false; byte[] frame = CreateLspFrame("{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"workspace/semanticTokens/refresh\"}"); + object session = CreateTransportSession(1, process: null, new ChunkedReadStream(SplitBytes(frame, 4, 9, 6, 13)), outputStream); - SetPrivateField(client, "_inputStream", new ChunkedReadStream(SplitBytes(frame, 4, 9, 6, 13))); - SetPrivateField(client, "_outputStream", outputStream); client.SemanticTokensRefreshRequested += () => refreshRequested = true; - await InvokePrivateTaskAsync(client, "ReadLoopAsync").ConfigureAwait(false); + await InvokePrivateTaskAsync(client, "ReadLoopAsync", session).ConfigureAwait(false); string writtenPayload = outputStream.GetWrittenText(); @@ -155,11 +153,11 @@ public async Task ReadLoopAsync_FailsPendingRequestsWhenConnectionCloses() { using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); var pendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + object session = CreateTransportSession(1, process: null, new ChunkedReadStream(), Stream.Null); - GetPendingRequests(client).TryAdd(42, pendingRequest); - SetPrivateField(client, "_inputStream", new ChunkedReadStream()); + GetPendingRequests(session).TryAdd(42, pendingRequest); - await InvokePrivateTaskAsync(client, "ReadLoopAsync").ConfigureAwait(false); + await InvokePrivateTaskAsync(client, "ReadLoopAsync", session).ConfigureAwait(false); await Assert.ThrowsExceptionAsync(() => pendingRequest.Task).ConfigureAwait(false); } @@ -170,17 +168,36 @@ public async Task ReadLoopAsync_CompletesPendingRequestFromChunkedResponse() using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); var pendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); byte[] frame = CreateLspFrame("{\"jsonrpc\":\"2.0\",\"id\":42,\"result\":{\"label\":\"ok\"}}"); + object session = CreateTransportSession(1, process: null, new ChunkedReadStream(SplitBytes(frame, 6, 8, 5, 9)), Stream.Null); - GetPendingRequests(client).TryAdd(42, pendingRequest); - SetPrivateField(client, "_inputStream", new ChunkedReadStream(SplitBytes(frame, 6, 8, 5, 9))); + GetPendingRequests(session).TryAdd(42, pendingRequest); - await InvokePrivateTaskAsync(client, "ReadLoopAsync").ConfigureAwait(false); + await InvokePrivateTaskAsync(client, "ReadLoopAsync", session).ConfigureAwait(false); JsonElement result = await pendingRequest.Task.ConfigureAwait(false); Assert.AreEqual("ok", result.GetProperty("label").GetString()); } + [TestMethod] + public async Task ReadLoopAsync_OldTransportGenerationDoesNotFailActiveSessionRequests() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + object oldSession = CreateTransportSession(1, process: null, new ChunkedReadStream(), Stream.Null); + object newSession = CreateTransportSession(2, process: null, new ChunkedReadStream(), Stream.Null); + var oldPendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var newPendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + GetPendingRequests(oldSession).TryAdd(41, oldPendingRequest); + GetPendingRequests(newSession).TryAdd(42, newPendingRequest); + SetActiveSession(client, newSession); + + await InvokePrivateTaskAsync(client, "ReadLoopAsync", oldSession).ConfigureAwait(false); + + await Assert.ThrowsExceptionAsync(() => oldPendingRequest.Task).ConfigureAwait(false); + Assert.IsFalse(newPendingRequest.Task.IsCompleted); + } + private static Process StartDisposableProcess() { var startInfo = new ProcessStartInfo @@ -198,12 +215,42 @@ private static Process StartDisposableProcess() ?? throw new InvalidOperationException("Unable to start the disposable test process."); } - private static void SetPrivateField(LuaLanguageServerClient client, string fieldName, object? value) + private static void SetPrivateField(object instance, string fieldName, object? value) { - FieldInfo field = typeof(LuaLanguageServerClient).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) + FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - field.SetValue(client, value); + field.SetValue(instance, value); + } + + private static object CreateTransportSession(long generation, Process? process, Stream inputStream, Stream outputStream) + { + Type sessionType = typeof(LuaLanguageServerClient).GetNestedType("LuaLanguageServerTransportSession", BindingFlags.NonPublic) + ?? throw new InvalidOperationException("Nested type 'LuaLanguageServerTransportSession' was not found."); + + ConstructorInfo constructor = sessionType.GetConstructor( + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + [typeof(long), typeof(Process), typeof(Stream), typeof(Stream)], + modifiers: null) + ?? throw new InvalidOperationException("Lua transport session constructor was not found."); + + return constructor.Invoke([generation, process, inputStream, outputStream]); + } + + private static void SetActiveSession(LuaLanguageServerClient client, object session) + { + SetPrivateField(client, "_activeSession", session); + SetPrivateField(client, "_activeTransportGeneration", GetTransportGeneration(session)); + } + + private static long GetTransportGeneration(object session) + { + PropertyInfo property = session.GetType().GetProperty("Generation", BindingFlags.Instance | BindingFlags.Public) + ?? throw new InvalidOperationException("Transport session property 'Generation' was not found."); + + return (long)(property.GetValue(session) + ?? throw new InvalidOperationException("Transport session generation value was null.")); } private static void InvokePrivateMethod(object instance, string methodName, params object?[] parameters) @@ -262,12 +309,13 @@ private static void CancelLifetime(LuaLanguageServerClient client) ((CancellationTokenSource)field.GetValue(client)!).Cancel(); } - private static ConcurrentDictionary> GetPendingRequests(LuaLanguageServerClient client) + private static ConcurrentDictionary> GetPendingRequests(object session) { - FieldInfo field = typeof(LuaLanguageServerClient).GetField("_pendingRequests", BindingFlags.Instance | BindingFlags.NonPublic) - ?? throw new InvalidOperationException("Private field '_pendingRequests' was not found."); + PropertyInfo property = session.GetType().GetProperty("PendingRequests", BindingFlags.Instance | BindingFlags.Public) + ?? throw new InvalidOperationException("Transport session property 'PendingRequests' was not found."); - return (ConcurrentDictionary>)field.GetValue(client)!; + return (ConcurrentDictionary>)(property.GetValue(session) + ?? throw new InvalidOperationException("Transport session pending request map was null.")); } private static byte[] CreateLspFrame(string json) diff --git a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs index 2df61f3a54..b03a4c2261 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs @@ -55,6 +55,56 @@ public async Task GetCompletionItemsAsync_ResolvesCompletionItemDetailsWhenServe client.GetSentMethodNames()); } + [TestMethod] + public async Task GetCompletionItemsAsync_ResolvePreservesOriginalInsertionMetadata() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + SupportsCompletionResolve = true, + CompletionResponse = JsonSerializer.SerializeToElement(new + { + items = new object[] + { + new + { + label = "spawn", + kind = 3, + textEdit = new + { + newText = "spawn", + range = new + { + start = new { line = 0, character = 0 }, + end = new { line = 0, character = 3 } + } + } + } + } + }), + CompletionResolveResponse = JsonSerializer.SerializeToElement(new + { + label = "spawn", + kind = 3, + insertText = "shouldNotReplaceOriginalInsertText", + detail = "function", + documentation = "Spawn docs." + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + IReadOnlyList items = await provider.GetCompletionItemsAsync(filePath, "spa", 0, 3); + LuaCompletionItem resolvedItem = await items[0].ResolveAsync(); + + Assert.AreEqual("spawn", resolvedItem.InsertText); + Assert.AreEqual(items[0].TextEdit, resolvedItem.TextEdit); + Assert.AreEqual("function", resolvedItem.Detail); + Assert.AreEqual("Spawn docs.", resolvedItem.Description); + } + [TestMethod] public async Task DispatchWorkspaceFileChangesAsync_RefreshesConfigurationWhenApiLibraryChanges() { @@ -124,6 +174,182 @@ public async Task GetHoverAsync_RaisesTransientAndPermanentStartupFailuresOnceEa Assert.AreEqual(3, client.StartCallCount); } + [TestMethod] + public async Task RenameDocument_MovesDiagnosticsAndSemanticTokensToNewPath() + { + const string workspaceRoot = @"C:\Workspace"; + const string oldFilePath = @"C:\Workspace\Scripts\test.lua"; + const string newFilePath = @"C:\Workspace\Scripts\renamed.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + SemanticTokenTypes = ["variable"] + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + var semanticTokensUpdated = new TaskCompletionSource>(TaskCreationOptions.RunContinuationsAsynchronously); + + provider.SemanticTokensUpdated += (filePath, tokens) => + { + if (string.Equals(filePath, oldFilePath, StringComparison.OrdinalIgnoreCase)) + semanticTokensUpdated.TrySetResult(tokens); + }; + + provider.OpenDocument(oldFilePath, content); + + Task completedTask = await Task.WhenAny(semanticTokensUpdated.Task, Task.Delay(TimeSpan.FromSeconds(1))).ConfigureAwait(false); + Assert.AreSame(semanticTokensUpdated.Task, completedTask); + + client.PublishDiagnostics(CreateDiagnostics(oldFilePath, 1, 6, 11, "Current warning.")); + + Assert.AreEqual(1, provider.GetDiagnostics(oldFilePath).Count); + Assert.AreEqual(1, provider.GetSemanticTokens(oldFilePath).Count); + + provider.RenameDocument(oldFilePath, newFilePath, content); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didClose", 1, TimeSpan.FromSeconds(1))); + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 2, TimeSpan.FromSeconds(1))); + + Assert.AreEqual(0, provider.GetDiagnostics(oldFilePath).Count); + Assert.AreEqual(0, provider.GetSemanticTokens(oldFilePath).Count); + Assert.AreEqual(1, provider.GetDiagnostics(newFilePath).Count); + Assert.AreEqual(1, provider.GetSemanticTokens(newFilePath).Count); + + CollectionAssert.AreEqual( + new[] + { + "textDocument/didOpen", + "textDocument/semanticTokens/full", + "textDocument/didClose", + "textDocument/didOpen" + }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task RenameDocument_PreservesOpenReferenceCountsAcrossMultipleTabs() + { + const string workspaceRoot = @"C:\Workspace"; + const string oldFilePath = @"C:\Workspace\Scripts\test.lua"; + const string newFilePath = @"C:\Workspace\Scripts\renamed.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(oldFilePath, content); + provider.OpenDocument(oldFilePath, content); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 1, TimeSpan.FromSeconds(1))); + + provider.RenameDocument(oldFilePath, newFilePath, content); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didClose", 1, TimeSpan.FromSeconds(1))); + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 2, TimeSpan.FromSeconds(1))); + + provider.CloseDocument(newFilePath); + + Assert.IsFalse(await client.WaitForMethodCountAsync("textDocument/didClose", 2, TimeSpan.FromMilliseconds(250))); + + provider.CloseDocument(newFilePath); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didClose", 2, TimeSpan.FromSeconds(1))); + } + + [TestMethod] + public async Task GetHoverAsync_RestartsAfterConsecutiveTimeoutsOnSameTransportGeneration() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + TimedOutHoverRequestsRemaining = 2, + HoverResponse = JsonSerializer.SerializeToElement(new + { + contents = new + { + kind = "markdown", + value = "Hover docs." + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider( + workspaceRoot, + client, + requestTimeout: TimeSpan.FromMilliseconds(50), + requestTimeoutRestartThreshold: 2); + + LuaHoverInfo? firstHover = await provider.GetHoverAsync(filePath, content, 0, 0); + LuaHoverInfo? secondHover = await provider.GetHoverAsync(filePath, content, 0, 0); + LuaHoverInfo? thirdHover = await provider.GetHoverAsync(filePath, content, 0, 0); + + Assert.IsNull(firstHover); + Assert.IsNull(secondHover); + Assert.IsNotNull(thirdHover); + Assert.AreEqual("Hover docs.", thirdHover.Content); + Assert.AreEqual(1, client.MarkTransportUnhealthyCallCount); + Assert.AreEqual(2, client.StartCallCount); + + client.TimedOutHoverRequestsRemaining = 1; + + LuaHoverInfo? fourthHover = await provider.GetHoverAsync(filePath, content, 0, 0); + + Assert.IsNull(fourthHover); + Assert.AreEqual(1, client.MarkTransportUnhealthyCallCount); + + CollectionAssert.AreEqual( + new[] + { + "textDocument/didOpen", + "textDocument/hover", + "textDocument/hover", + "textDocument/didOpen", + "textDocument/hover", + "textDocument/hover" + }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task GetHoverAsync_ShieldsRestartFromRequestCancellationAfterConnectionDrop() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + FailStartWhenCancellationRequested = true, + HoverResponse = JsonSerializer.SerializeToElement(new + { + contents = new + { + kind = "markdown", + value = "Hover docs." + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + await provider.GetHoverAsync(filePath, content, 0, 0); + + client.IsReady = false; + + using var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.Cancel(); + + await provider.GetHoverAsync(filePath, content, 0, 0, cancellationTokenSource.Token); + + Assert.AreEqual(2, client.StartCallCount); + Assert.AreEqual(2, client.StartCancellationTokenCanBeCanceled.Count); + Assert.IsFalse(client.StartCancellationTokenCanBeCanceled[1]); + } + [TestMethod] public async Task UpdateDocument_SendsFullTextChangeWhenServerAdvertisesFullSync() { @@ -219,6 +445,31 @@ public async Task DiagnosticsPublished_IgnoresVersionMismatchAndStoresMatchingVe Assert.AreEqual(12, diagnostics[0].EndOffset); } + [TestMethod] + public async Task DiagnosticsPublished_OneSubscriberExceptionDoesNotSuppressLaterSubscribers() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + int notifiedSubscribers = 0; + + provider.DiagnosticsUpdated += (_, _) => + { + notifiedSubscribers++; + throw new InvalidOperationException("Simulated diagnostics subscriber failure."); + }; + + provider.DiagnosticsUpdated += (_, _) => notifiedSubscribers++; + + await provider.GetHoverAsync(filePath, content, 0, 0); + client.PublishDiagnostics(CreateDiagnostics(filePath, 1, 6, 12, "Current warning.")); + + Assert.AreEqual(2, notifiedSubscribers); + } + [TestMethod] public async Task UpdateDocument_WaitsForEarlierOpenNotificationToFinish() { @@ -330,6 +581,44 @@ public async Task GetHoverAsync_RetriesWorkspaceWatcherStartAfterWorkspaceDirect } } + [TestMethod] + public async Task WorkspaceWatcherFailure_IsRaisedOnceAndStopsWatching() + { + string workspaceRoot = Path.Combine(Path.GetTempPath(), "LuaWatcherFailure_" + Guid.NewGuid().ToString("N")); + string filePath = Path.Combine(workspaceRoot, "Scripts", "test.lua"); + const string content = "local value = 1"; + + try + { + Directory.CreateDirectory(workspaceRoot); + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + var failures = new List(); + + provider.WorkspaceWatcherFailed += failure => failures.Add(failure); + + await provider.GetHoverAsync(filePath, content, 0, 0); + + LuaWorkspaceFileWatcher watcher = GetWorkspaceWatcher(provider) + ?? throw new AssertFailedException("Expected the workspace watcher to start."); + + Assert.IsTrue(watcher.HasActiveWatchers); + + watcher.ReportErrorForTest(new IOException("Simulated watcher failure.")); + watcher.ReportErrorForTest(new IOException("Simulated watcher failure.")); + + Assert.AreEqual(1, failures.Count); + Assert.IsFalse(watcher.HasActiveWatchers); + Assert.IsTrue(failures[0].Message.Contains("disabled", StringComparison.OrdinalIgnoreCase)); + } + finally + { + if (Directory.Exists(workspaceRoot)) + Directory.Delete(workspaceRoot, recursive: true); + } + } + [TestMethod] public async Task SemanticTokensRefreshRequested_RefreshesTrackedDocuments() { @@ -368,6 +657,78 @@ public async Task SemanticTokensRefreshRequested_RefreshesTrackedDocuments() client.GetSentMethodNames()); } + [TestMethod] + public async Task SemanticTokensRefreshRequested_FallsBackToFullRefreshAfterInvalidDelta() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + SemanticTokenTypes = ["variable"], + SupportsSemanticTokensDelta = true + }; + + client.EnqueueSemanticTokensFullResponse(JsonSerializer.SerializeToElement(new + { + data = new[] { 0, 6, 5, 0, 0 }, + resultId = "tokens-1" + })); + + client.EnqueueSemanticTokensDeltaResponse(JsonSerializer.SerializeToElement(new + { + resultId = "tokens-2" + })); + + client.EnqueueSemanticTokensFullResponse(JsonSerializer.SerializeToElement(new + { + data = new[] { 0, 6, 5, 0, 0 }, + resultId = "tokens-3" + })); + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + var firstRefresh = new TaskCompletionSource>(TaskCreationOptions.RunContinuationsAsynchronously); + var secondRefresh = new TaskCompletionSource>(TaskCreationOptions.RunContinuationsAsynchronously); + + provider.SemanticTokensUpdated += (updatedFilePath, tokens) => + { + if (!string.Equals(updatedFilePath, filePath, StringComparison.OrdinalIgnoreCase)) + return; + + if (!firstRefresh.Task.IsCompleted) + firstRefresh.TrySetResult(tokens); + else + secondRefresh.TrySetResult(tokens); + }; + + await provider.GetHoverAsync(filePath, content, 0, 0); + + client.PublishSemanticTokensRefreshRequested(); + + Task firstCompletedTask = await Task.WhenAny(firstRefresh.Task, Task.Delay(TimeSpan.FromSeconds(1))).ConfigureAwait(false); + Assert.AreSame(firstRefresh.Task, firstCompletedTask); + + client.PublishSemanticTokensRefreshRequested(); + + Task secondCompletedTask = await Task.WhenAny(secondRefresh.Task, Task.Delay(TimeSpan.FromSeconds(1))).ConfigureAwait(false); + Assert.AreSame(secondRefresh.Task, secondCompletedTask); + + IReadOnlyList semanticTokens = await secondRefresh.Task.ConfigureAwait(false); + + Assert.AreEqual(1, semanticTokens.Count); + CollectionAssert.AreEqual( + new[] + { + "textDocument/didOpen", + "textDocument/hover", + "textDocument/semanticTokens/full", + "textDocument/semanticTokens/full/delta", + "textDocument/semanticTokens/full" + }, + client.GetSentMethodNames()); + } + private static JsonElement CreateDiagnostics(string filePath, int version, int startCharacter, int endCharacter, string message) => JsonSerializer.SerializeToElement(new { @@ -409,23 +770,32 @@ private static async Task InvokePrivateTaskAsync(object instance, string methodN private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient { + private readonly object _syncRoot = new(); private readonly List<(string Method, JsonElement Parameters)> _sentNotifications = []; private readonly List _sentMethodNames = []; + private readonly Queue _semanticTokensDeltaResponses = []; + private readonly Queue _semanticTokensFullResponses = []; private TaskCompletionSource? _openNotificationGate; private readonly TaskCompletionSource _changeNotificationObserved = new(TaskCreationOptions.RunContinuationsAsynchronously); private readonly TaskCompletionSource _closeNotificationObserved = new(TaskCreationOptions.RunContinuationsAsynchronously); public bool IsReady { get; set; } = true; + public long TransportGeneration { get; private set; } public bool StartResult { get; set; } = true; public JsonElement CompletionResponse { get; set; } public JsonElement CompletionResolveResponse { get; set; } + public JsonElement HoverResponse { get; set; } public LuaTextDocumentSyncKind TextDocumentSyncKind { get; set; } = LuaTextDocumentSyncKind.Incremental; public IReadOnlyList SemanticTokenTypes { get; set; } = []; public IReadOnlyList SemanticTokenModifiers { get; set; } = []; public bool SupportsCompletionResolve { get; set; } - public bool SupportsSemanticTokensDelta => false; + public bool SupportsSemanticTokensDelta { get; set; } + public bool FailStartWhenCancellationRequested { get; set; } public int StartCallCount { get; private set; } + public int MarkTransportUnhealthyCallCount { get; private set; } + public int TimedOutHoverRequestsRemaining { get; set; } public bool ThrowIOExceptionOnNextDidChange { get; set; } + public List StartCancellationTokenCanBeCanceled { get; } = []; public event Action? DiagnosticsPublished; @@ -434,14 +804,32 @@ private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient public Task StartAsync(CancellationToken cancellationToken) { StartCallCount++; + StartCancellationTokenCanBeCanceled.Add(cancellationToken.CanBeCanceled); + + if (FailStartWhenCancellationRequested && cancellationToken.IsCancellationRequested) + throw new OperationCanceledException(cancellationToken); + IsReady = StartResult; + + if (StartResult) + TransportGeneration++; + return Task.FromResult(StartResult); } + public void MarkTransportUnhealthy() + { + MarkTransportUnhealthyCallCount++; + IsReady = false; + } + public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) { - _sentMethodNames.Add(method); - _sentNotifications.Add((method, JsonSerializer.SerializeToElement(parameters))); + lock (_syncRoot) + { + _sentMethodNames.Add(method); + _sentNotifications.Add((method, JsonSerializer.SerializeToElement(parameters))); + } if (method == "textDocument/didChange") { @@ -465,7 +853,20 @@ public Task SendNotificationAsync(string method, object parameters, Cancellation public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) { - _sentMethodNames.Add(method); + lock (_syncRoot) + _sentMethodNames.Add(method); + + if (method == "textDocument/hover") + { + if (TimedOutHoverRequestsRemaining > 0) + { + TimedOutHoverRequestsRemaining--; + return WaitForCancellationAsync(cancellationToken); + } + + if (HoverResponse.ValueKind != JsonValueKind.Undefined) + return Task.FromResult(HoverResponse); + } if (method == "textDocument/completion" && CompletionResponse.ValueKind != JsonValueKind.Undefined) return Task.FromResult(CompletionResponse); @@ -473,8 +874,23 @@ public Task SendRequestAsync(string method, object parameters, Canc if (method == "completionItem/resolve" && CompletionResolveResponse.ValueKind != JsonValueKind.Undefined) return Task.FromResult(CompletionResolveResponse); + if (method == "textDocument/semanticTokens/full/delta") + { + if (_semanticTokensDeltaResponses.Count > 0) + return Task.FromResult(_semanticTokensDeltaResponses.Dequeue()); + + return Task.FromResult(JsonSerializer.SerializeToElement(new + { + edits = Array.Empty(), + resultId = "tokens-delta" + })); + } + if (method == "textDocument/semanticTokens/full") { + if (_semanticTokensFullResponses.Count > 0) + return Task.FromResult(_semanticTokensFullResponses.Dequeue()); + return Task.FromResult(JsonSerializer.SerializeToElement(new { data = new[] { 0, 6, 5, 0, 0 }, @@ -485,14 +901,21 @@ public Task SendRequestAsync(string method, object parameters, Canc return Task.FromResult(JsonSerializer.SerializeToElement(new { })); } - public string[] GetSentMethodNames() => [.. _sentMethodNames]; + public string[] GetSentMethodNames() + { + lock (_syncRoot) + return [.. _sentMethodNames]; + } public JsonElement GetLastNotificationParameters(string method) { - for (int i = _sentNotifications.Count - 1; i >= 0; i--) + lock (_syncRoot) { - if (string.Equals(_sentNotifications[i].Method, method, StringComparison.Ordinal)) - return _sentNotifications[i].Parameters; + for (int i = _sentNotifications.Count - 1; i >= 0; i--) + { + if (string.Equals(_sentNotifications[i].Method, method, StringComparison.Ordinal)) + return _sentNotifications[i].Parameters; + } } throw new InvalidOperationException($"Notification '{method}' was not observed."); @@ -517,12 +940,55 @@ public async Task WaitForNotificationAsync(string method, TimeSpan timeout return ReferenceEquals(completedTask, observedNotification); } + public async Task WaitForMethodCountAsync(string method, int expectedCount, TimeSpan timeout) + { + DateTime deadline = DateTime.UtcNow + timeout; + + while (DateTime.UtcNow < deadline) + { + if (GetSentMethodCount(method) >= expectedCount) + return true; + + await Task.Delay(10).ConfigureAwait(false); + } + + return GetSentMethodCount(method) >= expectedCount; + } + public void PublishDiagnostics(JsonElement parameters) => DiagnosticsPublished?.Invoke(parameters); public void PublishSemanticTokensRefreshRequested() => SemanticTokensRefreshRequested?.Invoke(); + public void EnqueueSemanticTokensFullResponse(JsonElement response) + => _semanticTokensFullResponses.Enqueue(response); + + public void EnqueueSemanticTokensDeltaResponse(JsonElement response) + => _semanticTokensDeltaResponses.Enqueue(response); + + private int GetSentMethodCount(string method) + { + int count = 0; + + lock (_syncRoot) + { + for (int i = 0; i < _sentMethodNames.Count; i++) + { + if (string.Equals(_sentMethodNames[i], method, StringComparison.Ordinal)) + count++; + } + } + + return count; + } + + private static async Task WaitForCancellationAsync(CancellationToken cancellationToken) + { + await Task.Delay(Timeout.InfiniteTimeSpan, cancellationToken).ConfigureAwait(false); + return default; + } + public void Dispose() { } } diff --git a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs index dfc4b22765..fe770067c1 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs @@ -32,6 +32,86 @@ public void ParseCompletionItem_UsesParameterIconWhenDetailContainsParameter() Assert.AreEqual(LuaCompletionIconKind.Parameter, item.IconKind); } + [TestMethod] + public void ParseCompletionItem_ParsesTextEditRange() + { + JsonElement itemElement = JsonSerializer.SerializeToElement(new + { + label = "print", + kind = 3, + textEdit = new + { + newText = "print", + range = new + { + start = new { line = 1, character = 2 }, + end = new { line = 1, character = 5 } + } + } + }); + + LuaCompletionItem? item = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, 0); + + Assert.IsNotNull(item); + Assert.AreEqual("print", item.InsertText); + Assert.IsNotNull(item.TextEdit); + Assert.AreEqual(new LuaCompletionPosition(1, 2), item.TextEdit.Value.InsertRange.Start); + Assert.AreEqual(new LuaCompletionPosition(1, 5), item.TextEdit.Value.InsertRange.End); + Assert.IsNull(item.TextEdit.Value.ReplaceRange); + } + + [TestMethod] + public void ParseCompletionItem_ParsesInsertReplaceEditRanges() + { + JsonElement itemElement = JsonSerializer.SerializeToElement(new + { + label = "print", + kind = 3, + textEdit = new + { + newText = "print", + insert = new + { + start = new { line = 0, character = 1 }, + end = new { line = 0, character = 3 } + }, + replace = new + { + start = new { line = 0, character = 1 }, + end = new { line = 0, character = 6 } + } + } + }); + + LuaCompletionItem? item = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, 0); + + Assert.IsNotNull(item); + Assert.IsNotNull(item.TextEdit); + Assert.AreEqual(new LuaCompletionPosition(0, 1), item.TextEdit.Value.InsertRange.Start); + Assert.AreEqual(new LuaCompletionPosition(0, 3), item.TextEdit.Value.InsertRange.End); + Assert.AreEqual(new LuaCompletionPosition(0, 1), item.TextEdit.Value.ReplaceRange!.Value.Start); + Assert.AreEqual(new LuaCompletionPosition(0, 6), item.TextEdit.Value.ReplaceRange!.Value.End); + Assert.AreEqual(new LuaCompletionPosition(0, 6), item.TextEdit.Value.ReplacementRange.End); + } + + [TestMethod] + public void ParseCompletionItem_StripsSnippetAndPreservesFinalCaretOffset() + { + JsonElement itemElement = JsonSerializer.SerializeToElement(new + { + label = "if", + kind = 15, + insertText = "if ${1:condition} then\r\n\t$0\r\nend", + insertTextFormat = 2 + }); + + LuaCompletionItem? item = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, 0); + + Assert.IsNotNull(item); + Assert.AreEqual("if condition then\r\n\t\r\nend", item.InsertText); + Assert.AreEqual("if condition then\r\n\t".Length, item.InsertCaretOffset); + } + [TestMethod] public void ParseCompletionItems_DeduplicatesLabelAndInsertTextCaseSensitively() { diff --git a/TombLib/TombLib.Test/LuaLineParserTests.cs b/TombLib/TombLib.Test/LuaLineParserTests.cs index 9df235f9d1..d451d56da6 100644 --- a/TombLib/TombLib.Test/LuaLineParserTests.cs +++ b/TombLib/TombLib.Test/LuaLineParserTests.cs @@ -32,4 +32,12 @@ public void EnumerateStructuralCharacters_SkipsLongStringContents() string result = new(LuaLineParser.EnumerateStructuralCharacters("{ [[ignored } text]] }").ToArray()); Assert.AreEqual("{ }", result); } + + [TestMethod] + public void ExtractCodeText_RemovesQuotedAndCommentText() + { + string result = LuaLineParser.ExtractCodeText("if value == \"then\" then -- comment"); + + Assert.AreEqual("if value == then ", result); + } } diff --git a/TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs b/TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs new file mode 100644 index 0000000000..cd7702fdd6 --- /dev/null +++ b/TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs @@ -0,0 +1,17 @@ +using ICSharpCode.AvalonEdit.Highlighting; +using TombLib.Scripting.Highlighting; + +namespace TombLib.Test; + +[TestClass] +public class LuaTextMateSyntaxHighlightingTests +{ + [TestMethod] + public void LoadFallbackHighlighting_ReturnsLuaDefinition() + { + IHighlightingDefinition? highlighting = LuaTextMateSyntaxHighlighting.LoadFallbackHighlighting(); + + Assert.IsNotNull(highlighting); + Assert.AreEqual("Lua", highlighting.Name); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaWorkspaceFileWatcherTests.cs b/TombLib/TombLib.Test/LuaWorkspaceFileWatcherTests.cs new file mode 100644 index 0000000000..89af0048ef --- /dev/null +++ b/TombLib/TombLib.Test/LuaWorkspaceFileWatcherTests.cs @@ -0,0 +1,43 @@ +using System.Runtime.ExceptionServices; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; + +namespace TombLib.Test; + +[TestClass] +public class LuaWorkspaceFileWatcherTests +{ + [TestMethod] + public async Task Dispose_DuringActiveDispatch_DoesNotFaultDispatch() + { + string workspaceRoot = Path.Combine(Path.GetTempPath(), "LuaWatcherDispose_" + Guid.NewGuid().ToString("N")); + var dispatchStarted = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var allowDispatchToFinish = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + + try + { + Directory.CreateDirectory(workspaceRoot); + + using var watcher = new LuaWorkspaceFileWatcher(workspaceRoot, async (_, _) => + { + dispatchStarted.TrySetResult(true); + await allowDispatchToFinish.Task.ConfigureAwait(false); + }); + + watcher.QueueChangeForTest(Path.Combine(workspaceRoot, "test.lua"), FileChangeKind.Changed); + Task dispatchTask = watcher.DispatchPendingChangesForTestAsync(); + + Task completedTask = await Task.WhenAny(dispatchStarted.Task, Task.Delay(TimeSpan.FromSeconds(1))).ConfigureAwait(false); + Assert.AreSame(dispatchStarted.Task, completedTask); + + watcher.Dispose(); + allowDispatchToFinish.TrySetResult(true); + + await dispatchTask.ConfigureAwait(false); + } + finally + { + if (Directory.Exists(workspaceRoot)) + Directory.Delete(workspaceRoot, recursive: true); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs b/TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs new file mode 100644 index 0000000000..152e760e2f --- /dev/null +++ b/TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs @@ -0,0 +1,55 @@ +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Windows.Media; +using ICSharpCode.AvalonEdit; +using TombLib.Scripting.Rendering; + +namespace TombLib.Test; + +[TestClass] +public class MarkdownToolTipRendererTests +{ + [TestMethod] + public void CreateCodeBlockEditor_DoesNotAcceptKeyboardFocus() + { + RunInSta(() => + { + TextEditor editor = MarkdownToolTipRenderer.CreateCodeBlockEditor("lua", "local value = 1", Brushes.White); + + Assert.IsFalse(editor.Focusable); + Assert.IsFalse(editor.IsTabStop); + Assert.IsFalse(editor.TextArea.Focusable); + Assert.IsFalse(editor.TextArea.IsTabStop); + }); + } + + private static void RunInSta(Action action) + { + Exception? capturedException = null; + using var completed = new ManualResetEventSlim(false); + + var thread = new Thread(() => + { + try + { + action(); + } + catch (Exception exception) + { + capturedException = exception; + } + finally + { + completed.Set(); + } + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + completed.Wait(); + thread.Join(); + + if (capturedException is not null) + ExceptionDispatchInfo.Capture(capturedException).Throw(); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/TextMateHighlightingTests.cs b/TombLib/TombLib.Test/TextMateHighlightingTests.cs new file mode 100644 index 0000000000..e51afcf805 --- /dev/null +++ b/TombLib/TombLib.Test/TextMateHighlightingTests.cs @@ -0,0 +1,83 @@ +using System.Windows.Media; +using ICSharpCode.AvalonEdit.Document; +using TombLib.Scripting.Highlighting; +using TombLib.Scripting.Lua; + +namespace TombLib.Test; + +[TestClass] +public class TextMateHighlightingTests +{ + [TestMethod] + public void GetChangeInfo_CountsCrLfAsTwoAffectedLines() + { + (int startLineIndex, int removedLineCount, int insertedLineCount) = ApplyChangeAndGetInfo("alpha", document => document.Insert(5, "\r\nbeta")); + + Assert.AreEqual(0, startLineIndex); + Assert.AreEqual(1, removedLineCount); + Assert.AreEqual(2, insertedLineCount); + } + + [TestMethod] + public void GetChangeInfo_CountsLfAsTwoAffectedLines() + { + (int startLineIndex, int removedLineCount, int insertedLineCount) = ApplyChangeAndGetInfo("alpha", document => document.Insert(5, "\nbeta")); + + Assert.AreEqual(0, startLineIndex); + Assert.AreEqual(1, removedLineCount); + Assert.AreEqual(2, insertedLineCount); + } + + [TestMethod] + public void GetChangeInfo_CountsLoneCrAsTwoAffectedLines() + { + (int startLineIndex, int removedLineCount, int insertedLineCount) = ApplyChangeAndGetInfo("alpha", document => document.Insert(5, "\rbeta")); + + Assert.AreEqual(0, startLineIndex); + Assert.AreEqual(1, removedLineCount); + Assert.AreEqual(2, insertedLineCount); + } + + [TestMethod] + public void Resolve_UsesCommaSeparatedBundledFunctionSelectors() + { + var resolver = new TextMateThemeStyleResolver(new LuaEditorConfiguration + { + SelectedThemeName = "Tomorrow Light" + }.Theme.TextMateTheme); + + TextMateHighlightingStyle style = resolver.Resolve(["source.lua", "support.function.library.lua"]); + + Assert.AreEqual("#FF4271AE", GetForegroundColor(style)); + } + + [TestMethod] + public void Resolve_PrefersMoreSpecificBundledSelectorsOverBroaderParents() + { + var resolver = new TextMateThemeStyleResolver(new LuaEditorConfiguration + { + SelectedThemeName = "SharpLua" + }.Theme.TextMateTheme); + + TextMateHighlightingStyle style = resolver.Resolve(["source.lua", "support.type.property-name.lua"]); + + Assert.AreEqual("#FFD7B8FF", GetForegroundColor(style)); + } + + private static (int StartLineIndex, int RemovedLineCount, int InsertedLineCount) ApplyChangeAndGetInfo(string originalText, Action changeAction) + { + var document = new TextDocument(originalText); + DocumentChangeEventArgs? change = null; + + document.Changed += (_, args) => change = args; + changeAction(document); + + return TextMateDocumentLineList.GetChangeInfo(document, change!); + } + + private static string GetForegroundColor(TextMateHighlightingStyle style) + { + Assert.IsNotNull(style.Foreground); + return ((SolidColorBrush)style.Foreground).Color.ToString(); + } +} \ No newline at end of file From 061be3169a03796ce1c9f06060ee25be7a3ce60e Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 10 May 2026 13:44:29 +0100 Subject: [PATCH 28/34] Cleanups part 1 --- ...ntellisense_And_AvalonEdit_Cleanup_Plan.md | 344 ++++++++ ...LanguageServerResponseParser.Completion.cs | 10 +- .../Completion/LuaSnippetPlaceholderResult.cs | 6 + .../LuaLanguageServerDiagnosticsParser.cs | 0 .../LuaPublishedDiagnostics.cs | 0 .../{ => Documents}/LuaDocumentLineOffsets.cs | 0 .../LuaDocumentRenameRequest.cs | 0 .../{ => Documents}/LuaDocumentSnapshot.cs | 0 .../LuaDocumentSynchronizationKind.cs | 0 .../LuaDocumentSynchronizationRequest.cs | 0 .../LuaDocumentSynchronizationResult.cs | 10 + .../LuaIncrementalEditCalculator.cs | 0 .../LuaIntellisenseDocumentManager.cs | 8 +- .../LuaTextDocumentSyncKind.cs | 0 .../LuaLanguageServerResponseParser.Hover.cs | 24 + .../Client}/ILuaLanguageServerClient.cs | 0 .../LuaLanguageServerClient.Protocol.cs | 0 .../LuaLanguageServerClient.Transport.cs | 0 .../Client}/LuaLanguageServerClient.cs | 0 .../Pathing}/LuaLanguageServerLocator.cs | 0 .../Pathing}/LuaLanguageServerPathHelper.cs | 0 .../LuaLanguageServerSettingsFactory.cs | 0 .../LuaLanguageServerStartupFailure.cs | 0 .../Startup}/LuaProcessJobObject.cs | 0 .../Workspace}/LuaWorkspaceFileWatcher.cs | 0 .../Workspace}/LuaWorkspaceWatcherFailure.cs | 0 ...LuaLanguageServerResponseParser.Shared.cs} | 0 ...LanguageServerResponseParser.Navigation.cs | 15 - ...ageServerIntellisenseProvider.Documents.cs | 16 +- ...uageServerIntellisenseProvider.Requests.cs | 0 ...rverIntellisenseProvider.SemanticTokens.cs | 37 +- .../LuaLanguageServerIntellisenseProvider.cs | 0 .../Services/LuaIntellisense/README.md | 31 + ...LanguageServerSemanticTokensDeltaParser.cs | 0 .../LuaSemanticTokensDecodeResult.cs | 15 + .../LuaSemanticTokensDeltaState.cs | 8 + ...guageServerResponseParser.SignatureHelp.cs | 0 .../Completion/LuaCompletionController.cs | 522 ++++++++++++ .../Editor/Hover/LuaHoverController.cs | 176 ++++ .../LuaDefinitionNavigationController.cs | 82 ++ .../LuaSignatureHelpController.cs | 354 ++++++++ .../LuaEditor.Completion.cs | 487 ----------- .../TombLib.Scripting.Lua/LuaEditor.Hover.cs | 154 ---- .../LuaEditor.Intellisense.cs | 24 +- .../LuaEditor.Navigation.cs | 62 +- .../LuaEditor.SignatureHelp.cs | 312 ------- TombLib/TombLib.Scripting.Lua/LuaEditor.cs | 10 +- .../Objects/LuaCompletionData.cs | 6 +- TombLib/TombLib.Scripting.Lua/README.md | 28 + .../Utils/LuaCompletionNormalizationResult.cs | 6 + .../Utils/LuaEnterInsertionResult.cs | 6 + .../Utils/LuaIndentationStrategy.cs | 15 +- .../LuaEditorCompletionWindowTests.cs | 473 +++++++++++ .../LuaEditorIntellisenseStateTests.cs | 766 +++++++++++++++++- .../LuaIndentationStrategyTests.cs | 38 +- ...LanguageServerIntellisenseProviderTests.cs | 63 ++ .../LuaLanguageServerRealIntegrationTests.cs | 87 ++ .../LuaLanguageServerResponseParserTests.cs | 18 + 58 files changed, 3122 insertions(+), 1091 deletions(-) create mode 100644 Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Completion}/LuaLanguageServerResponseParser.Completion.cs (97%) create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Diagnostics}/LuaLanguageServerDiagnosticsParser.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Diagnostics}/LuaPublishedDiagnostics.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaDocumentLineOffsets.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaDocumentRenameRequest.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaDocumentSnapshot.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaDocumentSynchronizationKind.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaDocumentSynchronizationRequest.cs (100%) create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaIncrementalEditCalculator.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaIntellisenseDocumentManager.cs (97%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Documents}/LuaTextDocumentSyncKind.cs (100%) create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Client}/ILuaLanguageServerClient.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Client}/LuaLanguageServerClient.Protocol.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Client}/LuaLanguageServerClient.Transport.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Client}/LuaLanguageServerClient.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Pathing}/LuaLanguageServerLocator.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Pathing}/LuaLanguageServerPathHelper.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Pathing}/LuaLanguageServerSettingsFactory.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Startup}/LuaLanguageServerStartupFailure.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Startup}/LuaProcessJobObject.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Workspace}/LuaWorkspaceFileWatcher.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Infrastructure/Workspace}/LuaWorkspaceWatcherFailure.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{LuaLanguageServerResponseParser.cs => LuaLanguageServerResponseParser.Shared.cs} (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Navigation}/LuaLanguageServerResponseParser.Navigation.cs (83%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Provider}/LuaLanguageServerIntellisenseProvider.Documents.cs (95%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Provider}/LuaLanguageServerIntellisenseProvider.Requests.cs (100%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Provider}/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs (81%) rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => Provider}/LuaLanguageServerIntellisenseProvider.cs (100%) create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => SemanticTokens}/LuaLanguageServerSemanticTokensDeltaParser.cs (100%) create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDecodeResult.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{ => SignatureHelp}/LuaLanguageServerResponseParser.SignatureHelp.cs (100%) create mode 100644 TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs delete mode 100644 TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs create mode 100644 TombLib/TombLib.Scripting.Lua/README.md create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/LuaCompletionNormalizationResult.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Utils/LuaEnterInsertionResult.cs create mode 100644 TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs create mode 100644 TombLib/TombLib.Test/LuaLanguageServerRealIntegrationTests.cs diff --git a/Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md b/Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md new file mode 100644 index 0000000000..d49159ac92 --- /dev/null +++ b/Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md @@ -0,0 +1,344 @@ +# Lua IntelliSense And AvalonEdit Cleanup Plan + +## Scope + +This plan covers the Lua editor and the Lua language-server integration code that currently spans these areas: + +- `TombLib/TombLib.Scripting.Lua/LuaEditor*.cs` +- `TombLib/TombLib.Scripting.Lua/Utils/*` +- `TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/*` +- `TombLib/TombLib.Scripting/Bases/TextEditorBase.cs` + +Nearby editors such as `GameFlowEditor` and `ClassicScriptEditor` are comparison points only. They are not part of the first cleanup passes unless a small shared helper clearly benefits more than one editor. + +## Goals + +- Reduce the number of responsibilities owned by `LuaEditor` and its partials. +- Move stateful feature logic behind focused collaborators so timers, cancellation, popups, and request tokens have a single owner per feature. +- Replace unclear multi-value returns with named result types where the tuple shape hides meaning. +- Reorganize the LuaLS implementation into slices that are easy to discover by feature and by responsibility. +- Keep behavior stable while refactoring by adding tests before moving the highest-risk code. +- Follow `AGENTS.md`: partials only when the responsibility still belongs to the same type, prefer helper or service extraction when it does not, keep touched code nullable-aware, and avoid broad helper types with fuzzy ownership. + +## Current Findings + +### Editor-side hotspots + +- `LuaEditor.Completion.cs` owns too much in one place: debounce scheduling, request orchestration, popup lifecycle, tooltip lifecycle, reflection-based AvalonEdit integration, width measurement, and query-offset calculation. +- `LuaEditor.SignatureHelp.cs` owns both presentation and workflow state: popup UI elements, request-in-flight state, refresh timer, positioning, and active-parameter formatting. +- `LuaEditor.Hover.cs` mixes request orchestration, fallback selection, and tooltip composition. +- `LuaEditor.Navigation.cs` duplicates parts of the editor request pipeline and shares state patterns with hover and completion. +- `LuaEditor.Intellisense.cs` still acts as a central wiring file for many unrelated concerns, so field ownership is difficult to follow even though the code is split into partials. + +### LuaLS service-side hotspots + +- `TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense` is currently a flat folder containing client transport, protocol, response parsing, workspace watching, document synchronization, semantic tokens, and provider orchestration. +- `LuaLanguageServerIntellisenseProvider` is still a large composition point with significant state and workflow spread across partials. +- Several feature-specific files already exist, but they are not grouped together on disk in a way that helps maintainers navigate by feature. + +### Tuple and result-shape hotspots + +The following methods are good candidates for named result types because their return values carry multiple meanings or mixed null and boolean state: + +- `LuaIndentationStrategy.BuildEnterInsertion()` +- `LuaIndentationStrategy.NormalizeCompletionInsertion()` +- `LuaLanguageServerResponseParser.StripSnippetPlaceholders()` +- `LuaLanguageServerIntellisenseProvider.DecodeSemanticTokensResponse()` +- `LuaLanguageServerIntellisenseProvider.SynchronizeDocumentCoreAsync()` +- `LuaIntellisenseDocumentManager.GetSemanticTokensDeltaState()` + +Small, local coordinate pairs such as line and column can remain tuples until a wider text-position abstraction is clearly justified. Not every two-value tuple needs to become a record. + +## Cleanup Rules + +- Keep `LuaEditor` as the public control and composition root. Do not move public editor behavior into a maze of tiny pass-through wrappers. +- Extract collaborators only when they own real state, workflow, or policy. +- Use `record struct` for small immutable result carriers and state snapshots. +- Prefer one top-level type per new file. +- Keep partial classes only where the split still represents one type with one coherent ownership boundary. +- Avoid introducing a generic cross-language framework before at least two editors need the same abstraction with similar complexity. + +## Phase 0 - Safeguards And Baseline + +Purpose: lock down behavior before structural work begins. + +Work items: + +1. Add focused tests for the current behavior that is easiest to break during extraction. +2. Cover completion request debounce, completion window refresh, completion tooltip resolve, hover vs diagnostic fallback, signature help open and refresh and dismiss, definition navigation, document sync, and semantic-token delta fallback. +3. Add a short maintainer note near the Lua editor and LuaLS service roots describing which file currently owns which feature. +4. Adopt the naming convention before creating new collaborators: use `Controller` for editor-side stateful owners, `Coordinator` for provider-side workflow owners, and keep `Service` for stable external integration boundaries or shared utilities. + +Exit criteria: + +- Refactor-sensitive behavior has direct tests. +- Maintainers can see the intended cleanup direction before code starts moving. + +## Phase 1 - Replace Ambiguous Tuple Returns + +Purpose: improve readability first with low-risk changes that clarify intent. + +Recommended result types: + +- `LuaEnterInsertionResult` + - replaces the tuple returned by `BuildEnterInsertion()` +- `LuaCompletionNormalizationResult` + - replaces the tuple returned by `NormalizeCompletionInsertion()` +- `LuaSnippetPlaceholderResult` + - replaces the tuple returned by `StripSnippetPlaceholders()` +- `LuaSemanticTokensDecodeResult` + - replaces the four-part tuple returned by `DecodeSemanticTokensResponse()` +- `LuaDocumentSynchronizationResult` + - replaces the tuple returned by `SynchronizeDocumentCoreAsync()` +- `LuaSemanticTokensDeltaState` + - replaces the tuple returned by `GetSemanticTokensDeltaState()` + +Notes: + +- Favor `internal readonly record struct` for these types. +- Keep the first pass narrow: rename only the returns that improve comprehension immediately. +- Do not convert short, obvious local tuples just for consistency. + +Exit criteria: + +- Mixed-state tuple returns are replaced with named result types. +- Method call sites read as domain concepts instead of index-based unpacking. + +## Phase 2 - Extract Editor Feature Controllers + +Purpose: remove intertwined state from `LuaEditor` without breaking its public role. + +Target shape: + +- `LuaEditor` remains the host control, public API surface, and event source. +- Each major editor feature gets one internal owner for its fields, timers, request tokens, and UI state. + +Recommended extractions: + +1. `LuaCompletionController` + - Owns completion debounce scheduling. + - Owns popup lifecycle. + - Owns tooltip update scheduling and resolve flow. + - Owns width measurement and query-offset calculation. + - Owns AvalonEdit-specific reflection and non-activating window behavior. + +2. `LuaSignatureHelpController` + - Owns signature popup elements. + - Owns refresh timer and pending-offset state. + - Owns request-in-flight state. + - Owns positioning and active-parameter rendering. + +3. `LuaHoverController` + - Owns hover request cancellation and tokens. + - Owns hover-offset validation. + - Owns hover vs diagnostic fallback policy. + - Owns combined tooltip rendering decisions. + +4. `LuaDefinitionNavigationController` + - Owns F12 and Ctrl+Click navigation flow. + - Owns definition request cancellation and freshness checks. + +5. Optional shared internal helper after the first extractions only + - `LuaEditorRequestGate` or `LuaEditorAsyncState` + - Create this only if completion, hover, signature help, and navigation still duplicate freshness logic after the first controller pass. + +Recommended folder direction: + +```text +TombLib/TombLib.Scripting.Lua/ + Editor/ + LuaEditor.cs + Completion/ + Hover/ + Navigation/ + SignatureHelp/ + SemanticHighlighting/ + Objects/ + Resources/ + Utils/ +``` + +Notes: + +- Do not extract theme application or semantic-highlighting attachment until the feature controllers settle. Those areas are smaller and less entangled. +- Keep event wiring in `LuaEditor` or one small composition file, not spread across every controller. + +Exit criteria: + +- No single feature stores its timers and request state directly on `LuaEditor` unless that state is trivial. +- The owner of each field is easy to infer from the file name. + +## Phase 3 - Re-slice The LuaLS Implementation In TombIDE + +Purpose: turn the flat LuaLS service folder into a discoverable feature-oriented structure. + +Recommended folder direction: + +```text +TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ + Infrastructure/ + Client/ + Pathing/ + Startup/ + Workspace/ + Documents/ + Provider/ + Completion/ + Hover/ + Navigation/ + SignatureHelp/ + Diagnostics/ + SemanticTokens/ +``` + +Suggested file moves: + +- `Infrastructure/Client/` + - `ILuaLanguageServerClient.cs` + - `LuaLanguageServerClient.cs` + - `LuaLanguageServerClient.Protocol.cs` + - `LuaLanguageServerClient.Transport.cs` + +- `Infrastructure/Pathing/` + - `LuaLanguageServerPathHelper.cs` + - `LuaLanguageServerLocator.cs` + - `LuaLanguageServerSettingsFactory.cs` + +- `Infrastructure/Startup/` + - `LuaLanguageServerStartupFailure.cs` + - `LuaProcessJobObject.cs` + +- `Infrastructure/Workspace/` + - `LuaWorkspaceFileWatcher.cs` + - `LuaWorkspaceWatcherFailure.cs` + +- `Documents/` + - `LuaIntellisenseDocumentManager.cs` + - `LuaDocumentSnapshot.cs` + - `LuaDocumentSynchronizationRequest.cs` + - `LuaDocumentRenameRequest.cs` + - `LuaDocumentLineOffsets.cs` + - `LuaIncrementalEditCalculator.cs` + - `LuaTextDocumentSyncKind.cs` + +- `Provider/` + - `LuaLanguageServerIntellisenseProvider.cs` + - `LuaLanguageServerIntellisenseProvider.Documents.cs` + - `LuaLanguageServerIntellisenseProvider.Requests.cs` + - `LuaLanguageServerIntellisenseProvider.SemanticTokens.cs` + +- `Completion/` + - `LuaLanguageServerResponseParser.Completion.cs` + +- `Navigation/` + - `LuaLanguageServerResponseParser.Navigation.cs` + +- `SignatureHelp/` + - `LuaLanguageServerResponseParser.SignatureHelp.cs` + +- `Diagnostics/` + - `LuaLanguageServerDiagnosticsParser.cs` + - `LuaPublishedDiagnostics.cs` + - shared response-parser pieces that are diagnostics-specific if more are split later + +- `SemanticTokens/` + - `LuaLanguageServerSemanticTokensDeltaParser.cs` + - future semantic-token decoder or result helpers + +Implementation order inside this phase: + +1. Move files without behavioral changes. +2. Rename partials only when the new file names better match the responsibility. +3. Extract dedicated stateful coordinators only where there is real state ownership pressure. + +Recommended coordinator candidates inside the provider layer: + +- `LuaDocumentSynchronizationCoordinator` +- `LuaSemanticTokensCoordinator` +- `LuaWorkspaceWatcherCoordinator` + +Non-goal for this phase: + +- Do not create separate completion, hover, navigation, and signature-help service classes if they remain thin request wrappers around parser calls. That would add indirection without paying down much complexity. + +Exit criteria: + +- A maintainer can find document sync, semantic tokens, workspace watching, or client transport without scanning the whole folder. +- Provider partials and helper types match clear feature boundaries. + +## Phase 4 - Consolidate Shared AvalonEdit Infrastructure Carefully + +Purpose: extract only the reusable pieces that are already proven to repeat. + +Shared abstractions that are worth considering: + +- `TextDocumentPosition` + - only if Lua editor code and LuaLS infrastructure both need the same line and character concept in multiple places +- `AsyncRequestGate` + - only if multiple editor features or multiple editors share the same request freshness and lifecycle pattern +- `CompletionWindowHost` + - only if another async editor needs the same styled completion popup and tooltip behavior +- `HoverToolTipFactory` + - only if tooltip composition starts repeating across more than one editor + +Shared abstractions that are not worth building now: + +- A generic `IIntellisenseProvider` +- A generic editor framework for completion, hover, definition, and signature help across all AvalonEdit editors + +Reason: + +- Lua currently has the only rich async LSP-backed pipeline. +- `GameFlowEditor` and `ClassicScriptEditor` are much simpler and mostly synchronous. +- A shared full-framework abstraction would force weaker editors into stub implementations and increase indirection before there is a second real consumer. + +Recommendation: + +- Keep the Lua feature contracts Lua-specific for now. +- Revisit a broader abstraction only when at least one other editor reaches a Lua-like capability set or moves to an LSP-backed async model. + +Exit criteria: + +- Shared helpers exist only where they already have at least two concrete consumers. +- No new abstraction is introduced just to make the architecture diagram look cleaner. + +## Phase 5 - Final Simplification And Maintainer Handoff + +Purpose: finish the cleanup by reducing leftover friction for future contributors. + +Work items: + +1. Remove partials that no longer improve navigation after service extraction. +2. Ensure touched files follow nullable guidance and remove redundant null-forgiving usage where practical. +3. Remove unused `using` directives and redundant framework qualification in touched files. +4. Add a short `README.md` inside the LuaLS service root describing the slices and their ownership. +5. Add a small regression checklist for completion, hover, signature help, definition navigation, document rename, diagnostics, and semantic tokens. + +Exit criteria: + +- A new maintainer can identify the owner of a behavior in one or two guesses. +- The cleanup leaves fewer hidden couplings, not just more files. + +## Recommended Execution Order + +1. Phase 0 baseline tests and notes. +2. Phase 1 named result types. +3. Phase 2 completion controller extraction. +4. Phase 2 signature-help controller extraction. +5. Phase 2 hover and navigation extraction. +6. Phase 3 file moves for LuaLS slices. +7. Phase 3 targeted provider coordinators where state remains dense. +8. Phase 4 shared infrastructure only if the first three phases reveal a real repeated pattern. +9. Phase 5 final simplification, docs, and regression pass. + +## Decision On A Shared IntelliSense Abstraction + +Short answer: not as a full framework yet. + +The worthwhile cleanup right now is to separate Lua editor features and LuaLS infrastructure into well-owned pieces. That work will make later sharing easier if another editor actually grows into the same capability set. Building a generic abstraction for completion, hover, definition, signature help, and related plumbing before that point would most likely add complexity instead of removing duplication. + +The pragmatic middle ground is: + +- extract Lua-specific controllers and provider coordinators first +- promote only small reusable building blocks when a second consumer appears +- delay any broad cross-language IntelliSense contract until there is a second editor with comparable async behavior and lifecycle needs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaLanguageServerResponseParser.Completion.cs similarity index 97% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaLanguageServerResponseParser.Completion.cs index 3731c1c6db..269766cdb4 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaLanguageServerResponseParser.Completion.cs @@ -171,7 +171,9 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) { - (insertText, insertCaretOffset) = StripSnippetPlaceholders(insertText); + LuaSnippetPlaceholderResult snippetResult = StripSnippetPlaceholders(insertText); + insertText = snippetResult.Text; + insertCaretOffset = snippetResult.CaretOffset; } string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) @@ -441,10 +443,10 @@ private static MarkupContent BuildCompletionDescription(JsonElement itemElement) : new MarkupContent(normalizedText, documentation.IsMarkdown); } - private static (string Text, int? CaretOffset) StripSnippetPlaceholders(string snippet) + private static LuaSnippetPlaceholderResult StripSnippetPlaceholders(string snippet) { if (string.IsNullOrWhiteSpace(snippet)) - return (snippet, null); + return new LuaSnippetPlaceholderResult(snippet, null); var builder = new StringBuilder(snippet.Length); int? caretOffset = null; @@ -506,6 +508,6 @@ private static (string Text, int? CaretOffset) StripSnippetPlaceholders(string s index++; } - return (builder.ToString(), caretOffset); + return new LuaSnippetPlaceholderResult(builder.ToString(), caretOffset); } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs new file mode 100644 index 0000000000..43ad72f9e5 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs @@ -0,0 +1,6 @@ +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Represents snippet text after placeholder stripping and the resolved caret placement. +/// +internal readonly record struct LuaSnippetPlaceholderResult(string Text, int? CaretOffset); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaLanguageServerDiagnosticsParser.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerDiagnosticsParser.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaLanguageServerDiagnosticsParser.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaPublishedDiagnostics.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaPublishedDiagnostics.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaPublishedDiagnostics.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentLineOffsets.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentLineOffsets.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentLineOffsets.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentRenameRequest.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentRenameRequest.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentRenameRequest.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentRenameRequest.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSnapshot.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSnapshot.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSnapshot.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationKind.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationKind.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationKind.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationRequest.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationRequest.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaDocumentSynchronizationRequest.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationRequest.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs new file mode 100644 index 0000000000..2e26198792 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs @@ -0,0 +1,10 @@ +#nullable enable + +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Represents the outcome of synchronizing one document with the Lua language server. +/// +internal readonly record struct LuaDocumentSynchronizationResult(bool Success, LuaDocumentSnapshot? Document); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIncrementalEditCalculator.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIncrementalEditCalculator.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIncrementalEditCalculator.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs similarity index 97% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs index 3d28225390..03fb1a4da3 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs @@ -306,15 +306,15 @@ public bool TryStoreSemanticTokens(string filePath, int version, IReadOnlyList /// The normalized file path. - /// The previous result id and cached integer stream, if available. - public (string? PreviousResultId, int[]? PreviousData) GetSemanticTokensDeltaState(string filePath) + /// The cached delta state, if available. + public LuaSemanticTokensDeltaState GetSemanticTokensDeltaState(string filePath) { lock (_syncRoot) { if (!_documents.TryGetValue(filePath, out DocumentState? state)) - return (null, null); + return new LuaSemanticTokensDeltaState(null, null); - return (state.SemanticTokensResultId, state.SemanticTokensData); + return new LuaSemanticTokensDeltaState(state.SemanticTokensResultId, state.SemanticTokensData); } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaTextDocumentSyncKind.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaTextDocumentSyncKind.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaTextDocumentSyncKind.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs new file mode 100644 index 0000000000..40a2be8155 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs @@ -0,0 +1,24 @@ +#nullable enable + +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses hover content from a LuaLS hover response. + /// + public static LuaHoverInfo? ParseHoverInfo(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) + return null; + + MarkupContent hoverContent = ExtractMarkupContent(contentsElement); + + return string.IsNullOrWhiteSpace(hoverContent.Text) + ? null + : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ILuaLanguageServerClient.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Transport.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Transport.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerLocator.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerLocator.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerPathHelper.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerStartupFailure.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaProcessJobObject.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaProcessJobObject.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaProcessJobObject.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceWatcherFailure.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceWatcherFailure.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Navigation.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Navigation/LuaLanguageServerResponseParser.Navigation.cs similarity index 83% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Navigation.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Navigation/LuaLanguageServerResponseParser.Navigation.cs index 0cf866888c..de7b7321d7 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Navigation.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Navigation/LuaLanguageServerResponseParser.Navigation.cs @@ -17,21 +17,6 @@ internal static partial class LuaLanguageServerResponseParser "range" ]; - /// - /// Parses hover content from a LuaLS hover response. - /// - public static LuaHoverInfo? ParseHoverInfo(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) - return null; - - MarkupContent hoverContent = ExtractMarkupContent(contentsElement); - - return string.IsNullOrWhiteSpace(hoverContent.Text) - ? null - : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); - } - /// /// Parses a definition location from a LuaLS definition response. /// diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs similarity index 95% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs index ac0e419bee..8c83a1f5b7 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs @@ -74,15 +74,15 @@ private async Task SynchronizeDocumentAsync(string filePath, string conten try { - (bool success, LuaDocumentSnapshot? document) = await EnqueueDocumentOperationAsync( + LuaDocumentSynchronizationResult synchronizationResult = await EnqueueDocumentOperationAsync( token => SynchronizeDocumentCoreAsync(filePath, content, acquireOpenReference, token), cancellationToken).ConfigureAwait(false); - if (!success) + if (!synchronizationResult.Success) return false; - if (refreshSemanticTokens && document is not null) - await RefreshSemanticTokensAsync(document, cancellationToken).ConfigureAwait(false); + if (refreshSemanticTokens && synchronizationResult.Document is { } synchronizedDocument) + await RefreshSemanticTokensAsync(synchronizedDocument, cancellationToken).ConfigureAwait(false); return true; } @@ -161,22 +161,22 @@ private async Task RenameDocumentAsync(string oldFilePath, string newFileP } } - private async Task<(bool Success, LuaDocumentSnapshot? Document)> SynchronizeDocumentCoreAsync( + private async Task SynchronizeDocumentCoreAsync( string filePath, string content, bool acquireOpenReference, CancellationToken cancellationToken) { if (!await EnsureStartedAsync(cancellationToken).ConfigureAwait(false)) - return (false, null); + return new LuaDocumentSynchronizationResult(false, null); LuaDocumentSynchronizationRequest? request = _documents.Synchronize(filePath, content, acquireOpenReference); if (request is not { } pendingRequest) - return (true, null); + return new LuaDocumentSynchronizationResult(true, null); await SendDocumentSynchronizationNotificationAsync(pendingRequest, cancellationToken).ConfigureAwait(false); - return (true, pendingRequest.Document); + return new LuaDocumentSynchronizationResult(true, pendingRequest.Document); } private async Task RenameDocumentCoreAsync( diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs similarity index 81% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs index ca58bbe0e5..dad60413bb 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs @@ -35,17 +35,18 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc try { - (string? previousResultId, int[]? previousData) = _documents.GetSemanticTokensDeltaState(document.FilePath); - bool useDelta = _client.SupportsSemanticTokensDelta && previousResultId is not null && previousData is not null; - JsonElement response = await SendSemanticTokensRequestAsync(document, previousResultId, useDelta, effectiveToken).ConfigureAwait(false); + LuaSemanticTokensDeltaState deltaState = _documents.GetSemanticTokensDeltaState(document.FilePath); + bool useDelta = _client.SupportsSemanticTokensDelta + && deltaState.PreviousResultId is not null + && deltaState.PreviousData is not null; + JsonElement response = await SendSemanticTokensRequestAsync(document, deltaState.PreviousResultId, useDelta, effectiveToken).ConfigureAwait(false); if (response.ValueKind == JsonValueKind.Undefined) return; - (IReadOnlyList semanticTokens, int[]? newData, string? newResultId, bool retryWithFullRefresh) = - DecodeSemanticTokensResponse(response, document, previousData, useDelta); + LuaSemanticTokensDecodeResult decodeResult = DecodeSemanticTokensResponse(response, document, deltaState.PreviousData, useDelta); - if (retryWithFullRefresh) + if (decodeResult.RetryWithFullRefresh) { _documents.StoreSemanticTokensDeltaState(document.FilePath, null, null); @@ -54,15 +55,15 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc if (fullResponse.ValueKind == JsonValueKind.Undefined) return; - (semanticTokens, newData, newResultId, _) = DecodeSemanticTokensResponse(fullResponse, document, previousData: null, deltaWasRequested: false); + decodeResult = DecodeSemanticTokensResponse(fullResponse, document, previousData: null, deltaWasRequested: false); } - _documents.StoreSemanticTokensDeltaState(document.FilePath, newResultId, newData); + _documents.StoreSemanticTokensDeltaState(document.FilePath, decodeResult.ResultId, decodeResult.Data); - if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, semanticTokens)) + if (!_documents.TryStoreSemanticTokens(document.FilePath, document.Version, decodeResult.Tokens)) return; - RaiseSemanticTokensUpdated(document.FilePath, semanticTokens); + RaiseSemanticTokensUpdated(document.FilePath, decodeResult.Tokens); } catch (OperationCanceledException) when (effectiveToken.IsCancellationRequested && !cancellationToken.IsCancellationRequested) { @@ -109,11 +110,11 @@ private Task SendSemanticTokensRequestAsync( return SendBoundedRequestAsync(_client, method, parameters, cancellationToken); } - private (IReadOnlyList Tokens, int[]? Data, string? ResultId, bool RetryWithFullRefresh) DecodeSemanticTokensResponse( + private LuaSemanticTokensDecodeResult DecodeSemanticTokensResponse( JsonElement response, LuaDocumentSnapshot document, int[]? previousData, bool deltaWasRequested) { if (_client is null) - return ([], null, null, false); + return new LuaSemanticTokensDecodeResult([], null, null, false); if (deltaWasRequested) { @@ -127,11 +128,11 @@ private Task SendSemanticTokensRequestAsync( { IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( patchedData, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); - return (tokens, patchedData, delta.ResultId, false); + return new LuaSemanticTokensDecodeResult(tokens, patchedData, delta.ResultId, false); } Log.Debug("Lua semantic-tokens delta edits could not be applied for '{FilePath}'; falling back to a full reparse.", document.FilePath); - return ([], null, null, true); + return new LuaSemanticTokensDecodeResult([], null, null, true); } if (delta.Data is { } fullData) @@ -139,11 +140,11 @@ private Task SendSemanticTokensRequestAsync( IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( fullData, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); - return (tokens, fullData, delta.ResultId, false); + return new LuaSemanticTokensDecodeResult(tokens, fullData, delta.ResultId, false); } Log.Debug("Lua semantic-tokens delta response for '{FilePath}' did not contain usable data; requesting a full refresh.", document.FilePath); - return ([], null, null, true); + return new LuaSemanticTokensDecodeResult([], null, null, true); } LuaSemanticTokensDeltaResponse fullResponse = LuaLanguageServerSemanticTokensDeltaParser.Parse(response); @@ -153,10 +154,10 @@ private Task SendSemanticTokensRequestAsync( IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( data, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); - return (tokens, data, fullResponse.ResultId, false); + return new LuaSemanticTokensDecodeResult(tokens, data, fullResponse.ResultId, false); } - return ([], null, fullResponse.ResultId, false); + return new LuaSemanticTokensDecodeResult([], null, fullResponse.ResultId, false); } private CancellationToken ReplaceSemanticTokenRequest(string filePath, CancellationToken cancellationToken, out CancellationTokenSource? linkedSource) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md new file mode 100644 index 0000000000..28c2ed5273 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md @@ -0,0 +1,31 @@ +# Lua Language Server Ownership Notes + +This note is a maintainer map for the current LuaLS integration layout after the phase 3 re-slice. It is intentionally short and should be updated as cleanup work lands. + +## Current ownership + +- `Provider/`: provider composition root, startup and restart flow, request orchestration, document replay, and semantic-token refresh coordination. +- `Documents/`: tracked document snapshots, version and open-reference state, synchronization requests and results, incremental edit calculation, and text-sync kinds. +- `Infrastructure/Client/`: process lifetime, JSON-RPC session state, transport I/O, and server capability tracking. +- `Infrastructure/Pathing/`: path normalization, server discovery, and settings generation. +- `Infrastructure/Startup/`: startup failure reporting and process-host job-object integration. +- `Infrastructure/Workspace/`: workspace file watching, external change batching, and watcher failure reporting. +- `Completion/`: completion response parsing and snippet-placeholder result shaping. +- `Hover/`: hover response parsing. +- `Navigation/`: definition-location response parsing. +- `SignatureHelp/`: signature-help response parsing. +- `Diagnostics/`: diagnostics payload mapping and published diagnostics snapshots. +- `SemanticTokens/`: semantic-tokens delta parsing plus cached delta and decode result carriers. +- `LuaLanguageServerResponseParser.Shared.cs`: shared markup parsing helpers used by the response-parser partials. + +## Extraction naming + +- Use `Coordinator` for new provider-side owners of document sync, semantic tokens, restart handling, or workspace watching. +- Avoid introducing feature-specific `Service` types when the result would only wrap one parser call and add another hop. +- Keep parser and transport types focused on one protocol concern each. + +## Cleanup guardrails + +- Move files by feature first, then extract new stateful owners only where state is still dense. +- Keep document tracking centralized instead of splitting version and cache state across several helpers. +- Prefer feature-oriented folders over a larger set of flat provider partials. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSemanticTokensDeltaParser.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDecodeResult.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDecodeResult.cs new file mode 100644 index 0000000000..9a647e26d3 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDecodeResult.cs @@ -0,0 +1,15 @@ +#nullable enable + +using System.Collections.Generic; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Represents the decoded semantic tokens payload and whether the caller should retry with a full refresh. +/// +internal readonly record struct LuaSemanticTokensDecodeResult( + IReadOnlyList Tokens, + int[]? Data, + string? ResultId, + bool RetryWithFullRefresh); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs new file mode 100644 index 0000000000..3b46ea6eec --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs @@ -0,0 +1,8 @@ +#nullable enable + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +/// +/// Represents the cached semantic-tokens delta state used for incremental refresh requests. +/// +internal readonly record struct LuaSemanticTokensDeltaState(string? PreviousResultId, int[]? PreviousData); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.SignatureHelp.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.SignatureHelp.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs diff --git a/TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs b/TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs new file mode 100644 index 0000000000..d80ca17cd1 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs @@ -0,0 +1,522 @@ +using ICSharpCode.AvalonEdit.CodeCompletion; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Reflection; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Interop; +using System.Windows.Media; +using System.Windows.Threading; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Resources; +using TombLib.Scripting.Lua.Utils; +using TombLib.WPF; + +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor +{ + private void CloseCompletionWindow() + => _completionController.CloseWindow(); + + private void ScheduleCompletionRequest() + => _completionController.ScheduleRequest(); + + private void CancelPendingCompletionRequest() + => _completionController.CancelPendingRequest(); + + private Task RequestCompletionAsync(int offset, char? triggerCharacter) + => _completionController.RequestAsync(offset, triggerCharacter); + + private bool CanApplyCompletionItem(LuaCompletionItem item) + => IsCompletionItemCurrent(item.RequestDocumentVersion, _editorDocumentVersion, + item.RequestGeneration, _editorRequestGeneration, IsLoaded, IsIntellisenseAvailable()); + + private void RebaseOpenCompletionItems() + => _completionController.RebaseOpenCompletionItems(); + + private static bool IsCompletionItemCurrent(int? requestDocumentVersion, + int currentDocumentVersion, + int? requestGeneration, + int currentGeneration, + bool isEditorLoaded, + bool isIntellisenseAvailable) + { + if (!isEditorLoaded || !isIntellisenseAvailable) + return false; + + if (!requestDocumentVersion.HasValue && !requestGeneration.HasValue) + return true; + + if (!requestDocumentVersion.HasValue || !requestGeneration.HasValue) + return false; + + return requestDocumentVersion.Value == currentDocumentVersion + && requestGeneration.Value == currentGeneration; + } + + private void ScheduleCloseIfEmpty() + => _completionController.ScheduleCloseIfEmpty(); + + private sealed class LuaCompletionController + { + private const double CompletionRequestDebounceDelayInMilliseconds = 120.0; + private const int CompletionWindowMinWidth = 420; + private const int CompletionWindowMaxWidth = 920; + private const int CompletionWindowHeight = 320; + private const int CompletionWidthMeasurementSampleCount = 80; + private const double CompletionToolTipHorizontalOffset = 10.0; + private const double CompletionToolTipResolveDelayInMilliseconds = 120.0; + private const double CompletionWindowHorizontalChrome = 52.0; + private const double CompletionItemIconWidth = 24.0; + private const double CompletionItemDetailSpacing = 12.0; + + private static readonly Lazy CompletionToolTipFieldAccessor = new(() => + { + FieldInfo? field = typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); + + if (field is null) + Log?.Debug("AvalonEdit completion tooltip styling is unavailable because the internal tooltip field could not be found."); + + return field; + }); + + private static FieldInfo? CompletionToolTipField => CompletionToolTipFieldAccessor.Value; + + private readonly LuaEditor _editor; + private readonly DispatcherTimer _completionRequestTimer = new(); + private readonly DispatcherTimer _completionToolTipUpdateTimer = new(); + private int _completionRequestToken; + private int _completionToolTipUpdateToken; + private ToolTip? _pendingCompletionToolTip; + + public LuaCompletionController(LuaEditor editor) + { + _editor = editor; + } + + public void InitializeScheduling() + { + _completionRequestTimer.Interval = TimeSpan.FromMilliseconds(CompletionRequestDebounceDelayInMilliseconds); + _completionRequestTimer.Tick -= CompletionRequestTimer_Tick; + _completionRequestTimer.Tick += CompletionRequestTimer_Tick; + + _completionToolTipUpdateTimer.Interval = TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds); + _completionToolTipUpdateTimer.Tick -= CompletionToolTipUpdateTimer_Tick; + _completionToolTipUpdateTimer.Tick += CompletionToolTipUpdateTimer_Tick; + } + + public void CloseWindow() + { + InvalidateRequests(); + CloseWindowCore(); + } + + public void CloseWindowForRefresh() + => CloseWindowCore(); + + public void ScheduleRequest() + { + _completionRequestTimer.Stop(); + _completionRequestTimer.Start(); + } + + public void CancelPendingRequest() + => _completionRequestTimer.Stop(); + + public async Task RequestAsync(int offset, char? triggerCharacter) + { + CancellationToken cancellationToken = CancellationToken.None; + int requestToken = ++_completionRequestToken; + int requestDocumentVersion = _editor._editorDocumentVersion; + int requestGeneration = _editor._editorRequestGeneration; + + try + { + if (!_editor.IsIntellisenseAvailable()) + return; + + var intellisenseProvider = _editor.IntellisenseProvider; + + if (intellisenseProvider is null) + return; + + _editor.DismissSignatureHelp(); + _editor.CloseDefinitionToolTip(true); + + (int line, int column) = _editor.GetPositionFromOffset(offset); + + IReadOnlyList items = await intellisenseProvider + .GetCompletionItemsAsync(_editor.FilePath, _editor.Text, line, column, triggerCharacter, cancellationToken) + .ConfigureAwait(true); + + if (!_editor.IsAsyncEditorResultCurrent(cancellationToken, requestToken, _completionRequestToken, + requestDocumentVersion, requestGeneration)) + { + return; + } + + if (items.Count == 0) + { + CloseWindow(); + return; + } + + var completionDataItems = new LuaCompletionData[items.Count]; + LuaThemeBrushSet brushSet = _editor.GetThemeBrushSet(); + + for (int i = 0; i < items.Count; i++) + { + LuaCompletionItem completionItem = items[i].WithRequestContext(requestDocumentVersion, requestGeneration); + completionDataItems[i] = new LuaCompletionData(completionItem, brushSet, _editor.CanApplyCompletionItem); + } + + if (!_editor.IsAsyncEditorResultCurrent(cancellationToken, requestToken, _completionRequestToken, + requestDocumentVersion, requestGeneration)) + { + return; + } + + CloseWindowForRefresh(); + InitializeWindow(); + ResizeWindow(completionDataItems); + SetWindowOffsets(offset); + + foreach (LuaCompletionData completionDataItem in completionDataItems) + _editor._completionWindow.CompletionList.CompletionData.Add(completionDataItem); + + if (_editor._completionWindow.CompletionList.CompletionData.Count > 0) + { + _editor.ShowCompletionWindow(); + ScheduleInitialSelection(); + } + } + catch (OperationCanceledException) + { + } + catch (Exception exception) + { + CloseWindow(); + LogEditorFailure("Completion request", exception); + } + } + + public void RebaseOpenCompletionItems() + { + if (_editor._completionWindow?.CompletionList?.CompletionData is null) + return; + + for (int i = 0; i < _editor._completionWindow.CompletionList.CompletionData.Count; i++) + { + if (_editor._completionWindow.CompletionList.CompletionData[i] is LuaCompletionData completionData) + completionData.RebaseForCurrentDocument(_editor._editorDocumentVersion, _editor._editorRequestGeneration); + } + } + + public Task UpdateTooltipAsync(ToolTip tooltip, int updateToken) + => UpdateTooltipCoreAsync(tooltip, updateToken); + + public void ScheduleCloseIfEmpty() + => _editor.Dispatcher.BeginInvoke(new Action(() => CloseWindowIfEmpty()), DispatcherPriority.Background); + + public void InvalidateRequests() + => _completionRequestToken++; + + private void InitializeWindow() + { + _editor.InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); + LuaCompletionWindowStyle.Apply(_editor._completionWindow, _editor.GetThemeBrushSet()); + StyleTooltip(); + MakeWindowNonActivatable(); + } + + private void CloseWindowCore() + { + CancelPendingRequest(); + CancelTooltipUpdate(); + + if (_editor._completionWindow is null) + return; + + if (CompletionToolTipField?.GetValue(_editor._completionWindow) is ToolTip tooltip) + tooltip.IsOpen = false; + + _editor._completionWindow.Close(); + _editor._completionWindow = null; + } + + private async void CompletionRequestTimer_Tick(object? sender, EventArgs e) + { + _completionRequestTimer.Stop(); + + if (!_editor.AutocompleteEnabled || !_editor.IsIntellisenseAvailable()) + return; + + if (!LuaEditorInteractionRules.IsValidAutocompleteContext(_editor.Document, _editor.CaretOffset, triggerCharacter: null)) + return; + + await RequestAsync(_editor.CaretOffset, null).ConfigureAwait(true); + } + + private void StyleTooltip() + { + if (_editor._completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; + + if (CompletionToolTipField?.GetValue(_editor._completionWindow) is not ToolTip tooltip) + return; + + tooltip.Background = DefaultToolTipBackground; + tooltip.BorderBrush = DefaultToolTipBorder; + tooltip.BorderThickness = new Thickness(0.0); + tooltip.Padding = new Thickness(0.0); + tooltip.PlacementTarget = listBox; + tooltip.Placement = PlacementMode.Right; + tooltip.HorizontalOffset = CompletionToolTipHorizontalOffset; + tooltip.StaysOpen = true; + + listBox.SelectionChanged += (s, e) => ScheduleTooltipUpdate(tooltip); + listBox.PreviewMouseLeftButtonUp += (s, e) => HandleCompletionListClick(listBox, tooltip, e); + } + + private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) + { + ListBoxItem? listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); + + if (listBoxItem is null) + return; + + if (!ReferenceEquals(listBox.SelectedItem, listBoxItem.DataContext)) + listBox.SelectedItem = listBoxItem.DataContext; + + listBox.ScrollIntoView(listBoxItem.DataContext); + ScheduleTooltipUpdate(tooltip); + } + + private void ScheduleTooltipUpdate(ToolTip tooltip) + { + _pendingCompletionToolTip = tooltip; + _completionToolTipUpdateToken++; + _completionToolTipUpdateTimer.Stop(); + _completionToolTipUpdateTimer.Start(); + } + + private async void CompletionToolTipUpdateTimer_Tick(object? sender, EventArgs e) + { + _completionToolTipUpdateTimer.Stop(); + + if (_pendingCompletionToolTip is not ToolTip tooltip) + return; + + await UpdateTooltipCoreAsync(tooltip, _completionToolTipUpdateToken).ConfigureAwait(true); + } + + private async Task UpdateTooltipCoreAsync(ToolTip tooltip, int updateToken) + { + if (_editor._completionWindow?.CompletionList.ListBox is not ListBox listBox) + return; + + if (listBox.SelectedItem is not ICompletionData item) + { + tooltip.IsOpen = false; + return; + } + + try + { + object? description = item.Description; + + if (description is not null) + ApplyTooltipContent(tooltip, description); + else + tooltip.IsOpen = false; + + if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) + { + if (updateToken != _completionToolTipUpdateToken) + return; + + object? resolvedDescription = await luaCompletionData.GetDescriptionAsync().ConfigureAwait(true); + + if (updateToken != _completionToolTipUpdateToken) + return; + + if (_editor._completionWindow?.CompletionList.ListBox is not ListBox currentListBox + || !ReferenceEquals(currentListBox, listBox) + || !ReferenceEquals(currentListBox.SelectedItem, item)) + { + return; + } + + if (resolvedDescription is not null) + ApplyTooltipContent(tooltip, resolvedDescription); + else + tooltip.IsOpen = false; + } + } + catch (Exception exception) + { + tooltip.IsOpen = false; + LogEditorFailure("Completion tooltip update", exception); + } + } + + private void ResizeWindow(LuaCompletionData[] completionDataItems) + { + if (_editor._completionWindow is null || completionDataItems.Length == 0) + return; + + double requiredWidth = CompletionWindowMinWidth; + int measurementCount = Math.Min(completionDataItems.Length, CompletionWidthMeasurementSampleCount); + var textWidthCache = new Dictionary(StringComparer.Ordinal); + + for (int i = 0; i < measurementCount; i++) + requiredWidth = Math.Max(requiredWidth, MeasureItemWidth(completionDataItems[i], textWidthCache)); + + _editor._completionWindow.Width = Math.Max( + CompletionWindowMinWidth, + Math.Min(CompletionWindowMaxWidth, requiredWidth + CompletionWindowHorizontalChrome)); + } + + private double MeasureItemWidth(LuaCompletionData completionData, IDictionary textWidthCache) + { + double width = CompletionItemIconWidth + MeasureTextWidth(completionData.DisplayText, textWidthCache); + + if (!string.IsNullOrWhiteSpace(completionData.DisplayDetail)) + width += CompletionItemDetailSpacing + MeasureTextWidth(completionData.DisplayDetail, textWidthCache); + + return width; + } + + private double MeasureTextWidth(string text, IDictionary textWidthCache) + { + if (string.IsNullOrWhiteSpace(text)) + return 0.0; + + if (textWidthCache.TryGetValue(text, out double cachedWidth)) + return cachedWidth; + + double pixelsPerDip = VisualTreeHelper.GetDpi(_editor).PixelsPerDip; + + var formattedText = new FormattedText( + text, + CultureInfo.CurrentUICulture, + FlowDirection.LeftToRight, + new Typeface(_editor.FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), + _editor.FontSize, + _editor.Foreground, + pixelsPerDip); + + double width = formattedText.WidthIncludingTrailingWhitespace; + textWidthCache[text] = width; + return width; + } + + private static void ApplyTooltipContent(ToolTip tooltip, object content) + { + tooltip.Content = content; + + if (!tooltip.IsOpen) + { + tooltip.IsOpen = true; + } + else + { + tooltip.InvalidateMeasure(); + tooltip.InvalidateVisual(); + } + } + + public void CancelTooltipUpdate() + { + _completionToolTipUpdateToken++; + _pendingCompletionToolTip = null; + _completionToolTipUpdateTimer.Stop(); + } + + private void ScheduleInitialSelection() + => _editor.Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.ContextIdle); + + private void SelectInitialItem() + { + if (_editor._completionWindow is null) + return; + + _editor._completionWindow.CompletionList.SelectItem(GetCompletionWindowQuery()); + CloseWindowIfEmpty(); + } + + private void MakeWindowNonActivatable() + { + _editor._completionWindow.SourceInitialized += (s, e) => + { + if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) + source.AddHook(CompletionWindowWndProc); + }; + } + + private static IntPtr CompletionWindowWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + { + const int WM_MOUSEACTIVATE = 0x0021; + const int MA_NOACTIVATE = 3; + + if (msg == WM_MOUSEACTIVATE) + { + handled = true; + return new IntPtr(MA_NOACTIVATE); + } + + return IntPtr.Zero; + } + + private bool CloseWindowIfEmpty() + { + if (_editor._completionWindow is null) + return false; + + ListBox listBox = _editor._completionWindow.CompletionList.ListBox; + + if (listBox?.HasItems != false) + return false; + + CloseWindow(); + return true; + } + + private string GetCompletionWindowQuery() + { + if (_editor._completionWindow is null || _editor.Document is null) + return string.Empty; + + int startOffset = Math.Max(0, Math.Min(_editor._completionWindow.StartOffset, _editor.Document.TextLength)); + int endOffset = Math.Max(startOffset, Math.Min(_editor._completionWindow.EndOffset, _editor.Document.TextLength)); + + return endOffset > startOffset + ? _editor.Document.GetText(startOffset, endOffset - startOffset) + : string.Empty; + } + + private void SetWindowOffsets(int offset) + { + int startOffset = Math.Max(0, Math.Min(offset, _editor.Document.TextLength)); + + while (startOffset > 0) + { + char currentChar = _editor.Document.GetCharAt(startOffset - 1); + + if (LuaLineParser.IsIdentifierCharacter(currentChar)) + startOffset--; + else + break; + } + + _editor._completionWindow.StartOffset = startOffset; + _editor._completionWindow.EndOffset = Math.Max(0, Math.Min(offset, _editor.Document.TextLength)); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs b/TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs new file mode 100644 index 0000000000..889dfc4b1a --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs @@ -0,0 +1,176 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Rendering; +using TombLib.Scripting.Lua.Utils; +using TombLib.Scripting.Objects; + +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor +{ + protected override async void HandleMouseHover(MouseEventArgs e) + => await _hoverController.HandleMouseHoverAsync(e).ConfigureAwait(true); + + private static FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) => hoverInfo.IsMarkdown + ? MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground) + : MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); + + private sealed class LuaHoverController + { + private readonly LuaEditor _editor; + private CancellationTokenSource? _hoverCancellationTokenSource; + private int _hoverRequestToken; + + public LuaHoverController(LuaEditor editor) + { + _editor = editor; + } + + public async Task HandleMouseHoverAsync(MouseEventArgs e) + { + int hoveredOffset = _editor.GetOffsetFromPoint(e.GetPosition(_editor)); + + if (hoveredOffset == -1) + return; + + bool hasDiagnostic = _editor.TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity, allowLineFallback: false); + bool canShowDiagnosticFallback = _editor._completionWindow is null && !_editor._signatureHelpController.IsVisible; + + if (!TryGetRequestOffset(hoveredOffset, out int hoverOffset) || !_editor.IsIntellisenseAvailable()) + { + ShowDiagnosticToolTipIfAvailable(canShowDiagnosticFallback, hasDiagnostic, diagnosticMessage, diagnosticSeverity); + return; + } + + CancellationToken cancellationToken = ResetCancellationTokenSource(ref _hoverCancellationTokenSource); + int hoverRequestToken = ++_hoverRequestToken; + + try + { + LuaHoverInfo? hoverInfo = await RequestAsync(hoverOffset, cancellationToken).ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) + return; + + int currentHoveredOffset = _editor.GetOffsetFromPoint(Mouse.GetPosition(_editor)); + + if (!LuaEditorInteractionRules.TryGetHoverOffset(_editor.Document, currentHoveredOffset, out int currentHoverOffset) + || currentHoverOffset != hoverOffset) + { + return; + } + + hasDiagnostic = _editor.TryGetDiagnosticInfo(currentHoveredOffset, out diagnosticMessage, out diagnosticSeverity, allowLineFallback: false); + ShowBestToolTip(hoverInfo, hasDiagnostic, diagnosticMessage, diagnosticSeverity); + } + catch (OperationCanceledException) + { + } + catch (Exception exception) + { + LogEditorFailure("Hover request", exception); + ShowDiagnosticToolTipIfAvailable(canShowDiagnosticFallback, hasDiagnostic, diagnosticMessage, diagnosticSeverity); + } + } + + public void CancelPendingRequest() + => CancelAndDispose(ref _hoverCancellationTokenSource); + + public void InvalidateRequests() + => _hoverRequestToken++; + + public bool TryGetRequestOffset(int hoveredOffset, out int hoverOffset) + { + hoverOffset = 0; + + if (!LuaEditorInteractionRules.CanRequestHover(_editor._completionWindow is not null, _editor._signatureHelpController.IsVisible)) + return false; + + if (!LuaEditorInteractionRules.TryGetHoverOffset(_editor.Document, hoveredOffset, out hoverOffset)) + return false; + + return !string.IsNullOrWhiteSpace(_editor.GetWordFromOffset(hoverOffset)); + } + + public void ShowDiagnosticToolTipIfAvailable(bool canShowDiagnosticFallback, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + { + if (canShowDiagnosticFallback && hasDiagnostic) + _editor.ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + } + + public void ShowBestToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + { + bool canShowToolTip = _editor._completionWindow is null && !_editor._signatureHelpController.IsVisible; + + if (!canShowToolTip) + return; + + LuaHoverInfo? displayableHoverInfo = hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) + ? hoverInfo + : null; + + if (displayableHoverInfo is not null && hasDiagnostic) + ShowCombinedToolTip(displayableHoverInfo, diagnosticMessage, diagnosticSeverity); + else if (displayableHoverInfo is not null) + ShowHoverToolTip(displayableHoverInfo); + else if (hasDiagnostic) + _editor.ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + } + + private void ShowCombinedToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) + { + GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); + + var panel = new StackPanel { MaxWidth = ToolTipTextMaxWidth }; + + panel.Children.Add(CreateHoverToolTipContent(hoverInfo)); + + panel.Children.Add(new Border + { + Background = diagnosticBackground, + BorderBrush = diagnosticBorder, + BorderThickness = new Thickness(1.0), + CornerRadius = new CornerRadius(3.0), + Padding = new Thickness(8.0, 4.0, 8.0, 4.0), + Margin = new Thickness(0.0, 6.0, 0.0, 0.0), + Child = new TextBlock + { + Text = diagnosticMessage, + Foreground = ToolTipForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = ToolTipTextFontSize, + TextWrapping = TextWrapping.Wrap, + MaxWidth = ToolTipTextMaxWidth + } + }); + + _editor.ShowToolTip(panel, DefaultToolTipBorder, DefaultToolTipBackground); + } + + private void ShowHoverToolTip(LuaHoverInfo hoverInfo) + => _editor.ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); + + private async Task RequestAsync(int offset, CancellationToken cancellationToken) + { + if (!_editor.IsIntellisenseAvailable()) + return null; + + var intellisenseProvider = _editor.IntellisenseProvider; + + if (intellisenseProvider is null) + return null; + + (int line, int column) = _editor.GetPositionFromOffset(offset); + + return await intellisenseProvider + .GetHoverAsync(_editor.FilePath, _editor.Text, line, column, cancellationToken) + .ConfigureAwait(true); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs b/TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs new file mode 100644 index 0000000000..ebeed12f23 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs @@ -0,0 +1,82 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Utils; + +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor +{ + private sealed class LuaDefinitionNavigationController + { + private readonly LuaEditor _editor; + private CancellationTokenSource? _definitionCancellationTokenSource; + private int _definitionRequestToken; + + public LuaDefinitionNavigationController(LuaEditor editor) + { + _editor = editor; + } + + public void CancelPendingRequest() + => CancelAndDispose(ref _definitionCancellationTokenSource); + + public void InvalidateRequests() + => _definitionRequestToken++; + + public async Task TryNavigateAsync(int offset, CancellationToken cancellationToken) + { + if (!_editor.IsIntellisenseAvailable()) + return false; + + var intellisenseProvider = _editor.IntellisenseProvider; + + if (intellisenseProvider is null) + return false; + + try + { + if (!LuaEditorInteractionRules.TryGetDefinitionStartOffset(_editor.Document, offset, out int definitionOffset)) + return false; + + CancellationToken definitionCancellationToken = ResetCancellationTokenSource(ref _definitionCancellationTokenSource); + using CancellationTokenSource? linkedCancellationTokenSource = cancellationToken.CanBeCanceled + ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, definitionCancellationToken) + : null; + + CancellationToken effectiveCancellationToken = linkedCancellationTokenSource?.Token ?? definitionCancellationToken; + int requestToken = ++_definitionRequestToken; + int requestDocumentVersion = _editor._editorDocumentVersion; + int requestGeneration = _editor._editorRequestGeneration; + + (int line, int column) = _editor.GetPositionFromOffset(definitionOffset); + + LuaDefinitionLocation? definitionLocation = await intellisenseProvider + .GetDefinitionAsync(_editor.FilePath, _editor.Text, line, column, effectiveCancellationToken) + .ConfigureAwait(true); + + if (!_editor.IsAsyncEditorResultCurrent(effectiveCancellationToken, requestToken, _definitionRequestToken, + requestDocumentVersion, requestGeneration)) + { + return false; + } + + if (definitionLocation is null) + return false; + + _editor.DefinitionNavigationRequested?.Invoke(definitionLocation); + return true; + } + catch (OperationCanceledException) + { + return false; + } + catch (Exception exception) + { + LogEditorFailure("Go to definition", exception); + return false; + } + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs b/TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs new file mode 100644 index 0000000000..9bc7132393 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs @@ -0,0 +1,354 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Documents; +using System.Windows.Media; +using System.Windows.Threading; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Resources; + +namespace TombLib.Scripting.Lua; + +public sealed partial class LuaEditor +{ + private const double SignaturePopupFontSize = 14.0; + + private void DismissSignatureHelp() + => _signatureHelpController.Dismiss(); + + private Task RequestSignatureHelpAsync(int offset) + => _signatureHelpController.RequestAsync(offset); + + private void ScheduleSignatureHelpRefresh() + => _signatureHelpController.ScheduleRefresh(); + + private static TextBlock CreateSignatureDocumentationBlock(string text, LuaThemeBrushSet brushSet) => new() + { + Text = text, + Foreground = brushSet.SignatureParamDocForeground, + FontFamily = SystemFonts.MessageFontFamily, + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, SignaturePopupFontSize), + TextWrapping = TextWrapping.Wrap, + Margin = new Thickness(0.0, 4.0, 0.0, 0.0) + }; + + private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo, LuaThemeBrushSet brushSet) + { + var textBlock = new TextBlock + { + FontFamily = new FontFamily("Consolas"), + FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, SignaturePopupFontSize), + TextWrapping = TextWrapping.Wrap, + Foreground = brushSet.SignatureForeground + }; + + string label = signatureInfo.Label; + + if (signatureInfo.Parameters.Count == 0 + || !TryGetActiveParameterRange(label, signatureInfo, out int activeStart, out int activeEnd)) + { + textBlock.Text = label; + return textBlock; + } + + if (activeStart > 0) + textBlock.Inlines.Add(new Run(label[..activeStart])); + + textBlock.Inlines.Add(new Run(label[activeStart..activeEnd]) + { + FontWeight = FontWeights.Bold, + Foreground = brushSet.SignatureActiveParamForeground + }); + + if (activeEnd < label.Length) + textBlock.Inlines.Add(new Run(label[activeEnd..])); + + return textBlock; + } + + private static bool TryGetActiveParameterRange(string label, LuaSignatureInfo signatureInfo, out int activeStart, out int activeEnd) + { + activeStart = 0; + activeEnd = 0; + + int activeIndex = Math.Min(signatureInfo.ActiveParameter, signatureInfo.Parameters.Count - 1); + + if (activeIndex < 0) + return false; + + string activeLabel = signatureInfo.Parameters[activeIndex].Label; + + if (string.IsNullOrEmpty(activeLabel)) + return false; + + int searchStart = label.IndexOf('('); + searchStart = searchStart < 0 ? 0 : searchStart + 1; + + int matchIndex = label.IndexOf(activeLabel, searchStart, StringComparison.Ordinal); + + if (matchIndex < 0) + return false; + + activeStart = matchIndex; + activeEnd = matchIndex + activeLabel.Length; + return true; + } + + private sealed class LuaSignatureHelpController + { + private const double SignatureHelpRefreshDebounceDelayInMilliseconds = 50.0; + + private readonly LuaEditor _editor; + private int _signatureRequestToken; + private int _pendingSignatureHelpOffset = -1; + private bool _signatureRefreshPending; + private bool _signatureRequestInFlight; + + private readonly Popup _signaturePopup = new(); + private readonly Border _signaturePopupBorder = new(); + private readonly ContentPresenter _signaturePopupPresenter = new(); + private readonly DispatcherTimer _signatureRefreshTimer = new(); + + public LuaSignatureHelpController(LuaEditor editor) + { + _editor = editor; + } + + public bool IsVisible => _signaturePopup.IsOpen; + + public bool IsActiveOrPending => _signaturePopup.IsOpen || _signatureRequestInFlight || _signatureRefreshPending; + + public void InitializePopup() + { + _signaturePopup.AllowsTransparency = true; + _signaturePopup.PopupAnimation = PopupAnimation.None; + _signaturePopup.StaysOpen = true; + _signaturePopup.Placement = PlacementMode.RelativePoint; + + _signaturePopupBorder.SnapsToDevicePixels = true; + _signaturePopupBorder.CornerRadius = new CornerRadius(3.0); + _signaturePopupBorder.BorderThickness = new Thickness(1.0); + _signaturePopupBorder.Padding = new Thickness(8.0, 6.0, 8.0, 6.0); + _signaturePopupBorder.BorderBrush = DefaultToolTipBorder; + _signaturePopupBorder.Background = DefaultToolTipBackground; + _signaturePopupBorder.Child = _signaturePopupPresenter; + + _signaturePopup.Child = _signaturePopupBorder; + + _signatureRefreshTimer.Interval = TimeSpan.FromMilliseconds(SignatureHelpRefreshDebounceDelayInMilliseconds); + _signatureRefreshTimer.Tick -= SignatureRefreshTimer_Tick; + _signatureRefreshTimer.Tick += SignatureRefreshTimer_Tick; + } + + public void Dismiss() + { + CancelPendingRefresh(); + InvalidateRequests(); + + if (_signaturePopup.IsOpen) + _signaturePopup.IsOpen = false; + + _signaturePopupPresenter.Content = null; + } + + public Task RequestAsync(int offset) + => RequestAsyncCore(offset); + + public void ScheduleRefresh() + { + _pendingSignatureHelpOffset = _editor.CaretOffset; + _signatureRefreshPending = true; + _signatureRefreshTimer.Stop(); + _signatureRefreshTimer.Start(); + } + + public void CancelPendingRefresh() + { + _signatureRefreshTimer.Stop(); + _signatureRefreshPending = false; + _pendingSignatureHelpOffset = -1; + } + + public void InvalidateRequests() + { + _signatureRequestToken++; + _signatureRequestInFlight = false; + } + + public void HandleRefreshTimerTick(object? sender, EventArgs e) + => SignatureRefreshTimer_Tick(sender, e); + + private void ShowToolTip(LuaSignatureInfo signatureInfo) + { + double availablePopupWidth = Math.Max(0.0, Math.Min(500.0, _editor.ActualWidth - 16.0)); + + double popupHorizontalPadding = _signaturePopupBorder.Padding.Left + + _signaturePopupBorder.Padding.Right + + _signaturePopupBorder.BorderThickness.Left + + _signaturePopupBorder.BorderThickness.Right; + + double popupVerticalPadding = _signaturePopupBorder.Padding.Top + + _signaturePopupBorder.Padding.Bottom + + _signaturePopupBorder.BorderThickness.Top + + _signaturePopupBorder.BorderThickness.Bottom; + + double contentMaxWidth = Math.Max(0.0, availablePopupWidth - popupHorizontalPadding); + + StackPanel panel = CreatePanel(signatureInfo, contentMaxWidth); + + panel.Measure(new Size(contentMaxWidth, double.PositiveInfinity)); + + Size popupSize = new( + Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), + panel.DesiredSize.Height + popupVerticalPadding); + + _signaturePopupPresenter.Content = panel; + _signaturePopupPresenter.InvalidateMeasure(); + _signaturePopupBorder.InvalidateMeasure(); + PositionPopup(popupSize); + + if (!_signaturePopup.IsOpen) + _signaturePopup.IsOpen = true; + } + + private StackPanel CreatePanel(LuaSignatureInfo signatureInfo, double contentMaxWidth) + { + LuaThemeBrushSet brushSet = _editor.GetThemeBrushSet(); + var panel = new StackPanel { MaxWidth = contentMaxWidth }; + panel.Children.Add(BuildSignatureBlock(signatureInfo, brushSet)); + + if (!string.IsNullOrWhiteSpace(signatureInfo.Documentation)) + panel.Children.Add(CreateSignatureDocumentationBlock(signatureInfo.Documentation, brushSet)); + + if (signatureInfo.ActiveParameter < signatureInfo.Parameters.Count) + { + LuaParameterInfo activeParameter = signatureInfo.Parameters[signatureInfo.ActiveParameter]; + + if (!string.IsNullOrWhiteSpace(activeParameter.Documentation)) + panel.Children.Add(CreateSignatureDocumentationBlock(activeParameter.Label + ": " + activeParameter.Documentation, brushSet)); + } + + return panel; + } + + private void PositionPopup(Size popupSize) + { + _editor.AttachHostWindowHandlers(); + _signaturePopup.PlacementTarget = _editor; + _editor.TextArea.TextView.EnsureVisualLines(); + + Rect caretRectangle = _editor.TextArea.Caret.CalculateCaretRectangle(); + Vector scrollOffset = _editor.TextArea.TextView.ScrollOffset; + + Point caretViewportPoint = new( + caretRectangle.X - scrollOffset.X, + caretRectangle.Y - scrollOffset.Y); + + Point editorPoint = _editor.TextArea.TextView.TranslatePoint(caretViewportPoint, _editor); + double lineHeight = Math.Max(_editor.TextArea.TextView.DefaultLineHeight, caretRectangle.Height); + double lineSlack = Math.Max(0.0, lineHeight - caretRectangle.Height); + double horizontalOffset = Math.Max(0.0, editorPoint.X + 2.0); + double maxHorizontalOffset = Math.Max(0.0, _editor.ActualWidth - popupSize.Width - 8.0); + horizontalOffset = Math.Min(horizontalOffset, maxHorizontalOffset); + + double verticalOffset = editorPoint.Y - popupSize.Height - lineSlack - 8.0; + + if (verticalOffset < 0.0) + verticalOffset = Math.Min(Math.Max(0.0, _editor.ActualHeight - popupSize.Height), editorPoint.Y + lineHeight + 4.0); + + _signaturePopup.HorizontalOffset = horizontalOffset; + _signaturePopup.VerticalOffset = verticalOffset; + } + + private async Task RequestAsyncCore(int offset) + { + if (_signatureRequestInFlight) + { + _pendingSignatureHelpOffset = offset; + _signatureRefreshPending = true; + return; + } + + _signatureRequestInFlight = true; + + if (!_editor.IsIntellisenseAvailable()) + { + _signatureRequestInFlight = false; + Dismiss(); + return; + } + + var intellisenseProvider = _editor.IntellisenseProvider; + + if (intellisenseProvider is null) + { + _signatureRequestInFlight = false; + Dismiss(); + return; + } + + CancellationToken cancellationToken = CancellationToken.None; + int requestToken = ++_signatureRequestToken; + int requestDocumentVersion = _editor._editorDocumentVersion; + int requestGeneration = _editor._editorRequestGeneration; + + try + { + (int line, int column) = _editor.GetPositionFromOffset(offset); + + LuaSignatureInfo? signatureInfo = await intellisenseProvider + .GetSignatureHelpAsync(_editor.FilePath, _editor.Text, line, column, cancellationToken) + .ConfigureAwait(true); + + if (!_editor.IsAsyncEditorResultCurrent(cancellationToken, requestToken, _signatureRequestToken, + requestDocumentVersion, requestGeneration)) + { + return; + } + + if (signatureInfo is null) + { + Dismiss(); + return; + } + + ShowToolTip(signatureInfo); + } + catch (OperationCanceledException) + { + } + catch (Exception exception) + { + LogEditorFailure("Signature help", exception); + } + finally + { + _signatureRequestInFlight = false; + + if (_signatureRefreshPending && _pendingSignatureHelpOffset >= 0) + { + _signatureRefreshTimer.Stop(); + _signatureRefreshTimer.Start(); + } + } + } + + private async void SignatureRefreshTimer_Tick(object? sender, EventArgs e) + { + _signatureRefreshTimer.Stop(); + + if (!_signatureRefreshPending || _pendingSignatureHelpOffset < 0) + return; + + if (_signatureRequestInFlight) + return; + + int offset = _pendingSignatureHelpOffset; + _signatureRefreshPending = false; + await RequestAsyncCore(offset).ConfigureAwait(true); + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs deleted file mode 100644 index 7f803d9917..0000000000 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs +++ /dev/null @@ -1,487 +0,0 @@ -using ICSharpCode.AvalonEdit.CodeCompletion; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Reflection; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Input; -using System.Windows.Interop; -using System.Windows.Media; -using System.Windows.Threading; -using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Lua.Utils; -using TombLib.WPF; - -namespace TombLib.Scripting.Lua; - -public sealed partial class LuaEditor -{ - private const double CompletionRequestDebounceDelayInMilliseconds = 120.0; - private const int CompletionWindowMinWidth = 420; - private const int CompletionWindowMaxWidth = 920; - private const int CompletionWindowHeight = 320; - private const int CompletionWidthMeasurementSampleCount = 80; - private const double CompletionToolTipHorizontalOffset = 10.0; - private const double CompletionToolTipResolveDelayInMilliseconds = 120.0; - private const double CompletionWindowHorizontalChrome = 52.0; - private const double CompletionItemIconWidth = 24.0; - private const double CompletionItemDetailSpacing = 12.0; - - // Reflection target: AvalonEdit's CompletionWindow keeps the documentation tooltip in a private field named "toolTip". - // Verified against the AvalonEdit version pinned in TombLib.Scripting.Lua.csproj. - private static readonly Lazy CompletionToolTipFieldAccessor = new(() => - { - FieldInfo? field = typeof(CompletionWindow).GetField("toolTip", BindingFlags.NonPublic | BindingFlags.Instance); - - if (field is null) - Log?.Debug("AvalonEdit completion tooltip styling is unavailable because the internal tooltip field could not be found."); - - return field; - }); - - private static FieldInfo? CompletionToolTipField => CompletionToolTipFieldAccessor.Value; - - private readonly DispatcherTimer _completionRequestTimer = new(); - private readonly DispatcherTimer _completionToolTipUpdateTimer = new(); - private int _completionRequestToken; - private int _completionToolTipUpdateToken; - private ToolTip? _pendingCompletionToolTip; - - private void InitializeCompletionScheduling() - { - _completionRequestTimer.Interval = TimeSpan.FromMilliseconds(CompletionRequestDebounceDelayInMilliseconds); - _completionRequestTimer.Tick -= CompletionRequestTimer_Tick; - _completionRequestTimer.Tick += CompletionRequestTimer_Tick; - - _completionToolTipUpdateTimer.Interval = TimeSpan.FromMilliseconds(CompletionToolTipResolveDelayInMilliseconds); - _completionToolTipUpdateTimer.Tick -= CompletionToolTipUpdateTimer_Tick; - _completionToolTipUpdateTimer.Tick += CompletionToolTipUpdateTimer_Tick; - } - - private void CloseCompletionWindow() - { - InvalidateCompletionRequests(); - CloseCompletionWindowCore(); - } - - private void CloseCompletionWindowForRefresh() - => CloseCompletionWindowCore(); - - private void CloseCompletionWindowCore() - { - CancelPendingCompletionRequest(); - CancelCompletionToolTipUpdate(); - - if (_completionWindow is null) - return; - - if (CompletionToolTipField?.GetValue(_completionWindow) is ToolTip tooltip) - tooltip.IsOpen = false; - - _completionWindow.Close(); - _completionWindow = null; - } - - private void InvalidateCompletionRequests() - => _completionRequestToken++; - - private void InitializeLuaCompletionWindow() - { - InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); - LuaCompletionWindowStyle.Apply(_completionWindow, GetThemeBrushSet()); - StyleCompletionTooltip(); - MakeCompletionWindowNonActivatable(); - } - - private void ScheduleCompletionRequest() - { - _completionRequestTimer.Stop(); - _completionRequestTimer.Start(); - } - - private void CancelPendingCompletionRequest() - => _completionRequestTimer.Stop(); - - private async void CompletionRequestTimer_Tick(object? sender, EventArgs e) - { - _completionRequestTimer.Stop(); - - if (!AutocompleteEnabled || !IsIntellisenseAvailable()) - return; - - if (!LuaEditorInteractionRules.IsValidAutocompleteContext(Document, CaretOffset, triggerCharacter: null)) - return; - - await RequestCompletionAsync(CaretOffset, null).ConfigureAwait(true); - } - - private async Task RequestCompletionAsync(int offset, char? triggerCharacter) - { - CancellationToken cancellationToken = CancellationToken.None; - int requestToken = ++_completionRequestToken; - int requestDocumentVersion = _editorDocumentVersion; - int requestGeneration = _editorRequestGeneration; - - try - { - // Validate the request context up front, then dismiss competing transient UI before asking LuaLS. - if (!IsIntellisenseAvailable()) - return; - - DismissSignatureHelp(); - CloseDefinitionToolTip(true); - - (int Line, int Column) = GetPositionFromOffset(offset); - - var items = await IntellisenseProvider - .GetCompletionItemsAsync(FilePath, Text, Line, Column, triggerCharacter, cancellationToken) - .ConfigureAwait(true); - - if (!IsAsyncEditorResultCurrent(cancellationToken, requestToken, _completionRequestToken, - requestDocumentVersion, requestGeneration)) - return; - - if (items is null || items.Count == 0) - { - CloseCompletionWindow(); - return; - } - - // Materialize the provider response into AvalonEdit completion rows using the current theme. - var completionDataItems = new LuaCompletionData[items.Count]; - var brushSet = GetThemeBrushSet(); - - for (int i = 0; i < items.Count; i++) - { - LuaCompletionItem completionItem = items[i].WithRequestContext(requestDocumentVersion, requestGeneration); - completionDataItems[i] = new LuaCompletionData(completionItem, brushSet, CanApplyCompletionItem); - } - - if (!IsAsyncEditorResultCurrent(cancellationToken, requestToken, _completionRequestToken, - requestDocumentVersion, requestGeneration)) - return; - - // Recreate the popup from scratch so stale selection and tooltip state never leaks between requests. - CloseCompletionWindowForRefresh(); - - InitializeLuaCompletionWindow(); - ResizeCompletionWindow(completionDataItems); - SetCompletionWindowOffsets(offset); - - foreach (LuaCompletionData completionDataItem in completionDataItems) - _completionWindow.CompletionList.CompletionData.Add(completionDataItem); - - if (_completionWindow.CompletionList.CompletionData.Count > 0) - { - ShowCompletionWindow(); - ScheduleInitialSelection(); - } - } - catch (OperationCanceledException) - { } - catch (Exception exception) - { - CloseCompletionWindow(); - LogEditorFailure("Completion request", exception); - } - } - - private bool CanApplyCompletionItem(LuaCompletionItem item) - => IsCompletionItemCurrent(item.RequestDocumentVersion, _editorDocumentVersion, - item.RequestGeneration, _editorRequestGeneration, IsLoaded, IsIntellisenseAvailable()); - - private void RebaseOpenCompletionItems() - { - if (_completionWindow?.CompletionList?.CompletionData is null) - return; - - for (int i = 0; i < _completionWindow.CompletionList.CompletionData.Count; i++) - { - if (_completionWindow.CompletionList.CompletionData[i] is LuaCompletionData completionData) - completionData.RebaseForCurrentDocument(_editorDocumentVersion, _editorRequestGeneration); - } - } - - private static bool IsCompletionItemCurrent(int? requestDocumentVersion, - int currentDocumentVersion, - int? requestGeneration, - int currentGeneration, - bool isEditorLoaded, - bool isIntellisenseAvailable) - { - if (!isEditorLoaded || !isIntellisenseAvailable) - return false; - - if (!requestDocumentVersion.HasValue && !requestGeneration.HasValue) - return true; - - if (!requestDocumentVersion.HasValue || !requestGeneration.HasValue) - return false; - - return requestDocumentVersion.Value == currentDocumentVersion - && requestGeneration.Value == currentGeneration; - } - - private void StyleCompletionTooltip() - { - if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) - return; - - if (CompletionToolTipField?.GetValue(_completionWindow) is not ToolTip tooltip) - return; - - tooltip.Background = DefaultToolTipBackground; - tooltip.BorderBrush = DefaultToolTipBorder; - tooltip.BorderThickness = new Thickness(0.0); - tooltip.Padding = new Thickness(0.0); - tooltip.PlacementTarget = listBox; - tooltip.Placement = PlacementMode.Right; - tooltip.HorizontalOffset = CompletionToolTipHorizontalOffset; - tooltip.StaysOpen = true; - - listBox.SelectionChanged += (s, e) => ScheduleCompletionTooltipUpdate(tooltip); - listBox.PreviewMouseLeftButtonUp += (s, e) => HandleCompletionListClick(listBox, tooltip, e); - } - - private void HandleCompletionListClick(ListBox listBox, ToolTip tooltip, MouseButtonEventArgs e) - { - ListBoxItem? listBoxItem = (e.OriginalSource as DependencyObject)?.FindVisualAncestorOrSelf(); - - if (listBoxItem is null) - return; - - if (!ReferenceEquals(listBox.SelectedItem, listBoxItem.DataContext)) - listBox.SelectedItem = listBoxItem.DataContext; - - listBox.ScrollIntoView(listBoxItem.DataContext); - ScheduleCompletionTooltipUpdate(tooltip); - } - - private void ScheduleCompletionTooltipUpdate(ToolTip tooltip) - { - _pendingCompletionToolTip = tooltip; - _completionToolTipUpdateToken++; - _completionToolTipUpdateTimer.Stop(); - _completionToolTipUpdateTimer.Start(); - } - - private async void CompletionToolTipUpdateTimer_Tick(object? sender, EventArgs e) - { - _completionToolTipUpdateTimer.Stop(); - - if (_pendingCompletionToolTip is not ToolTip tooltip) - return; - - await UpdateCompletionTooltipAsync(tooltip, _completionToolTipUpdateToken).ConfigureAwait(true); - } - - private async Task UpdateCompletionTooltipAsync(ToolTip tooltip, int updateToken) - { - if (_completionWindow?.CompletionList.ListBox is not ListBox listBox) - return; - - if (listBox.SelectedItem is not ICompletionData item) - { - tooltip.IsOpen = false; - return; - } - - try - { - object? description = item.Description; - - if (description is not null) - ApplyCompletionToolTipContent(tooltip, description); - else - tooltip.IsOpen = false; - - if (item is LuaCompletionData luaCompletionData && luaCompletionData.CanResolve) - { - if (updateToken != _completionToolTipUpdateToken) - return; - - object? resolvedDescription = await luaCompletionData.GetDescriptionAsync().ConfigureAwait(true); - - if (updateToken != _completionToolTipUpdateToken) - return; - - if (_completionWindow?.CompletionList.ListBox is not ListBox currentListBox - || !ReferenceEquals(currentListBox, listBox) - || !ReferenceEquals(currentListBox.SelectedItem, item)) - { - return; - } - - if (resolvedDescription is not null) - ApplyCompletionToolTipContent(tooltip, resolvedDescription); - else - tooltip.IsOpen = false; - } - } - catch (Exception exception) - { - tooltip.IsOpen = false; - LogEditorFailure("Completion tooltip update", exception); - } - } - - private void ResizeCompletionWindow(LuaCompletionData[] completionDataItems) - { - if (_completionWindow is null || completionDataItems is null || completionDataItems.Length == 0) - return; - - double requiredWidth = CompletionWindowMinWidth; - int measurementCount = Math.Min(completionDataItems.Length, CompletionWidthMeasurementSampleCount); - var textWidthCache = new Dictionary(StringComparer.Ordinal); - - for (int i = 0; i < measurementCount; i++) - requiredWidth = Math.Max(requiredWidth, MeasureCompletionItemWidth(completionDataItems[i], textWidthCache)); - - _completionWindow.Width = Math.Max( - CompletionWindowMinWidth, - Math.Min(CompletionWindowMaxWidth, requiredWidth + CompletionWindowHorizontalChrome)); - } - - private double MeasureCompletionItemWidth(LuaCompletionData completionData, IDictionary textWidthCache) - { - double width = CompletionItemIconWidth + MeasureCompletionTextWidth(completionData.DisplayText, textWidthCache); - - if (!string.IsNullOrWhiteSpace(completionData.DisplayDetail)) - width += CompletionItemDetailSpacing + MeasureCompletionTextWidth(completionData.DisplayDetail, textWidthCache); - - return width; - } - - private double MeasureCompletionTextWidth(string text, IDictionary textWidthCache) - { - if (string.IsNullOrWhiteSpace(text)) - return 0.0; - - if (textWidthCache.TryGetValue(text, out double cachedWidth)) - return cachedWidth; - - double pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip; - - var formattedText = new FormattedText( - text, - CultureInfo.CurrentUICulture, - FlowDirection.LeftToRight, - new Typeface(FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), - FontSize, - Foreground, - pixelsPerDip); - - double width = formattedText.WidthIncludingTrailingWhitespace; - textWidthCache[text] = width; - return width; - } - - private static void ApplyCompletionToolTipContent(ToolTip tooltip, object content) - { - tooltip.Content = content; - - if (!tooltip.IsOpen) - { - tooltip.IsOpen = true; - } - else - { - tooltip.InvalidateMeasure(); - tooltip.InvalidateVisual(); - } - } - - private void CancelCompletionToolTipUpdate() - { - _completionToolTipUpdateToken++; - _pendingCompletionToolTip = null; - _completionToolTipUpdateTimer.Stop(); - } - - private void ScheduleCloseIfEmpty() - => Dispatcher.BeginInvoke(new Action(() => CloseCompletionWindowIfEmpty()), DispatcherPriority.Background); - - private void ScheduleInitialSelection() - => Dispatcher.BeginInvoke(new Action(SelectInitialItem), DispatcherPriority.ContextIdle); - - private void SelectInitialItem() - { - if (_completionWindow is null) - return; - - _completionWindow.CompletionList.SelectItem(GetCompletionWindowQuery()); - CloseCompletionWindowIfEmpty(); - } - - private void MakeCompletionWindowNonActivatable() - { - _completionWindow.SourceInitialized += (s, e) => - { - if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) - source.AddHook(CompletionWindowWndProc); - }; - } - - private static IntPtr CompletionWindowWndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) - { - const int WM_MOUSEACTIVATE = 0x0021; - const int MA_NOACTIVATE = 3; - - if (msg == WM_MOUSEACTIVATE) - { - handled = true; - return new IntPtr(MA_NOACTIVATE); - } - - return IntPtr.Zero; - } - - private bool CloseCompletionWindowIfEmpty() - { - if (_completionWindow is null) - return false; - - ListBox listBox = _completionWindow.CompletionList.ListBox; - - if (listBox?.HasItems != false) - return false; - - CloseCompletionWindow(); - return true; - } - - private string GetCompletionWindowQuery() - { - if (_completionWindow is null || Document is null) - return string.Empty; - - int startOffset = Math.Max(0, Math.Min(_completionWindow.StartOffset, Document.TextLength)); - int endOffset = Math.Max(startOffset, Math.Min(_completionWindow.EndOffset, Document.TextLength)); - - return endOffset > startOffset - ? Document.GetText(startOffset, endOffset - startOffset) - : string.Empty; - } - - private void SetCompletionWindowOffsets(int offset) - { - int startOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); - - while (startOffset > 0) - { - char currentChar = Document.GetCharAt(startOffset - 1); - - if (LuaLineParser.IsIdentifierCharacter(currentChar)) - startOffset--; - else - break; - } - - _completionWindow.StartOffset = startOffset; - _completionWindow.EndOffset = Math.Max(0, Math.Min(offset, Document.TextLength)); - } -} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs deleted file mode 100644 index eafa643931..0000000000 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Lua.Utils; -using TombLib.Scripting.Objects; -using TombLib.Scripting.Rendering; - -namespace TombLib.Scripting.Lua; - -public sealed partial class LuaEditor -{ - private CancellationTokenSource? _hoverCancellationTokenSource; - private int _hoverRequestToken; - - protected override async void HandleMouseHover(MouseEventArgs e) - { - int hoveredOffset = GetOffsetFromPoint(e.GetPosition(this)); - - if (hoveredOffset == -1) - return; - - bool hasDiagnostic = TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity, allowLineFallback: false); - bool canShowDiagnosticFallback = _completionWindow is null && !_signaturePopup.IsOpen; - - if (!TryGetHoverRequestOffset(hoveredOffset, out int hoverOffset) || !IsIntellisenseAvailable()) - { - ShowDiagnosticToolTipIfAvailable(canShowDiagnosticFallback, hasDiagnostic, diagnosticMessage, diagnosticSeverity); - return; - } - - CancellationToken cancellationToken = ResetCancellationTokenSource(ref _hoverCancellationTokenSource); - int hoverRequestToken = ++_hoverRequestToken; - - try - { - LuaHoverInfo? hoverInfo = await RequestHoverAsync(hoverOffset, cancellationToken).ConfigureAwait(true); - - if (cancellationToken.IsCancellationRequested || hoverRequestToken != _hoverRequestToken) - return; - - int currentHoveredOffset = GetOffsetFromPoint(Mouse.GetPosition(this)); - - if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, currentHoveredOffset, out int currentHoverOffset) - || currentHoverOffset != hoverOffset) - { - return; - } - - hasDiagnostic = TryGetDiagnosticInfo(currentHoveredOffset, out diagnosticMessage, out diagnosticSeverity, allowLineFallback: false); - ShowBestHoverToolTip(hoverInfo, hasDiagnostic, diagnosticMessage, diagnosticSeverity); - } - catch (OperationCanceledException) - { } - catch (Exception exception) - { - LogEditorFailure("Hover request", exception); - ShowDiagnosticToolTipIfAvailable(canShowDiagnosticFallback, hasDiagnostic, diagnosticMessage, diagnosticSeverity); - } - } - - private bool TryGetHoverRequestOffset(int hoveredOffset, out int hoverOffset) - { - hoverOffset = 0; - - if (!LuaEditorInteractionRules.CanRequestHover(_completionWindow is not null, _signaturePopup.IsOpen)) - return false; - - if (!LuaEditorInteractionRules.TryGetHoverOffset(Document, hoveredOffset, out hoverOffset)) - return false; - - return !string.IsNullOrWhiteSpace(GetWordFromOffset(hoverOffset)); - } - - private void ShowDiagnosticToolTipIfAvailable(bool canShowDiagnosticFallback, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) - { - if (canShowDiagnosticFallback && hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); - } - - private void ShowBestHoverToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) - { - // Recompute eligibility: a completion window or signature popup may have opened during the - // asynchronous hover request; we must not paint a hover tooltip on top of either of them. - bool canShowToolTip = _completionWindow is null && !_signaturePopup.IsOpen; - - if (!canShowToolTip) - return; - - LuaHoverInfo? displayableHoverInfo = hoverInfo is not null && !string.IsNullOrWhiteSpace(hoverInfo.Content) - ? hoverInfo - : null; - - if (displayableHoverInfo is not null && hasDiagnostic) - ShowCombinedHoverAndDiagnosticToolTip(displayableHoverInfo, diagnosticMessage, diagnosticSeverity); - else if (displayableHoverInfo is not null) - ShowHoverToolTip(displayableHoverInfo); - else if (hasDiagnostic) - ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); - } - - private void ShowCombinedHoverAndDiagnosticToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) - { - GetDiagnosticToolTipColors(severity, out SolidColorBrush diagnosticBorder, out SolidColorBrush diagnosticBackground); - - var panel = new StackPanel { MaxWidth = ToolTipTextMaxWidth }; - - panel.Children.Add(CreateHoverToolTipContent(hoverInfo)); - - panel.Children.Add(new Border - { - Background = diagnosticBackground, - BorderBrush = diagnosticBorder, - BorderThickness = new Thickness(1.0), - CornerRadius = new CornerRadius(3.0), - Padding = new Thickness(8.0, 4.0, 8.0, 4.0), - Margin = new Thickness(0.0, 6.0, 0.0, 0.0), - Child = new TextBlock - { - Text = diagnosticMessage, - Foreground = ToolTipForeground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = ToolTipTextFontSize, - TextWrapping = TextWrapping.Wrap, - MaxWidth = ToolTipTextMaxWidth - } - }); - - ShowToolTip(panel, DefaultToolTipBorder, DefaultToolTipBackground); - } - - private void ShowHoverToolTip(LuaHoverInfo hoverInfo) - => ShowToolTip(CreateHoverToolTipContent(hoverInfo), DefaultToolTipBorder, DefaultToolTipBackground); - - private static FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo) => hoverInfo.IsMarkdown - ? MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground) - : MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); - - private async Task RequestHoverAsync(int offset, CancellationToken cancellationToken) - { - if (!IsIntellisenseAvailable()) - return null; - - (int Line, int Column) = GetPositionFromOffset(offset); - - return await IntellisenseProvider - .GetHoverAsync(FilePath, Text, Line, Column, cancellationToken) - .ConfigureAwait(true); - } -} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs index 61feb6cf1a..cc9c3ef3fa 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs @@ -14,7 +14,7 @@ public sealed partial class LuaEditor private void BindLuaIntellisenseEvents() { - InitializeCompletionScheduling(); + _completionController.InitializeScheduling(); Document.Changed += LuaEditor_DocumentChanged; IsKeyboardFocusWithinChanged += LuaEditor_IsKeyboardFocusWithinChanged; @@ -78,11 +78,11 @@ private void LuaEditor_Unloaded(object? sender, RoutedEventArgs e) InvalidateAsyncEditorRequests(); CancelPendingCompletionRequest(); - CancelAndDispose(ref _hoverCancellationTokenSource); + _hoverController.CancelPendingRequest(); - CancelCompletionToolTipUpdate(); + _completionController.CancelTooltipUpdate(); - CancelAndDispose(ref _definitionCancellationTokenSource); + _definitionNavigationController.CancelPendingRequest(); CloseCompletionWindow(); if (_hostWindow is not null) @@ -121,7 +121,7 @@ private async void TextArea_TextEntered(object? sender, TextCompositionEventArgs { CancelPendingCompletionRequest(); CloseCompletionWindow(); - CancelPendingSignatureHelpRefresh(); + _signatureHelpController.CancelPendingRefresh(); await RequestSignatureHelpAsync(CaretOffset).ConfigureAwait(true); return; } @@ -198,8 +198,8 @@ private static bool ShouldKeepCompletionWindowOpen(string? inputText) private void DismissTransientToolTips() { CancelPendingCompletionRequest(); - CancelAndDispose(ref _hoverCancellationTokenSource); - _hoverRequestToken++; + _hoverController.CancelPendingRequest(); + _hoverController.InvalidateRequests(); DismissSignatureHelp(); CloseDefinitionToolTip(true); } @@ -245,10 +245,10 @@ protected override void OnAutoClosingElementSkipped(string element) private void InvalidateAsyncEditorRequests() { _editorRequestGeneration++; - _completionRequestToken++; - _hoverRequestToken++; - _signatureRequestToken++; - _definitionRequestToken++; + _completionController.InvalidateRequests(); + _hoverController.InvalidateRequests(); + _signatureHelpController.InvalidateRequests(); + _definitionNavigationController.InvalidateRequests(); } private bool IsAsyncEditorResultCurrent(CancellationToken cancellationToken, @@ -288,7 +288,7 @@ private static bool IsAsyncEditorResultCurrent(bool isCancellationRequested, } private bool ShouldRefreshSignatureHelpAfterTextInput(string? inputText) - => ShouldRefreshSignatureHelpAfterTextInput(inputText, _signaturePopup.IsOpen || _signatureRequestInFlight || _signatureRefreshPending); + => ShouldRefreshSignatureHelpAfterTextInput(inputText, _signatureHelpController.IsActiveOrPending); private static bool ShouldRefreshSignatureHelpAfterTextInput(string? inputText, bool isSignatureHelpActiveOrPending) => isSignatureHelpActiveOrPending && inputText?.Length == 1; diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs index 75da8b7a49..d88a517b20 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs @@ -1,20 +1,14 @@ -using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; -using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Lua.Utils; namespace TombLib.Scripting.Lua; public sealed partial class LuaEditor { - private CancellationTokenSource? _definitionCancellationTokenSource; - private int _definitionRequestToken; - private async void TextEditor_KeyDown(object? sender, KeyEventArgs e) { - if (e.Key == Key.Escape && (_completionWindow is not null || _signaturePopup.IsOpen || _specialToolTip.IsOpen)) + if (e.Key == Key.Escape && (_completionWindow is not null || _signatureHelpController.IsVisible || _specialToolTip.IsOpen)) { CloseCompletionWindow(); DismissTransientToolTips(); @@ -22,12 +16,12 @@ private async void TextEditor_KeyDown(object? sender, KeyEventArgs e) return; } - if (_signaturePopup.IsOpen && (e.Key == Key.Back || e.Key == Key.Delete)) + if (_signatureHelpController.IsVisible && (e.Key == Key.Back || e.Key == Key.Delete)) ScheduleSignatureHelpRefresh(); if (e.Key == Key.F12) { - if (await TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true)) + if (await _definitionNavigationController.TryNavigateAsync(CaretOffset, CancellationToken.None).ConfigureAwait(true)) e.Handled = true; } } @@ -51,60 +45,14 @@ private async void TextEditor_PreviewMouseLeftButtonDown(object? sender, MouseBu if (hoveredOffset == -1) return; - if (await TryNavigateToDefinitionAsync(hoveredOffset, CancellationToken.None).ConfigureAwait(true)) + if (await _definitionNavigationController.TryNavigateAsync(hoveredOffset, CancellationToken.None).ConfigureAwait(true)) e.Handled = true; } - private async Task TryNavigateToDefinitionAsync(int offset, CancellationToken cancellationToken) - { - if (!IsIntellisenseAvailable()) - return false; - - try - { - if (!LuaEditorInteractionRules.TryGetDefinitionStartOffset(Document, offset, out int definitionOffset)) - return false; - - CancellationToken definitionCancellationToken = ResetCancellationTokenSource(ref _definitionCancellationTokenSource); - using CancellationTokenSource? linkedCancellationTokenSource = cancellationToken.CanBeCanceled - ? CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, definitionCancellationToken) - : null; - - CancellationToken effectiveCancellationToken = linkedCancellationTokenSource?.Token ?? definitionCancellationToken; - int requestToken = ++_definitionRequestToken; - int requestDocumentVersion = _editorDocumentVersion; - int requestGeneration = _editorRequestGeneration; - - (int Line, int Column) = GetPositionFromOffset(definitionOffset); - - LuaDefinitionLocation? definitionLocation = await IntellisenseProvider - .GetDefinitionAsync(FilePath, Text, Line, Column, effectiveCancellationToken) - .ConfigureAwait(true); - - if (!IsAsyncEditorResultCurrent(effectiveCancellationToken, requestToken, _definitionRequestToken, requestDocumentVersion, requestGeneration)) - return false; - - if (definitionLocation is null) - return false; - - DefinitionNavigationRequested?.Invoke(definitionLocation); - return true; - } - catch (OperationCanceledException) - { - return false; - } - catch (Exception exception) - { - LogEditorFailure("Go to definition", exception); - return false; - } - } - /// /// Attempts to resolve and navigate to the symbol definition at the current caret position. /// /// A task that completes once the navigation attempt finishes. public Task NavigateToDefinitionAtCaretAsync() - => TryNavigateToDefinitionAsync(CaretOffset, CancellationToken.None); + => _definitionNavigationController.TryNavigateAsync(CaretOffset, CancellationToken.None); } diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs deleted file mode 100644 index 3c176a5f3e..0000000000 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs +++ /dev/null @@ -1,312 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Documents; -using System.Windows.Media; -using System.Windows.Threading; -using TombLib.Scripting.Lua.Objects; -using TombLib.Scripting.Lua.Resources; - -namespace TombLib.Scripting.Lua; - -public sealed partial class LuaEditor -{ - private const double SignaturePopupFontSize = 14.0; - private const double SignatureHelpRefreshDebounceDelayInMilliseconds = 50.0; - - private int _signatureRequestToken; - private int _pendingSignatureHelpOffset = -1; - private bool _signatureRefreshPending; - private bool _signatureRequestInFlight; - - private readonly Popup _signaturePopup = new(); - private readonly Border _signaturePopupBorder = new(); - private readonly ContentPresenter _signaturePopupPresenter = new(); - private readonly DispatcherTimer _signatureRefreshTimer = new(); - - private void InitializeSignaturePopup() - { - _signaturePopup.AllowsTransparency = true; - _signaturePopup.PopupAnimation = PopupAnimation.None; - _signaturePopup.StaysOpen = true; - _signaturePopup.Placement = PlacementMode.RelativePoint; - - _signaturePopupBorder.SnapsToDevicePixels = true; - _signaturePopupBorder.CornerRadius = new CornerRadius(3.0); - _signaturePopupBorder.BorderThickness = new Thickness(1.0); - _signaturePopupBorder.Padding = new Thickness(8.0, 6.0, 8.0, 6.0); - _signaturePopupBorder.BorderBrush = DefaultToolTipBorder; - _signaturePopupBorder.Background = DefaultToolTipBackground; - _signaturePopupBorder.Child = _signaturePopupPresenter; - - _signaturePopup.Child = _signaturePopupBorder; - - _signatureRefreshTimer.Interval = TimeSpan.FromMilliseconds(SignatureHelpRefreshDebounceDelayInMilliseconds); - _signatureRefreshTimer.Tick -= SignatureRefreshTimer_Tick; - _signatureRefreshTimer.Tick += SignatureRefreshTimer_Tick; - } - - private void DismissSignatureHelp() - { - CancelPendingSignatureHelpRefresh(); - InvalidateSignatureHelpRequests(); - - if (_signaturePopup.IsOpen) - _signaturePopup.IsOpen = false; - - _signaturePopupPresenter.Content = null; - } - - private void ShowSignatureToolTip(LuaSignatureInfo signatureInfo) - { - double availablePopupWidth = Math.Max(0.0, Math.Min(500.0, ActualWidth - 16.0)); - - double popupHorizontalPadding = _signaturePopupBorder.Padding.Left - + _signaturePopupBorder.Padding.Right - + _signaturePopupBorder.BorderThickness.Left - + _signaturePopupBorder.BorderThickness.Right; - - double popupVerticalPadding = _signaturePopupBorder.Padding.Top - + _signaturePopupBorder.Padding.Bottom - + _signaturePopupBorder.BorderThickness.Top - + _signaturePopupBorder.BorderThickness.Bottom; - - double contentMaxWidth = Math.Max(0.0, availablePopupWidth - popupHorizontalPadding); - - StackPanel panel = CreateSignaturePanel(signatureInfo, contentMaxWidth); - - panel.Measure(new Size(contentMaxWidth, double.PositiveInfinity)); - - Size popupSize = new( - Math.Min(availablePopupWidth, panel.DesiredSize.Width + popupHorizontalPadding), - panel.DesiredSize.Height + popupVerticalPadding); - - _signaturePopupPresenter.Content = panel; - _signaturePopupPresenter.InvalidateMeasure(); - _signaturePopupBorder.InvalidateMeasure(); - PositionSignaturePopup(popupSize); - - if (!_signaturePopup.IsOpen) - _signaturePopup.IsOpen = true; - } - - private StackPanel CreateSignaturePanel(LuaSignatureInfo signatureInfo, double contentMaxWidth) - { - LuaThemeBrushSet brushSet = GetThemeBrushSet(); - var panel = new StackPanel { MaxWidth = contentMaxWidth }; - panel.Children.Add(BuildSignatureBlock(signatureInfo, brushSet)); - - if (!string.IsNullOrWhiteSpace(signatureInfo.Documentation)) - panel.Children.Add(CreateSignatureDocumentationBlock(signatureInfo.Documentation, brushSet)); - - if (signatureInfo.ActiveParameter < signatureInfo.Parameters.Count) - { - LuaParameterInfo activeParam = signatureInfo.Parameters[signatureInfo.ActiveParameter]; - - if (!string.IsNullOrWhiteSpace(activeParam.Documentation)) - panel.Children.Add(CreateSignatureDocumentationBlock(activeParam.Label + ": " + activeParam.Documentation, brushSet)); - } - - return panel; - } - - private static TextBlock CreateSignatureDocumentationBlock(string text, LuaThemeBrushSet brushSet) => new() - { - Text = text, - Foreground = brushSet.SignatureParamDocForeground, - FontFamily = SystemFonts.MessageFontFamily, - FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, SignaturePopupFontSize), - TextWrapping = TextWrapping.Wrap, - Margin = new Thickness(0.0, 4.0, 0.0, 0.0) - }; - - private void PositionSignaturePopup(Size popupSize) - { - AttachHostWindowHandlers(); - _signaturePopup.PlacementTarget = this; - TextArea.TextView.EnsureVisualLines(); - - Rect caretRectangle = TextArea.Caret.CalculateCaretRectangle(); - Vector scrollOffset = TextArea.TextView.ScrollOffset; - - Point caretViewportPoint = new( - caretRectangle.X - scrollOffset.X, - caretRectangle.Y - scrollOffset.Y); - - Point editorPoint = TextArea.TextView.TranslatePoint(caretViewportPoint, this); - double lineHeight = Math.Max(TextArea.TextView.DefaultLineHeight, caretRectangle.Height); - double lineSlack = Math.Max(0.0, lineHeight - caretRectangle.Height); - double horizontalOffset = Math.Max(0.0, editorPoint.X + 2.0); - double maxHorizontalOffset = Math.Max(0.0, ActualWidth - popupSize.Width - 8.0); - horizontalOffset = Math.Min(horizontalOffset, maxHorizontalOffset); - - double verticalOffset = editorPoint.Y - popupSize.Height - lineSlack - 8.0; - - if (verticalOffset < 0.0) - verticalOffset = Math.Min(Math.Max(0.0, ActualHeight - popupSize.Height), editorPoint.Y + lineHeight + 4.0); - - _signaturePopup.HorizontalOffset = horizontalOffset; - _signaturePopup.VerticalOffset = verticalOffset; - } - - private async Task RequestSignatureHelpAsync(int offset) - { - if (_signatureRequestInFlight) - { - _pendingSignatureHelpOffset = offset; - _signatureRefreshPending = true; - return; - } - - _signatureRequestInFlight = true; - - if (!IsIntellisenseAvailable()) - { - _signatureRequestInFlight = false; - DismissSignatureHelp(); - return; - } - - CancellationToken cancellationToken = CancellationToken.None; - int requestToken = ++_signatureRequestToken; - int requestDocumentVersion = _editorDocumentVersion; - int requestGeneration = _editorRequestGeneration; - - try - { - (int Line, int Column) = GetPositionFromOffset(offset); - - LuaSignatureInfo? signatureInfo = await IntellisenseProvider - .GetSignatureHelpAsync(FilePath, Text, Line, Column, cancellationToken) - .ConfigureAwait(true); - - if (!IsAsyncEditorResultCurrent(cancellationToken, requestToken, _signatureRequestToken, requestDocumentVersion, requestGeneration)) - return; - - if (signatureInfo is null) - { - DismissSignatureHelp(); - return; - } - - ShowSignatureToolTip(signatureInfo); - } - catch (OperationCanceledException) - { } - catch (Exception exception) - { - LogEditorFailure("Signature help", exception); - } - finally - { - _signatureRequestInFlight = false; - - if (_signatureRefreshPending && _pendingSignatureHelpOffset >= 0) - { - _signatureRefreshTimer.Stop(); - _signatureRefreshTimer.Start(); - } - } - } - - private void ScheduleSignatureHelpRefresh() - { - _pendingSignatureHelpOffset = CaretOffset; - _signatureRefreshPending = true; - _signatureRefreshTimer.Stop(); - _signatureRefreshTimer.Start(); - } - - private void CancelPendingSignatureHelpRefresh() - { - _signatureRefreshTimer.Stop(); - _signatureRefreshPending = false; - _pendingSignatureHelpOffset = -1; - } - - private void InvalidateSignatureHelpRequests() - { - _signatureRequestToken++; - _signatureRequestInFlight = false; - } - - private async void SignatureRefreshTimer_Tick(object? sender, EventArgs e) - { - _signatureRefreshTimer.Stop(); - - if (!_signatureRefreshPending || _pendingSignatureHelpOffset < 0) - return; - - if (_signatureRequestInFlight) - return; - - int offset = _pendingSignatureHelpOffset; - _signatureRefreshPending = false; - await RequestSignatureHelpAsync(offset).ConfigureAwait(true); - } - - private static TextBlock BuildSignatureBlock(LuaSignatureInfo signatureInfo, LuaThemeBrushSet brushSet) - { - var textBlock = new TextBlock - { - FontFamily = new FontFamily("Consolas"), - FontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, SignaturePopupFontSize), - TextWrapping = TextWrapping.Wrap, - Foreground = brushSet.SignatureForeground - }; - - string label = signatureInfo.Label; - - if (signatureInfo.Parameters.Count == 0 - || !TryGetActiveParameterRange(label, signatureInfo, out int activeStart, out int activeEnd)) - { - textBlock.Text = label; - return textBlock; - } - - if (activeStart > 0) - textBlock.Inlines.Add(new Run(label[..activeStart])); - - textBlock.Inlines.Add(new Run(label[activeStart..activeEnd]) - { - FontWeight = FontWeights.Bold, - Foreground = brushSet.SignatureActiveParamForeground - }); - - if (activeEnd < label.Length) - textBlock.Inlines.Add(new Run(label[activeEnd..])); - - return textBlock; - } - - private static bool TryGetActiveParameterRange(string label, LuaSignatureInfo signatureInfo, out int activeStart, out int activeEnd) - { - activeStart = 0; - activeEnd = 0; - - int activeIndex = Math.Min(signatureInfo.ActiveParameter, signatureInfo.Parameters.Count - 1); - - if (activeIndex < 0) - return false; - - string activeLabel = signatureInfo.Parameters[activeIndex].Label; - - if (string.IsNullOrEmpty(activeLabel)) - return false; - - int searchStart = label.IndexOf('('); - searchStart = searchStart < 0 ? 0 : searchStart + 1; - - int matchIndex = label.IndexOf(activeLabel, searchStart, StringComparison.Ordinal); - - if (matchIndex < 0) - return false; - - activeStart = matchIndex; - activeEnd = matchIndex + activeLabel.Length; - return true; - } -} diff --git a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs index 77db7e6744..c6f71a5391 100644 --- a/TombLib/TombLib.Scripting.Lua/LuaEditor.cs +++ b/TombLib/TombLib.Scripting.Lua/LuaEditor.cs @@ -15,6 +15,10 @@ namespace TombLib.Scripting.Lua; public sealed partial class LuaEditor : TextEditorBase { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + private readonly LuaCompletionController _completionController; + private readonly LuaDefinitionNavigationController _definitionNavigationController; + private readonly LuaHoverController _hoverController; + private readonly LuaSignatureHelpController _signatureHelpController; /// /// Gets the default file extension associated with Lua documents. @@ -44,7 +48,11 @@ public LuaEditor(Version engineVersion) : base(engineVersion) { CommentPrefix = "--"; TextArea.IndentationStrategy = new LuaAutoIndentationStrategy(Options); - InitializeSignaturePopup(); + _completionController = new LuaCompletionController(this); + _definitionNavigationController = new LuaDefinitionNavigationController(this); + _hoverController = new LuaHoverController(this); + _signatureHelpController = new LuaSignatureHelpController(this); + _signatureHelpController.InitializePopup(); BindLuaIntellisenseEvents(); } diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs index d54cf9c437..689f478f56 100644 --- a/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs @@ -141,7 +141,7 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in if (ContainsLineBreak(insertText)) { - (string normalizedText, int? normalizedCaretOffset) = LuaIndentationStrategy.NormalizeCompletionInsertion( + LuaCompletionNormalizationResult normalizedInsertion = LuaIndentationStrategy.NormalizeCompletionInsertion( insertText, insertCaretOffset, GetCurrentLineIndentation(document, replacementOffset), @@ -150,8 +150,8 @@ public void Complete(TextArea textArea, ISegment completionSegment, EventArgs in textArea.Options.IndentationSize, 4)); - insertText = normalizedText; - insertCaretOffset = normalizedCaretOffset; + insertText = normalizedInsertion.Text; + insertCaretOffset = normalizedInsertion.CaretOffset; } document.Replace(replacementOffset, replacementLength, insertText); diff --git a/TombLib/TombLib.Scripting.Lua/README.md b/TombLib/TombLib.Scripting.Lua/README.md new file mode 100644 index 0000000000..f404c735ca --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/README.md @@ -0,0 +1,28 @@ +# Lua Editor Ownership Notes + +This note is a phase 0 maintainer map for the current Lua editor layout. It is intentionally short and should be updated as cleanup work lands. + +## Current ownership + +- `LuaEditor.cs`: public control surface, composition root, theme application, syntax-highlighting setup, and provider hookup. +- `LuaEditor.Intellisense.cs`: event wiring, trigger routing, document/request generation invalidation, unload cleanup, and shared editor-side request helpers. +- `Editor/Completion/LuaCompletionController.cs`: editor-facing completion entry points, debounce scheduling, popup lifecycle, completion tooltip resolve flow, query-offset calculation, width measurement, and AvalonEdit popup integration details. +- `Editor/Hover/LuaHoverController.cs`: editor hover entry points, hover request cancellation, hover eligibility checks, tooltip rendering, and hover versus diagnostic tooltip selection. +- `Editor/Navigation/LuaDefinitionNavigationController.cs`: F12 and Ctrl+Click definition navigation flow and definition-request cancellation state. +- `Editor/SignatureHelp/LuaSignatureHelpController.cs`: editor-facing signature help entry points, signature popup UI, refresh timer, pending-request state, popup positioning, and request flow. +- `LuaEditor.Navigation.cs`: keyboard and mouse navigation event handling plus the public navigation entry point. +- `LuaEditor.SemanticHighlighting.cs`: semantic-token subscriptions, token application, and editor-side highlighting refresh. +- `Utils/`: editor-local rules and pure helpers such as line parsing, indentation, and hover/completion/definition interaction guards. +- `Services/ILuaIntellisenseProvider.cs`: editor-facing contract for the Lua language-service backend. + +## Extraction naming + +- Use `Controller` for new stateful editor-owned feature workflows. +- Reserve `Coordinator` for provider-side workflows that own document queues, background refresh, or restart-sensitive state. +- Keep `Service` for stable external integration surfaces or shared utilities that already represent a service boundary. + +## Cleanup guardrails + +- Keep `LuaEditor` as the public control and composition root. +- Keep partials only when the state still clearly belongs to `LuaEditor` itself. +- Prefer moving real feature state and workflow into a named owner instead of spreading it across another partial. \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaCompletionNormalizationResult.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaCompletionNormalizationResult.cs new file mode 100644 index 0000000000..a2893e8464 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaCompletionNormalizationResult.cs @@ -0,0 +1,6 @@ +namespace TombLib.Scripting.Lua.Utils; + +/// +/// Represents the normalized completion text and its optional caret placement. +/// +internal readonly record struct LuaCompletionNormalizationResult(string Text, int? CaretOffset); \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaEnterInsertionResult.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaEnterInsertionResult.cs new file mode 100644 index 0000000000..368b67f7cd --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaEnterInsertionResult.cs @@ -0,0 +1,6 @@ +namespace TombLib.Scripting.Lua.Utils; + +/// +/// Represents the text inserted for Enter along with caret and whitespace removal metadata. +/// +internal readonly record struct LuaEnterInsertionResult(string Text, int CaretOffset, int RemoveFollowingWhitespaceLength); \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs b/TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs index 3c0d5649ee..1ca913c119 100644 --- a/TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs +++ b/TombLib/TombLib.Scripting.Lua/Utils/LuaIndentationStrategy.cs @@ -68,7 +68,7 @@ public static string GetDesiredIndentation( /// /// Builds the text that should be inserted when Enter is pressed inside Lua code. /// - public static (string Text, int CaretOffset, int RemoveFollowingWhitespaceLength) BuildEnterInsertion( + public static LuaEnterInsertionResult BuildEnterInsertion( string lineTextBeforeCaret, string lineTextAfterCaret, string currentLineIndentation, @@ -94,24 +94,27 @@ public static (string Text, int CaretOffset, int RemoveFollowingWhitespaceLength if (!shouldSplitBeforeDedent) { string text = newLineText + nextLineIndentation; - return (text, text.Length, 0); + return new LuaEnterInsertionResult(text, text.Length, 0); } string splitText = newLineText + nextLineIndentation + newLineText + currentLineIndentation; - return (splitText, newLineText.Length + nextLineIndentation.Length, GetLeadingWhitespaceLength(lineTextAfterCaret)); + return new LuaEnterInsertionResult( + splitText, + newLineText.Length + nextLineIndentation.Length, + GetLeadingWhitespaceLength(lineTextAfterCaret)); } /// /// Normalizes multiline completion insertion relative to the current line indentation. /// - public static (string Text, int? CaretOffset) NormalizeCompletionInsertion( + public static LuaCompletionNormalizationResult NormalizeCompletionInsertion( string text, int? caretOffset, string currentLineIndentation, string indentationUnit) { if (string.IsNullOrEmpty(text) || !ContainsLineBreak(text)) - return (text, caretOffset); + return new LuaCompletionNormalizationResult(text, caretOffset); List lines = SplitLines(text); var builder = new StringBuilder(text.Length + Math.Max(0, lines.Count - 1) * currentLineIndentation.Length); @@ -151,7 +154,7 @@ public static (string Text, int? CaretOffset) NormalizeCompletionInsertion( if (caretOffset == text.Length) normalizedCaretOffset = builder.Length; - return (builder.ToString(), normalizedCaretOffset ?? caretOffset); + return new LuaCompletionNormalizationResult(builder.ToString(), normalizedCaretOffset ?? caretOffset); } private static string BuildIndentation(string currentLineIndentation, string indentationUnit, int indentLevel) diff --git a/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs b/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs new file mode 100644 index 0000000000..6444c98529 --- /dev/null +++ b/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs @@ -0,0 +1,473 @@ +using ICSharpCode.AvalonEdit.CodeCompletion; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Threading; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaEditorCompletionWindowTests +{ + [TestMethod] + public void RequestCompletionAsync_OpensCompletionWindowWithCurrentItemsAndOffsets() + { + RunInSta(() => + { + var provider = new FakeLuaCompletionProvider(); + provider.EnqueueCompletionResponse( + [ + new LuaCompletionItem("spawn_room", detail: "local variable") + ]); + + var editor = CreateEditor(provider, "spa"); + Window hostWindow = ShowInHostWindow(editor); + + try + { + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + + Assert.AreEqual(1, completionWindow.CompletionList.CompletionData.Count); + Assert.AreEqual(0, completionWindow.StartOffset); + Assert.AreEqual(3, completionWindow.EndOffset); + Assert.IsNotNull(completionWindow.CompletionList.ListBox.SelectedItem); + Assert.AreEqual(1, provider.CompletionRequests.Count); + Assert.AreEqual(0, provider.CompletionRequests[0].Line); + Assert.AreEqual(3, provider.CompletionRequests[0].Column); + } + finally + { + CloseCompletionWindow(editor); + hostWindow.Close(); + } + }); + } + + [TestMethod] + public void RequestCompletionAsync_RefreshClosesPreviousTooltipAndRecreatesWindow() + { + RunInSta(() => + { + var provider = new FakeLuaCompletionProvider(); + provider.EnqueueCompletionResponse( + [ + new LuaCompletionItem("spawn_room", detail: "local variable") + ]); + provider.EnqueueCompletionResponse( + [ + new LuaCompletionItem("spell_room", detail: "global variable") + ]); + + var editor = CreateEditor(provider, "spa"); + Window hostWindow = ShowInHostWindow(editor); + + try + { + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + CompletionWindow firstWindow = GetPrivateField(editor, "_completionWindow"); + ToolTip firstToolTip = GetCompletionToolTip(firstWindow); + firstToolTip.Content = new TextBlock { Text = "old tooltip" }; + firstToolTip.IsOpen = true; + + editor.Text = "spe"; + editor.CaretOffset = 3; + + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + CompletionWindow refreshedWindow = GetPrivateField(editor, "_completionWindow"); + var refreshedItem = (LuaCompletionData)refreshedWindow.CompletionList.CompletionData[0]; + + Assert.AreNotSame(firstWindow, refreshedWindow); + Assert.IsFalse(firstToolTip.IsOpen); + Assert.AreEqual("spell_room", refreshedItem.DisplayText); + } + finally + { + CloseCompletionWindow(editor); + hostWindow.Close(); + } + }); + } + + [TestMethod] + public void RequestCompletionAsync_EmptyResults_CloseExistingWindow() + { + RunInSta(() => + { + var provider = new FakeLuaCompletionProvider(); + provider.EnqueueCompletionResponse( + [ + new LuaCompletionItem("spawn_room", detail: "local variable") + ]); + provider.EnqueueCompletionResponse([]); + + var editor = CreateEditor(provider, "spa"); + Window hostWindow = ShowInHostWindow(editor); + + try + { + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + FieldInfo completionWindowField = FindInstanceField(editor.GetType(), "_completionWindow") + ?? throw new InvalidOperationException("Private field '_completionWindow' was not found."); + + Assert.IsNull(completionWindowField.GetValue(editor)); + } + finally + { + CloseCompletionWindow(editor); + hostWindow.Close(); + } + }); + } + + [TestMethod] + public void RequestCompletionAsync_DismissesSignatureHelpBeforeOpeningWindow() + { + RunInSta(() => + { + var provider = new FakeLuaCompletionProvider(); + provider.EnqueueCompletionResponse( + [ + new LuaCompletionItem("spawn_room", detail: "local variable") + ]); + + var editor = CreateEditor(provider, "spa"); + Window hostWindow = ShowInHostWindow(editor); + + try + { + Popup signaturePopup = GetSignatureHelpField(editor, "_signaturePopup"); + ContentPresenter signaturePresenter = GetSignatureHelpField(editor, "_signaturePopupPresenter"); + + signaturePresenter.Content = new TextBlock { Text = "signature" }; + signaturePopup.IsOpen = true; + SetSignatureHelpField(editor, "_signatureRequestToken", 4); + + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + Assert.IsFalse(signaturePopup.IsOpen); + Assert.IsNull(signaturePresenter.Content); + Assert.AreEqual(5, GetSignatureHelpField(editor, "_signatureRequestToken")); + Assert.IsNotNull(GetPrivateField(editor, "_completionWindow")); + } + finally + { + CloseCompletionWindow(editor); + hostWindow.Close(); + } + }); + } + + [TestMethod] + public void UpdateCompletionTooltipAsync_ResolvesSelectedCompletionItem() + { + RunInSta(() => + { + int resolveCallCount = 0; + var provider = new FakeLuaCompletionProvider(); + provider.EnqueueCompletionResponse( + [ + new LuaCompletionItem( + "spawn_room", + resolveAsync: _ => + { + resolveCallCount++; + return Task.FromResult(new LuaCompletionItem("spawn_room", detail: "resolved detail")); + }) + ]); + + var editor = CreateEditor(provider, "spa"); + Window hostWindow = ShowInHostWindow(editor); + + try + { + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + ToolTip toolTip = GetCompletionToolTip(completionWindow); + completionWindow.CompletionList.ListBox.SelectedItem = completionWindow.CompletionList.CompletionData[0]; + + int updateToken = GetPrivateField(GetCompletionController(editor), "_completionToolTipUpdateToken"); + InvokeControllerTask(editor, "_completionController", "UpdateTooltipAsync", [typeof(ToolTip), typeof(int)], toolTip, updateToken).GetAwaiter().GetResult(); + + Assert.AreEqual(1, resolveCallCount); + Assert.IsTrue(toolTip.IsOpen); + Assert.IsInstanceOfType(toolTip.Content, typeof(Border)); + + var contentBorder = (Border)toolTip.Content!; + var contentPanel = (StackPanel)(contentBorder.Child + ?? throw new AssertFailedException("Expected tooltip content panel.")); + var detailBlock = (TextBlock)contentPanel.Children[0]; + + Assert.AreEqual("resolved detail", detailBlock.Text); + } + finally + { + CloseCompletionWindow(editor); + hostWindow.Close(); + } + }); + } + + [TestMethod] + public void UpdateCompletionTooltipAsync_HidesTooltipWhenSelectionIsCleared() + { + RunInSta(() => + { + var provider = new FakeLuaCompletionProvider(); + provider.EnqueueCompletionResponse( + [ + new LuaCompletionItem("spawn_room", detail: "local variable") + ]); + + var editor = CreateEditor(provider, "spa"); + Window hostWindow = ShowInHostWindow(editor); + + try + { + InvokePrivateTask(editor, "RequestCompletionAsync", [typeof(int), typeof(char?)], 3, null).GetAwaiter().GetResult(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.ContextIdle); + + CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + ToolTip toolTip = GetCompletionToolTip(completionWindow); + toolTip.Content = new TextBlock { Text = "stale tooltip" }; + toolTip.IsOpen = true; + completionWindow.CompletionList.ListBox.SelectedItem = null; + + int updateToken = GetPrivateField(GetCompletionController(editor), "_completionToolTipUpdateToken"); + InvokeControllerTask(editor, "_completionController", "UpdateTooltipAsync", [typeof(ToolTip), typeof(int)], toolTip, updateToken).GetAwaiter().GetResult(); + + Assert.IsFalse(toolTip.IsOpen); + } + finally + { + CloseCompletionWindow(editor); + hostWindow.Close(); + } + }); + } + + private static LuaEditor CreateEditor(ILuaIntellisenseProvider provider, string text) + => new(new Version(1, 0)) + { + FilePath = @"C:\Workspace\Scripts\test.lua", + Text = text, + IntellisenseProvider = provider + }; + + private static Task InvokePrivateTask(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) + => (Task)(InvokePrivateInstanceMethod(instance, methodName, parameterTypes, arguments) + ?? throw new InvalidOperationException($"Private instance method '{methodName}' returned null.")); + + private static Task InvokeControllerTask(LuaEditor editor, string controllerFieldName, string methodName, Type[] parameterTypes, params object?[] arguments) + => (Task)(InvokePrivateInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName, parameterTypes, arguments) + ?? throw new InvalidOperationException($"Controller method '{methodName}' returned null.")); + + private static object? InvokePrivateInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = instance.GetType().GetMethod( + methodName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Private instance method '{methodName}' was not found."); + + return method.Invoke(instance, arguments); + } + + private static void CloseCompletionWindow(LuaEditor editor) + => InvokePrivateInstanceMethod(editor, "CloseCompletionWindow", Type.EmptyTypes); + + private static object GetCompletionController(LuaEditor editor) + => GetPrivateField(editor, "_completionController"); + + private static T GetSignatureHelpField(LuaEditor editor, string fieldName) + => GetPrivateField(GetPrivateField(editor, "_signatureHelpController"), fieldName); + + private static void SetSignatureHelpField(LuaEditor editor, string fieldName, object value) + => SetPrivateField(GetPrivateField(editor, "_signatureHelpController"), fieldName, value); + + private static T GetPrivateField(object instance, string fieldName) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return (T)(field.GetValue(instance) + ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); + } + + private static void SetPrivateField(object instance, string fieldName, object value) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + field.SetValue(instance, value); + } + + private static FieldInfo? FindInstanceField(Type type, string fieldName) + { + for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) + { + FieldInfo? field = currentType.GetField( + fieldName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); + + if (field is not null) + return field; + } + + return null; + } + + private static ToolTip GetCompletionToolTip(CompletionWindow completionWindow) + { + FieldInfo field = typeof(CompletionWindow).GetField("toolTip", BindingFlags.Instance | BindingFlags.NonPublic) + ?? throw new InvalidOperationException("CompletionWindow private field 'toolTip' was not found."); + + return (ToolTip)(field.GetValue(completionWindow) + ?? throw new InvalidOperationException("CompletionWindow private field 'toolTip' returned null.")); + } + + private static Window ShowInHostWindow(FrameworkElement content) + { + var window = new Window + { + Content = content, + Width = 800.0, + Height = 600.0, + ShowActivated = false, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None + }; + + window.Show(); + PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); + return window; + } + + private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) + => dispatcher.Invoke(priority, new Action(() => { })); + + private static void RunInSta(Action action) + { + Exception? capturedException = null; + using var completed = new ManualResetEventSlim(false); + + var thread = new Thread(() => + { + try + { + action(); + } + catch (Exception exception) + { + capturedException = exception; + } + finally + { + completed.Set(); + } + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + completed.Wait(); + thread.Join(); + + if (capturedException is not null) + ExceptionDispatchInfo.Capture(capturedException).Throw(); + } + + private readonly record struct CompletionRequest(string FilePath, string Content, int Line, int Column, char? TriggerCharacter); + + private sealed class FakeLuaCompletionProvider : ILuaIntellisenseProvider + { + private readonly Queue> _completionResponses = []; + + public bool IsAvailable { get; set; } = true; + + public List CompletionRequests { get; } = []; + + public event Action>? DiagnosticsUpdated + { + add { } + remove { } + } + + public event Action>? SemanticTokensUpdated + { + add { } + remove { } + } + + public void EnqueueCompletionResponse(IReadOnlyList items) + => _completionResponses.Enqueue(items); + + public IReadOnlyList GetDiagnostics(string filePath) + => []; + + public IReadOnlyList GetSemanticTokens(string filePath) + => []; + + public void OpenDocument(string filePath, string content) + { + } + + public void UpdateDocument(string filePath, string content) + { + } + + public void CloseDocument(string filePath) + { + } + + public void RenameDocument(string oldFilePath, string newFilePath, string content) + { + } + + public Task> GetCompletionItemsAsync(string filePath, string content, + int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) + { + CompletionRequests.Add(new CompletionRequest(filePath, content, line, column, triggerCharacter)); + IReadOnlyList response = _completionResponses.Count > 0 ? _completionResponses.Dequeue() : []; + return Task.FromResult(response); + } + + public Task GetHoverAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + => Task.FromResult(null); + + public Task GetDefinitionAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + => Task.FromResult(null); + + public Task GetSignatureHelpAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + => Task.FromResult(null); + + public void Dispose() + { + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs index 59a7887c4e..06fda73c32 100644 --- a/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs +++ b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs @@ -1,8 +1,17 @@ using System; +using System.Collections.Generic; using System.Reflection; using System.Runtime.ExceptionServices; using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Threading; using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Lua.Services; +using TombLib.Scripting.Objects; namespace TombLib.Test; @@ -52,6 +61,133 @@ public void ShouldDismissSignatureHelpOnAutoClosingSkip_ReturnsTrueOnlyForMatchi Assert.IsFalse(shouldDismissOtherElement); } + [TestMethod] + public void ScheduleSignatureHelpRefresh_StoresCaretOffsetAndStartsTimer() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)) + { + Text = "spawn(room)" + }; + + editor.CaretOffset = 6; + InvokeControllerInstanceMethod(editor, "_signatureHelpController", "ScheduleRefresh"); + + Assert.IsTrue(GetSignatureHelpField(editor, "_signatureRefreshPending")); + Assert.AreEqual(6, GetSignatureHelpField(editor, "_pendingSignatureHelpOffset")); + Assert.IsTrue(GetSignatureHelpField(editor, "_signatureRefreshTimer").IsEnabled); + }); + } + + [TestMethod] + public void CancelPendingSignatureHelpRefresh_ClearsPendingStateAndStopsTimer() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)) + { + Text = "spawn(room)" + }; + + editor.CaretOffset = 6; + InvokeControllerInstanceMethod(editor, "_signatureHelpController", "ScheduleRefresh"); + InvokeControllerInstanceMethod(editor, "_signatureHelpController", "CancelPendingRefresh"); + + Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRefreshPending")); + Assert.AreEqual(-1, GetSignatureHelpField(editor, "_pendingSignatureHelpOffset")); + Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRefreshTimer").IsEnabled); + }); + } + + [TestMethod] + public void DismissSignatureHelp_ClearsPendingStateAndInvalidatesOutstandingRequests() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + ContentPresenter presenter = GetSignatureHelpField(editor, "_signaturePopupPresenter"); + Popup popup = GetSignatureHelpField(editor, "_signaturePopup"); + + presenter.Content = new TextBlock { Text = "signature" }; + SetSignatureHelpField(editor, "_signatureRequestToken", 5); + SetSignatureHelpField(editor, "_signatureRequestInFlight", true); + SetSignatureHelpField(editor, "_signatureRefreshPending", true); + SetSignatureHelpField(editor, "_pendingSignatureHelpOffset", 9); + + InvokePrivateInstanceMethod(editor, "DismissSignatureHelp"); + + Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRequestInFlight")); + Assert.AreEqual(6, GetSignatureHelpField(editor, "_signatureRequestToken")); + Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRefreshPending")); + Assert.AreEqual(-1, GetSignatureHelpField(editor, "_pendingSignatureHelpOffset")); + Assert.IsNull(presenter.Content); + Assert.IsFalse(popup.IsOpen); + }); + } + + [TestMethod] + public void TryGetCompletionTrigger_ReturnsExplicitAndImplicitTriggers() + { + Assert.IsTrue(InvokeTryGetCompletionTrigger(".", out char? dotTrigger)); + Assert.AreEqual('.', dotTrigger); + + Assert.IsTrue(InvokeTryGetCompletionTrigger(":", out char? colonTrigger)); + Assert.AreEqual(':', colonTrigger); + + Assert.IsTrue(InvokeTryGetCompletionTrigger("a", out char? identifierTrigger)); + Assert.IsNull(identifierTrigger); + } + + [TestMethod] + public void TryGetCompletionTrigger_RejectsEmptyMultiCharacterAndNonIdentifierInput() + { + Assert.IsFalse(InvokeTryGetCompletionTrigger(null, out _)); + Assert.IsFalse(InvokeTryGetCompletionTrigger(string.Empty, out _)); + Assert.IsFalse(InvokeTryGetCompletionTrigger("ab", out _)); + Assert.IsFalse(InvokeTryGetCompletionTrigger(" ", out _)); + } + + [TestMethod] + public void ShouldKeepCompletionWindowOpen_ReturnsTrueOnlyForIdentifierCharacters() + { + Assert.IsTrue(InvokePrivateStaticBooleanMethod( + "ShouldKeepCompletionWindowOpen", + [typeof(string)], + "a")); + + Assert.IsTrue(InvokePrivateStaticBooleanMethod( + "ShouldKeepCompletionWindowOpen", + [typeof(string)], + "_")); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "ShouldKeepCompletionWindowOpen", + [typeof(string)], + new object?[] { null })); + + Assert.IsFalse(InvokePrivateStaticBooleanMethod( + "ShouldKeepCompletionWindowOpen", + [typeof(string)], + ".")); + } + + [TestMethod] + public void ScheduleCompletionRequest_StartsTimerAndCancelPendingCompletionRequest_StopsIt() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + object completionController = GetCompletionController(editor); + + InvokeControllerInstanceMethod(editor, "_completionController", "ScheduleRequest"); + Assert.IsTrue(GetPrivateField(completionController, "_completionRequestTimer").IsEnabled); + + InvokeControllerInstanceMethod(editor, "_completionController", "CancelPendingRequest"); + Assert.IsFalse(GetPrivateField(completionController, "_completionRequestTimer").IsEnabled); + }); + } + [TestMethod] public void IsAsyncEditorResultCurrent_ReturnsTrueForCurrentLoadedAvailableRequest() { @@ -229,13 +365,428 @@ public void CloseCompletionWindow_InvalidatesPendingRequests_ButRefreshCloseDoes RunInSta(() => { var editor = new LuaEditor(new Version(1, 0)); + object completionController = GetCompletionController(editor); - SetPrivateField(editor, "_completionRequestToken", 5); + SetPrivateField(completionController, "_completionRequestToken", 5); InvokePrivateInstanceMethod(editor, "CloseCompletionWindow"); - Assert.AreEqual(6, GetPrivateField(editor, "_completionRequestToken")); + Assert.AreEqual(6, GetPrivateField(completionController, "_completionRequestToken")); + + InvokeControllerInstanceMethod(editor, "_completionController", "CloseWindowForRefresh"); + Assert.AreEqual(6, GetPrivateField(completionController, "_completionRequestToken")); + }); + } + + [TestMethod] + public void TryGetHoverRequestOffset_ReturnsIdentifierOffsetWhenEligible() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)) + { + Text = "spawn(room)" + }; + + bool result = InvokeTryGetHoverRequestOffset(editor, 2, out int hoverOffset); + + Assert.IsTrue(result); + Assert.AreEqual(2, hoverOffset); + }); + } + + [TestMethod] + public void TryGetHoverRequestOffset_BlocksRequestsWhenCompletionWindowIsOpen() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)) + { + Text = "spawn(room)" + }; + + editor.InitializeCompletionWindow(); + + bool result = InvokeTryGetHoverRequestOffset(editor, 2, out _); + + Assert.IsFalse(result); + }); + } + + [TestMethod] + public void ShowBestHoverToolTip_ShowsCombinedTooltipWhenHoverAndDiagnosticAreAvailable() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + + InvokeControllerInstanceMethod( + editor, + "_hoverController", + "ShowBestToolTip", + [typeof(LuaHoverInfo), typeof(bool), typeof(string), typeof(TextEditorDiagnosticSeverity)], + new LuaHoverInfo("Hover docs.", false), + true, + "Warning message.", + TextEditorDiagnosticSeverity.Warning); + + Popup popup = GetPrivateField(editor, "_specialToolTip"); + ContentPresenter presenter = GetPrivateField(editor, "_specialToolTipPresenter"); + + Assert.IsTrue(popup.IsOpen); + Assert.IsInstanceOfType(presenter.Content, typeof(StackPanel)); + + var panel = (StackPanel)presenter.Content!; + Assert.AreEqual(2, panel.Children.Count); + }); + } + + [TestMethod] + public void ShowBestHoverToolTip_ShowsHoverTooltipWhenOnlyHoverIsAvailable() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + + InvokeControllerInstanceMethod( + editor, + "_hoverController", + "ShowBestToolTip", + [typeof(LuaHoverInfo), typeof(bool), typeof(string), typeof(TextEditorDiagnosticSeverity)], + new LuaHoverInfo("Hover docs.", false), + false, + string.Empty, + TextEditorDiagnosticSeverity.Warning); + + Popup popup = GetPrivateField(editor, "_specialToolTip"); + ContentPresenter presenter = GetPrivateField(editor, "_specialToolTipPresenter"); + + Assert.IsTrue(popup.IsOpen); + Assert.IsNotNull(presenter.Content); + Assert.IsNotInstanceOfType(presenter.Content, typeof(StackPanel)); + }); + } + + [TestMethod] + public void ShowBestHoverToolTip_ShowsDiagnosticTooltipWhenOnlyDiagnosticIsAvailable() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + + InvokeControllerInstanceMethod( + editor, + "_hoverController", + "ShowBestToolTip", + [typeof(LuaHoverInfo), typeof(bool), typeof(string), typeof(TextEditorDiagnosticSeverity)], + null, + true, + "Warning message.", + TextEditorDiagnosticSeverity.Warning); + + Popup popup = GetPrivateField(editor, "_specialToolTip"); + ContentPresenter presenter = GetPrivateField(editor, "_specialToolTipPresenter"); + + Assert.IsTrue(popup.IsOpen); + Assert.IsNotNull(presenter.Content); + Assert.IsNotInstanceOfType(presenter.Content, typeof(StackPanel)); + }); + } + + [TestMethod] + public void ShowBestHoverToolTip_SuppressesTooltipWhenCompletionWindowIsOpen() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + editor.InitializeCompletionWindow(); + + InvokeControllerInstanceMethod( + editor, + "_hoverController", + "ShowBestToolTip", + [typeof(LuaHoverInfo), typeof(bool), typeof(string), typeof(TextEditorDiagnosticSeverity)], + new LuaHoverInfo("Hover docs.", false), + true, + "Warning message.", + TextEditorDiagnosticSeverity.Warning); + + Popup popup = GetPrivateField(editor, "_specialToolTip"); + ContentPresenter presenter = GetPrivateField(editor, "_specialToolTipPresenter"); + + Assert.IsFalse(popup.IsOpen); + Assert.IsNull(presenter.Content); + }); + } + + [TestMethod] + public void DismissTransientToolTips_CancelsHoverAndClearsTransientUi() + { + RunInSta(() => + { + var editor = new LuaEditor(new Version(1, 0)); + var hoverCancellationTokenSource = new CancellationTokenSource(); + ContentPresenter signaturePresenter = GetSignatureHelpField(editor, "_signaturePopupPresenter"); + + SetHoverField(editor, "_hoverCancellationTokenSource", hoverCancellationTokenSource); + SetHoverField(editor, "_hoverRequestToken", 4); + SetSignatureHelpField(editor, "_signatureRequestToken", 2); + SetSignatureHelpField(editor, "_signatureRequestInFlight", true); + SetSignatureHelpField(editor, "_signatureRefreshPending", true); + SetSignatureHelpField(editor, "_pendingSignatureHelpOffset", 7); + signaturePresenter.Content = new TextBlock { Text = "signature" }; + + editor.InitializeCompletionWindow(); + editor.ShowToolTip("Hover docs."); + + InvokePrivateInstanceMethod(editor, "DismissTransientToolTips"); + + Assert.IsTrue(hoverCancellationTokenSource.IsCancellationRequested); + Assert.IsNull(GetHoverFieldValue(editor, "_hoverCancellationTokenSource")); + Assert.AreEqual(5, GetHoverField(editor, "_hoverRequestToken")); + Assert.IsNotNull(GetPrivateFieldValue(editor, "_completionWindow")); + Assert.AreEqual(3, GetSignatureHelpField(editor, "_signatureRequestToken")); + Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRequestInFlight")); + Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRefreshPending")); + Assert.AreEqual(-1, GetSignatureHelpField(editor, "_pendingSignatureHelpOffset")); + Assert.IsNull(signaturePresenter.Content); + Assert.IsFalse(GetPrivateField(editor, "_specialToolTip").IsOpen); + }); + } + + [TestMethod] + public void NavigateToDefinitionAtCaretAsync_RaisesDefinitionNavigationRequestedForResolvedLocation() + { + RunInSta(() => + { + var provider = new FakeLuaIntellisenseProvider + { + DefinitionResponse = new LuaDefinitionLocation(@"C:\Workspace\Definitions\spawn.lua", 4, 2) + }; + + var editor = new LuaEditor(new Version(1, 0)) + { + FilePath = @"C:\Workspace\Scripts\test.lua", + Text = "spawn()", + IntellisenseProvider = provider + }; + + editor.CaretOffset = 2; + LuaDefinitionLocation? navigatedLocation = null; + + editor.DefinitionNavigationRequested += location => navigatedLocation = location; + + Window window = ShowInHostWindow(editor); + + try + { + editor.NavigateToDefinitionAtCaretAsync().GetAwaiter().GetResult(); + } + finally + { + window.Close(); + } + + Assert.IsNotNull(navigatedLocation); + Assert.AreEqual(provider.DefinitionResponse!.FilePath, navigatedLocation.FilePath); + Assert.AreEqual(provider.DefinitionResponse.LineNumber, navigatedLocation.LineNumber); + Assert.AreEqual(provider.DefinitionResponse.ColumnNumber, navigatedLocation.ColumnNumber); + Assert.AreEqual(1, provider.DefinitionRequests.Count); + Assert.AreEqual(0, provider.DefinitionRequests[0].Line); + Assert.AreEqual(0, provider.DefinitionRequests[0].Column); + }); + } + + [TestMethod] + public void NavigateToDefinitionAtCaretAsync_DoesNotRaiseEventWhenProviderReturnsNoDefinition() + { + RunInSta(() => + { + var provider = new FakeLuaIntellisenseProvider(); + + var editor = new LuaEditor(new Version(1, 0)) + { + FilePath = @"C:\Workspace\Scripts\test.lua", + Text = "spawn()", + IntellisenseProvider = provider + }; + + editor.CaretOffset = 2; + int navigationRequestCount = 0; + + editor.DefinitionNavigationRequested += _ => navigationRequestCount++; + + Window window = ShowInHostWindow(editor); + + try + { + editor.NavigateToDefinitionAtCaretAsync().GetAwaiter().GetResult(); + } + finally + { + window.Close(); + } + + Assert.AreEqual(0, navigationRequestCount); + Assert.AreEqual(1, provider.DefinitionRequests.Count); + }); + } + + [TestMethod] + public void RequestSignatureHelpAsync_DismissesExistingPopupWhenProviderReturnsNoSignature() + { + RunInSta(() => + { + var provider = new FakeLuaIntellisenseProvider(); + + var editor = new LuaEditor(new Version(1, 0)) + { + FilePath = @"C:\Workspace\Scripts\test.lua", + Text = "spawn(", + IntellisenseProvider = provider + }; + + Window window = ShowInHostWindow(editor); + + try + { + Popup popup = GetSignatureHelpField(editor, "_signaturePopup"); + ContentPresenter presenter = GetSignatureHelpField(editor, "_signaturePopupPresenter"); + + presenter.Content = new TextBlock { Text = "signature" }; + popup.IsOpen = true; + + Task requestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) + ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); - InvokePrivateInstanceMethod(editor, "CloseCompletionWindowForRefresh"); - Assert.AreEqual(6, GetPrivateField(editor, "_completionRequestToken")); + requestTask.GetAwaiter().GetResult(); + + Assert.IsFalse(popup.IsOpen); + Assert.IsNull(presenter.Content); + Assert.AreEqual(1, provider.SignatureRequests.Count); + } + finally + { + window.Close(); + } + }); + } + + [TestMethod] + public void RequestSignatureHelpAsync_WhenRequestIsInFlight_DefersRefreshToLatestOffset() + { + RunInSta(() => + { + var firstResponse = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + LuaSignatureInfo secondSignature = new( + "spawn(room, objectName)", + "Spawns an object.", + [new LuaParameterInfo("room", "Room id."), new LuaParameterInfo("objectName", "Object name.")], + 1); + int servedResponses = 0; + + var provider = new FakeLuaIntellisenseProvider + { + SignatureHelpHandler = (_, _) => + { + servedResponses++; + + return servedResponses == 1 + ? firstResponse.Task + : Task.FromResult(secondSignature); + } + }; + + var editor = new LuaEditor(new Version(1, 0)) + { + FilePath = @"C:\Workspace\Scripts\test.lua", + Text = "spawn(room)", + IntellisenseProvider = provider + }; + + Window window = ShowInHostWindow(editor); + + try + { + Task firstRequestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) + ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); + + Task deferredRequestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 11) + ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); + + deferredRequestTask.GetAwaiter().GetResult(); + + Assert.IsTrue(GetSignatureHelpField(editor, "_signatureRequestInFlight")); + Assert.IsTrue(GetSignatureHelpField(editor, "_signatureRefreshPending")); + Assert.AreEqual(11, GetSignatureHelpField(editor, "_pendingSignatureHelpOffset")); + Assert.AreEqual(1, provider.SignatureRequests.Count); + + firstResponse.SetResult(new LuaSignatureInfo( + "spawn(room)", + "Spawns an object.", + [new LuaParameterInfo("room", "Room id.")], + 0)); + + firstRequestTask.GetAwaiter().GetResult(); + Assert.IsTrue(GetSignatureHelpField(editor, "_signatureRefreshTimer").IsEnabled); + + InvokeControllerInstanceMethod(editor, "_signatureHelpController", "HandleRefreshTimerTick", [typeof(object), typeof(EventArgs)], null, EventArgs.Empty); + window.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => { })); + + Assert.AreEqual(2, provider.SignatureRequests.Count); + Assert.AreEqual(11, provider.SignatureRequests[1].Column); + Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRefreshPending")); + Assert.AreEqual(11, GetSignatureHelpField(editor, "_pendingSignatureHelpOffset")); + Assert.IsTrue(GetSignatureHelpField(editor, "_signaturePopup").IsOpen); + } + finally + { + window.Close(); + } + }); + } + + [TestMethod] + public void RequestSignatureHelpAsync_ShowsSignaturePopupForResolvedSignature() + { + RunInSta(() => + { + var provider = new FakeLuaIntellisenseProvider + { + SignatureResponse = new LuaSignatureInfo( + "spawn(room)", + "Spawns an object.", + [new LuaParameterInfo("room", "Room id.")], + 0) + }; + + var editor = new LuaEditor(new Version(1, 0)) + { + FilePath = @"C:\Workspace\Scripts\test.lua", + Text = "spawn(", + IntellisenseProvider = provider + }; + + Window window = ShowInHostWindow(editor); + + try + { + Task requestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) + ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); + + requestTask.GetAwaiter().GetResult(); + } + finally + { + window.Close(); + } + + Popup popup = GetSignatureHelpField(editor, "_signaturePopup"); + ContentPresenter presenter = GetSignatureHelpField(editor, "_signaturePopupPresenter"); + + Assert.IsTrue(popup.IsOpen); + Assert.IsNotNull(presenter.Content); + Assert.AreEqual(1, provider.SignatureRequests.Count); + Assert.AreEqual(0, provider.SignatureRequests[0].Line); + Assert.AreEqual(6, provider.SignatureRequests[0].Column); }); } @@ -252,17 +803,96 @@ private static bool InvokePrivateStaticBooleanMethod(string methodName, Type[] p ?? throw new InvalidOperationException($"Private static method '{methodName}' returned null.")); } + private static bool InvokeTryGetCompletionTrigger(string? inputText, out char? triggerCharacter) + { + MethodInfo method = typeof(LuaEditor).GetMethod( + "TryGetCompletionTrigger", + BindingFlags.Static | BindingFlags.NonPublic, + binder: null, + [typeof(string), typeof(char?).MakeByRefType()], + modifiers: null) + ?? throw new InvalidOperationException("Private static method 'TryGetCompletionTrigger' was not found."); + + object?[] arguments = [inputText, null]; + bool result = (bool)(method.Invoke(null, arguments) + ?? throw new InvalidOperationException("Private static method 'TryGetCompletionTrigger' returned null.")); + + triggerCharacter = arguments[1] as char?; + return result; + } + + private static bool InvokeTryGetHoverRequestOffset(LuaEditor editor, int hoveredOffset, out int hoverOffset) + { + MethodInfo method = GetHoverController(editor).GetType().GetMethod( + "TryGetRequestOffset", + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + [typeof(int), typeof(int).MakeByRefType()], + modifiers: null) + ?? throw new InvalidOperationException("Hover controller method 'TryGetRequestOffset' was not found."); + + object?[] arguments = [hoveredOffset, 0]; + bool result = (bool)(method.Invoke(GetHoverController(editor), arguments) + ?? throw new InvalidOperationException("Hover controller method 'TryGetRequestOffset' returned null.")); + + hoverOffset = (int)arguments[1]!; + return result; + } + private static void InvokePrivateInstanceMethod(object instance, string methodName) { - MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? throw new InvalidOperationException($"Private instance method '{methodName}' was not found."); method.Invoke(instance, null); } + private static void InvokeControllerInstanceMethod(LuaEditor editor, string controllerFieldName, string methodName) + => InvokePrivateInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName); + + private static object? InvokeControllerInstanceMethod(LuaEditor editor, string controllerFieldName, string methodName, Type[] parameterTypes, params object?[] arguments) + => InvokePrivateInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName, parameterTypes, arguments); + + private static object GetCompletionController(LuaEditor editor) + => GetPrivateField(editor, "_completionController"); + + private static T GetSignatureHelpField(LuaEditor editor, string fieldName) + => GetPrivateField(GetSignatureHelpController(editor), fieldName); + + private static T GetHoverField(LuaEditor editor, string fieldName) + => GetPrivateField(GetHoverController(editor), fieldName); + + private static object GetHoverController(LuaEditor editor) + => GetPrivateField(editor, "_hoverController"); + + private static object? GetHoverFieldValue(LuaEditor editor, string fieldName) + => GetPrivateFieldValue(GetHoverController(editor), fieldName); + + private static object GetSignatureHelpController(LuaEditor editor) + => GetPrivateField(editor, "_signatureHelpController"); + + private static void SetHoverField(LuaEditor editor, string fieldName, object value) + => SetPrivateField(GetHoverController(editor), fieldName, value); + + private static void SetSignatureHelpField(LuaEditor editor, string fieldName, object value) + => SetPrivateField(GetSignatureHelpController(editor), fieldName, value); + + private static object? InvokePrivateInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = instance.GetType().GetMethod( + methodName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Private instance method '{methodName}' was not found."); + + return method.Invoke(instance, arguments); + } + private static T GetPrivateField(object instance, string fieldName) { - FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); return (T)(field.GetValue(instance) @@ -271,12 +901,52 @@ private static T GetPrivateField(object instance, string fieldName) private static void SetPrivateField(object instance, string fieldName, object value) { - FieldInfo field = instance.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic) + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); field.SetValue(instance, value); } + private static object? GetPrivateFieldValue(object instance, string fieldName) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return field.GetValue(instance); + } + + private static FieldInfo? FindInstanceField(Type type, string fieldName) + { + for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) + { + FieldInfo? field = currentType.GetField( + fieldName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); + + if (field is not null) + return field; + } + + return null; + } + + private static Window ShowInHostWindow(FrameworkElement content) + { + var window = new Window + { + Content = content, + Width = 800.0, + Height = 600.0, + ShowActivated = false, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None + }; + + window.Show(); + window.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => { })); + return window; + } + private static void RunInSta(Action action) { Exception? capturedException = null; @@ -306,4 +976,86 @@ private static void RunInSta(Action action) if (capturedException is not null) ExceptionDispatchInfo.Capture(capturedException).Throw(); } + + private readonly record struct ProviderRequest(string FilePath, string Content, int Line, int Column); + + private sealed class FakeLuaIntellisenseProvider : ILuaIntellisenseProvider + { + public bool IsAvailable { get; set; } = true; + + public LuaHoverInfo? HoverResponse { get; set; } + + public LuaDefinitionLocation? DefinitionResponse { get; set; } + + public LuaSignatureInfo? SignatureResponse { get; set; } + + public Func>? SignatureHelpHandler { get; set; } + + public IReadOnlyList CompletionItems { get; set; } = []; + + public List DefinitionRequests { get; } = []; + + public List SignatureRequests { get; } = []; + + public event Action>? DiagnosticsUpdated + { + add { } + remove { } + } + + public event Action>? SemanticTokensUpdated + { + add { } + remove { } + } + + public IReadOnlyList GetDiagnostics(string filePath) + => []; + + public IReadOnlyList GetSemanticTokens(string filePath) + => []; + + public void OpenDocument(string filePath, string content) + { } + + public void UpdateDocument(string filePath, string content) + { } + + public void CloseDocument(string filePath) + { } + + public void RenameDocument(string oldFilePath, string newFilePath, string content) + { } + + public Task> GetCompletionItemsAsync(string filePath, string content, + int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) + => Task.FromResult(CompletionItems); + + public Task GetHoverAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + => Task.FromResult(HoverResponse); + + public Task GetDefinitionAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + DefinitionRequests.Add(new ProviderRequest(filePath, content, line, column)); + return Task.FromResult(DefinitionResponse); + } + + public Task GetSignatureHelpAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + var request = new ProviderRequest(filePath, content, line, column); + SignatureRequests.Add(request); + + if (SignatureHelpHandler is not null) + return SignatureHelpHandler(request, cancellationToken); + + return Task.FromResult(SignatureResponse); + } + + public void Dispose() + { + } + } } \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaIndentationStrategyTests.cs b/TombLib/TombLib.Test/LuaIndentationStrategyTests.cs index 6bb1b5a672..3bdc976718 100644 --- a/TombLib/TombLib.Test/LuaIndentationStrategyTests.cs +++ b/TombLib/TombLib.Test/LuaIndentationStrategyTests.cs @@ -40,13 +40,45 @@ public void IndentLine_BeforeEnd_DedentsCurrentLineWithoutExtraInsertion() [TestMethod] public void NormalizeCompletionInsertion_DedentsEndLineAndPreservesCaretAndCrLf() { - (string text, int? caretOffset) = LuaIndentationStrategy.NormalizeCompletionInsertion( + LuaCompletionNormalizationResult result = LuaIndentationStrategy.NormalizeCompletionInsertion( "if condition then\r\n\t\r\nend", "if condition then\r\n\t".Length, " ", " "); - Assert.AreEqual("if condition then\r\n \r\n end", text); - Assert.AreEqual("if condition then\r\n ".Length, caretOffset); + Assert.AreEqual("if condition then\r\n \r\n end", result.Text); + Assert.AreEqual("if condition then\r\n ".Length, result.CaretOffset); + } + + [TestMethod] + public void BuildEnterInsertion_BeforeDedent_SplitsLineAndRemovesExistingIndentation() + { + LuaEnterInsertionResult result = LuaIndentationStrategy.BuildEnterInsertion( + "if condition then", + " end", + string.Empty, + " ", + "\r\n", + useSmartIndent: true); + + Assert.AreEqual("\r\n \r\n", result.Text); + Assert.AreEqual("\r\n ".Length, result.CaretOffset); + Assert.AreEqual(4, result.RemoveFollowingWhitespaceLength); + } + + [TestMethod] + public void BuildEnterInsertion_WithoutDedentSplit_InsertsIndentedNewLineOnly() + { + LuaEnterInsertionResult result = LuaIndentationStrategy.BuildEnterInsertion( + "if condition then", + "value = 1", + string.Empty, + " ", + "\r\n", + useSmartIndent: true); + + Assert.AreEqual("\r\n ", result.Text); + Assert.AreEqual("\r\n ".Length, result.CaretOffset); + Assert.AreEqual(0, result.RemoveFollowingWhitespaceLength); } } \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs index b03a4c2261..61f62abc3e 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs @@ -375,6 +375,69 @@ public async Task UpdateDocument_SendsFullTextChangeWhenServerAdvertisesFullSync Assert.IsFalse(change.TryGetProperty("range", out _)); } + [TestMethod] + public async Task UpdateDocument_WithUnchangedContent_DoesNotSendDidChange() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(filePath, content); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 1, TimeSpan.FromSeconds(1))); + + provider.UpdateDocument(filePath, content); + + Assert.IsFalse(await client.WaitForNotificationAsync("textDocument/didChange", TimeSpan.FromMilliseconds(250))); + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task UpdateDocument_WithUnchangedContentAfterTransportFailure_ReopensWithFullSemanticTokensRefresh() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + SemanticTokenTypes = ["variable"], + SupportsSemanticTokensDelta = true + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(filePath, "local value = 1"); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/semanticTokens/full", 1, TimeSpan.FromSeconds(1))); + + client.ThrowIOExceptionOnNextDidChange = true; + + provider.UpdateDocument(filePath, "local value = 2"); + + Assert.IsTrue(await client.WaitForNotificationAsync("textDocument/didChange", TimeSpan.FromSeconds(1))); + + provider.UpdateDocument(filePath, "local value = 2"); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 2, TimeSpan.FromSeconds(1))); + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/semanticTokens/full", 2, TimeSpan.FromSeconds(1))); + + CollectionAssert.AreEqual( + new[] + { + "textDocument/didOpen", + "textDocument/semanticTokens/full", + "textDocument/didChange", + "textDocument/didOpen", + "textDocument/semanticTokens/full" + }, + client.GetSentMethodNames()); + } + [TestMethod] public async Task GetHoverAsync_ReplaysTrackedDocumentsAfterLanguageServerRestart() { diff --git a/TombLib/TombLib.Test/LuaLanguageServerRealIntegrationTests.cs b/TombLib/TombLib.Test/LuaLanguageServerRealIntegrationTests.cs new file mode 100644 index 0000000000..56974439df --- /dev/null +++ b/TombLib/TombLib.Test/LuaLanguageServerRealIntegrationTests.cs @@ -0,0 +1,87 @@ +using System.IO.Compression; +using TombIDE.ScriptingStudio.Services.LuaIntellisense; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Test; + +[TestClass] +public class LuaLanguageServerRealIntegrationTests +{ + [TestMethod] + [TestCategory("Integration")] + public async Task GetCompletionItemsAsync_WithBundledLuaLanguageServer_ReturnsLocalVariableCompletion() + { + string archivePath = TryFindRepositoryFile(Path.Combine("TombIDE", "TombIDE.Shared", "TIDE", "LuaLS.zip")) + ?? throw new AssertInconclusiveException("Could not locate the bundled LuaLS archive from the test output directory."); + + string extractionRoot = Path.Combine(Path.GetTempPath(), "LuaLsExtract_" + Guid.NewGuid().ToString("N")); + string workspaceRoot = Path.Combine(Path.GetTempPath(), "LuaLsWorkspace_" + Guid.NewGuid().ToString("N")); + + try + { + ZipFile.ExtractToDirectory(archivePath, extractionRoot); + string executablePath = Path.Combine(extractionRoot, "bin", "lua-language-server.exe"); + + Assert.IsTrue(File.Exists(executablePath), "The extracted LuaLS executable was not found."); + + string filePath = Path.Combine(workspaceRoot, "Scripts", "test.lua"); + Directory.CreateDirectory(Path.GetDirectoryName(filePath) ?? workspaceRoot); + const string content = "local spawn_room = 1\r\nsp"; +; + File.WriteAllText(filePath, content); + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, executablePath); + + IReadOnlyList items = []; + + for (int attempt = 0; attempt < 4; attempt++) + { + items = await provider.GetCompletionItemsAsync(filePath, content, 1, 2).ConfigureAwait(false); + + if (items.Any(item => string.Equals(item.Label, "spawn_room", StringComparison.Ordinal))) + break; + + await Task.Delay(250).ConfigureAwait(false); + } + + Assert.IsTrue( + items.Any(item => string.Equals(item.Label, "spawn_room", StringComparison.Ordinal)), + "The real LuaLS server did not return the expected local variable completion."); + } + finally + { + TryDeleteDirectory(extractionRoot); + TryDeleteDirectory(workspaceRoot); + } + } + + private static string? TryFindRepositoryFile(string relativePath) + { + for (DirectoryInfo? current = new(AppContext.BaseDirectory); current is not null; current = current.Parent) + { + string candidatePath = Path.Combine(current.FullName, relativePath); + + if (File.Exists(candidatePath)) + return candidatePath; + } + + return null; + } + + private static void TryDeleteDirectory(string path) + { + if (!Directory.Exists(path)) + return; + + try + { + Directory.Delete(path, recursive: true); + } + catch (IOException) + { + } + catch (UnauthorizedAccessException) + { + } + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs index fe770067c1..aeabfe443b 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs @@ -112,6 +112,24 @@ public void ParseCompletionItem_StripsSnippetAndPreservesFinalCaretOffset() Assert.AreEqual("if condition then\r\n\t".Length, item.InsertCaretOffset); } + [TestMethod] + public void ParseCompletionItem_PreservesUnknownSnippetPlaceholdersAndPlacesCaretAfterDefaultText() + { + JsonElement itemElement = JsonSerializer.SerializeToElement(new + { + label = "call", + kind = 3, + insertText = "call(${name}, ${0:done})", + insertTextFormat = 2 + }); + + LuaCompletionItem? item = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, 0); + + Assert.IsNotNull(item); + Assert.AreEqual("call(${name}, done)", item.InsertText); + Assert.AreEqual("call(${name}, done".Length, item.InsertCaretOffset); + } + [TestMethod] public void ParseCompletionItems_DeduplicatesLabelAndInsertTextCaseSensitively() { From e2e1721234f47a782a38b2139e877c8da0b44fb4 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 10 May 2026 14:49:53 +0100 Subject: [PATCH 29/34] Cleanups part 2 --- .../LuaLanguageServerResponseParser.Shared.cs | 3 + .../Services/LuaIntellisense/README.md | 11 + .../ClassicScriptEditor.cs | 146 ++++++------ .../GameFlowEditor.cs | 58 ++--- .../Completion/LuaCompletionController.cs | 47 ++-- .../Editor/Hover/LuaHoverController.cs | 31 +-- .../LuaDefinitionNavigationController.cs | 11 +- .../LuaSignatureHelpController.cs | 23 +- .../Implementations/AutocompleteManager.cs | 4 +- .../Tomb1MainEditor.cs | 37 +-- .../TombLib.Scripting/Bases/TextEditorBase.cs | 217 ++++++++---------- .../Interfaces/ISupportsFindReplace.cs | 7 - .../Services/CompletionWindowHost.cs | 93 ++++++++ .../Services/EditorToolTipPresenter.cs | 116 ++++++++++ .../Utils/EditorCompletionTriggerHelper.cs | 18 ++ ...lassicScriptEditorCompletionWindowTests.cs | 130 +++++++++++ .../EditorCompletionTriggerHelperTests.cs | 29 +++ .../GameFlowEditorCompletionWindowTests.cs | 170 ++++++++++++++ .../Tomb1MainEditorToolTipTests.cs | 133 +++++++++++ 19 files changed, 966 insertions(+), 318 deletions(-) delete mode 100644 TombLib/TombLib.Scripting/Interfaces/ISupportsFindReplace.cs create mode 100644 TombLib/TombLib.Scripting/Services/CompletionWindowHost.cs create mode 100644 TombLib/TombLib.Scripting/Services/EditorToolTipPresenter.cs create mode 100644 TombLib/TombLib.Scripting/Utils/EditorCompletionTriggerHelper.cs create mode 100644 TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs create mode 100644 TombLib/TombLib.Test/EditorCompletionTriggerHelperTests.cs create mode 100644 TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs create mode 100644 TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs index 74d87eb574..22de7f1aca 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs @@ -7,6 +7,9 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +/// +/// Converts raw LuaLS JSON payloads into the editor-facing result objects shared by completion, hover, navigation, signature-help, diagnostics, and semantic-token parsing. +/// internal static partial class LuaLanguageServerResponseParser { private readonly struct MarkupContent(string? text, bool isMarkdown) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md index 28c2ed5273..05a18b2d37 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md @@ -29,3 +29,14 @@ This note is a maintainer map for the current LuaLS integration layout after the - Move files by feature first, then extract new stateful owners only where state is still dense. - Keep document tracking centralized instead of splitting version and cache state across several helpers. - Prefer feature-oriented folders over a larger set of flat provider partials. +- Keep XML docs current on provider-facing contracts, result carriers, and other maintainer-facing entry points when responsibilities change. + +## Regression checklist + +- Completion: verify `.` `:` and manual `Ctrl+Space` requests still open the completion list, refresh correctly after edits, and continue to resolve selected-item tooltip content. +- Hover: verify symbol hover still shows hover content, and that hover falls back to diagnostics when no hover payload is available. +- Signature help: verify `(` and `,` open or refresh the popup, `)` dismisses it, and editor deactivation clears transient UI. +- Definition navigation: verify `F12` and `Ctrl+Click` navigate for valid identifiers and stay inert for comments, strings, or unresolved symbols. +- Document lifecycle: verify open, update, rename, close, and restart replay keep document versions, URIs, and open references synchronized with LuaLS. +- Diagnostics: verify published diagnostics replace stale results, clear when documents change or close, and stay attached to the correct file after rename and restart flows. +- Semantic tokens: verify full refresh, delta apply, and delta fallback all keep coloring stable after edits, file changes, and server restart. diff --git a/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs b/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs index e80004c37e..11bfaffdcb 100644 --- a/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs +++ b/TombLib/TombLib.Scripting.ClassicScript/ClassicScriptEditor.cs @@ -1,3 +1,5 @@ +#nullable enable + using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; @@ -5,6 +7,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -20,6 +23,7 @@ using TombLib.Scripting.ClassicScript.Utils; using TombLib.Scripting.Helpers; using TombLib.Scripting.Objects; +using TombLib.Scripting.Utils; using TombLib.Scripting.Workers; namespace TombLib.Scripting.ClassicScript @@ -66,6 +70,8 @@ public bool ShowSectionSeparators private IBackgroundRenderer _sectionRenderer; + private readonly record struct AutocompleteRequest(string Text, int CaretOffset, int ArgumentIndex); + #endregion Fields #region Construction @@ -80,6 +86,7 @@ public ClassicScriptEditor(Version engineVersion) : base(engineVersion) CommentPrefix = ";"; } + [MemberNotNull(nameof(_autocompleteWorker), nameof(_errorDetectionWorker))] private void InitializeBackgroundWorkers() { _autocompleteWorker = new BackgroundWorker(); @@ -90,6 +97,7 @@ private void InitializeBackgroundWorkers() _errorDetectionWorker.RunWorkerCompleted += ErrorWorker_RunWorkerCompleted; } + [MemberNotNull(nameof(_sectionRenderer))] private void InitializeRenderers() { _sectionRenderer = new SectionRenderer(this); @@ -112,33 +120,25 @@ private void BindEventMethods() #region Events - private void TextArea_TextEntering(object sender, TextCompositionEventArgs e) + private void TextArea_TextEntering(object? sender, TextCompositionEventArgs e) { - if (AutocompleteEnabled && !SuppressAutocomplete) - { - if (e.Text == " " && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) - { - if (_completionWindow == null) - HandleAutocompleteAfterSpaceCtrl(); - - e.Handled = true; - } - } + if (!SuppressAutocomplete) + TryHandleCtrlSpaceCompletion(e, HandleAutocompleteAfterSpaceCtrl); } - private void TextEditor_TextEntered(object sender, TextCompositionEventArgs e) + private void TextEditor_TextEntered(object? sender, TextCompositionEventArgs e) { if (AutocompleteEnabled && !SuppressAutocomplete) HandleAutocomplete(e); } - private void TextEditor_TextChanged(object sender, EventArgs e) + private void TextEditor_TextChanged(object? sender, EventArgs e) { if (LiveErrorUnderlining) _errorDetectionWorker.RunErrorCheckOnIdle(Text); } - private void TextEditor_KeyDown(object sender, KeyEventArgs e) + private void TextEditor_KeyDown(object? sender, KeyEventArgs e) { if (e.Key == Key.F12) { @@ -167,7 +167,7 @@ private void TextEditor_KeyDown(object sender, KeyEventArgs e) } } - private void TextEditor_MouseHover(object sender, MouseEventArgs e) + private void TextEditor_MouseHover(object? sender, MouseEventArgs e) => HandleDefinitionToolTips(e); #endregion Events @@ -180,7 +180,7 @@ private void HandleAutocomplete(TextCompositionEventArgs e) { if (_completionWindow == null) // Prevents window duplicates { - if (Document.GetLineByOffset(CaretOffset).Length == 1) + if (EditorCompletionTriggerHelper.IsSingleCharacterLine(Document.GetText(Document.GetLineByOffset(CaretOffset)))) HandleAutocompleteOnEmptyLine(); else if (e.Text != "_" && CaretOffset > 1) HandleAutocompleteAfterSpace(); @@ -201,14 +201,7 @@ private void HandleAutocompleteAfterSpaceCtrl() HandleAutocompleteOnEmptyLine(); else if (!_autocompleteWorker.IsBusy) { - var data = new List - { - Text, - CaretOffset, - -1 - }; - - _autocompleteWorker.RunWorkerAsync(data); + _autocompleteWorker.RunWorkerAsync(new AutocompleteRequest(Text, CaretOffset, -1)); } } @@ -230,14 +223,7 @@ private void HandleAutocompleteAfterSpace() || Document.GetCharAt(CaretOffset - 2) == '/') && !_autocompleteWorker.IsBusy) { - var data = new List - { - Text, - CaretOffset, - -1 - }; - - _autocompleteWorker.RunWorkerAsync(data); + _autocompleteWorker.RunWorkerAsync(new AutocompleteRequest(Text, CaretOffset, -1)); } else TryHandleIncludeAutocomplete(); @@ -250,10 +236,11 @@ private void TryHandleIncludeAutocomplete() if (Regex.IsMatch(lineText, Patterns.IncludeCommand, RegexOptions.IgnoreCase)) { - InitializeCompletionWindow(); + int? startOffset = null; + int? endOffset = null; if (Document.GetCharAt(CaretOffset - 1) == '\"') - _completionWindow.StartOffset = CaretOffset - 1; + startOffset = CaretOffset - 1; else if (Document.GetCharAt(CaretOffset - 1) != ' ') { int wordStartOffset = @@ -263,29 +250,33 @@ private void TryHandleIncludeAutocomplete() if (!word.StartsWith("#")) { - _completionWindow.StartOffset = wordStartOffset; + startOffset = wordStartOffset; if (wordStartOffset - 1 > 0 && Document.GetCharAt(wordStartOffset - 1) == '\"') - _completionWindow.StartOffset--; + startOffset--; } } if (CaretOffset < Document.TextLength && Document.GetCharAt(CaretOffset) == '\"') - _completionWindow.EndOffset = CaretOffset + 1; + endOffset = CaretOffset + 1; + + string? directoryPath = Path.GetDirectoryName(FilePath); + + if (string.IsNullOrWhiteSpace(directoryPath)) + return; - string directoryPath = Path.GetDirectoryName(FilePath); var fileDirectory = new DirectoryInfo(directoryPath); + var completionItems = new List(); foreach (FileInfo file in fileDirectory.GetFiles("*.txt", SearchOption.AllDirectories).Where(x => !x.FullName.Equals(FilePath))) { string pathPart = file.FullName.Replace(directoryPath, string.Empty).TrimStart('\\'); string completionDataString = $"\"{pathPart}\""; - _completionWindow.CompletionList.CompletionData.Add(new CompletionData(completionDataString)); + completionItems.Add(new CompletionData(completionDataString)); } - if (_completionWindow.CompletionList.CompletionData.Count > 0) - ShowCompletionWindow(); + TryOpenCompletionWindow(completionItems, startOffset, endOffset); } } @@ -299,14 +290,13 @@ private void HandleAutocompleteOnWordWithoutContext() if (!MnemonicData.AllConstantFlags.Any(x => x.StartsWith(word, StringComparison.OrdinalIgnoreCase))) return; - InitializeCompletionWindow(); - _completionWindow.StartOffset = wordStartOffset; + var completionItems = new List(); foreach (string mnemonicConstant in MnemonicData.AllConstantFlags) if (mnemonicConstant.StartsWith(word, StringComparison.OrdinalIgnoreCase)) - _completionWindow.CompletionList.CompletionData.Add(new CompletionData(mnemonicConstant)); + completionItems.Add(new CompletionData(mnemonicConstant)); - ShowCompletionWindow(); + TryOpenCompletionWindow(completionItems, wordStartOffset); } private void HandleAutocompleteOnEmptyLine() @@ -317,27 +307,23 @@ private void HandleAutocompleteOnEmptyLine() "Strings", "PSXStrings", "PCStrings", "ExtraNG")) return; - InitializeCompletionWindow(); - _completionWindow.StartOffset = Document.GetLineByOffset(CaretOffset).Offset; - - foreach (ICompletionData item in Autocomplete.GetNewLineAutocompleteList()) - _completionWindow.CompletionList.CompletionData.Add(item); - - ShowCompletionWindow(); + TryOpenCompletionWindow(Autocomplete.GetNewLineAutocompleteList(), Document.GetLineByOffset(CaretOffset).Offset); } - private void AutocompleteWorker_DoWork(object sender, DoWorkEventArgs e) + private void AutocompleteWorker_DoWork(object? sender, DoWorkEventArgs e) { - var data = e.Argument as List; + if (e.Argument is not AutocompleteRequest request) + { + e.Result = new List(); + return; + } - var document = new TextDocument(data[0].ToString()); - int caretOffset = (int)data[1]; - int argumentIndex = (int)data[2]; + var document = new TextDocument(request.Text); - e.Result = Autocomplete.GetCompletionData(document, caretOffset, argumentIndex); + e.Result = Autocomplete.GetCompletionData(document, request.CaretOffset, request.ArgumentIndex); } - private void AutocompleteWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + private void AutocompleteWorker_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) { var completionData = e.Result as List; @@ -347,21 +333,17 @@ private void AutocompleteWorker_RunWorkerCompleted(object sender, RunWorkerCompl if (completionData.Count == 0) return; - InitializeCompletionWindow(); - int wordStartOffset = TextUtilities.GetNextCaretPosition(Document, CaretOffset, LogicalDirection.Backward, CaretPositioningMode.WordStart); string word = Document.GetText(wordStartOffset, CaretOffset - wordStartOffset); + int? startOffset = null; if (!word.StartsWith("=") && !word.StartsWith(",") && !word.StartsWith("+") && !word.StartsWith("-") && !word.StartsWith("*") && !word.StartsWith("/")) - _completionWindow.StartOffset = wordStartOffset; - - foreach (ICompletionData item in completionData) - _completionWindow.CompletionList.CompletionData.Add(item); + startOffset = wordStartOffset; - ShowCompletionWindow(); + TryOpenCompletionWindow(completionData, startOffset); } #endregion Autocomplete @@ -374,7 +356,7 @@ public void CheckForErrors() _errorDetectionWorker.CheckForErrorsAsync(Text); } - private void ErrorWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + private void ErrorWorker_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) { if (e.Result is not IReadOnlyList diagnostics) return; @@ -414,7 +396,8 @@ public void InputFreeIndex() public override void UpdateSettings(Bases.ConfigurationBase configuration) { - var config = configuration as ClassicScriptEditorConfiguration; + if (configuration is not ClassicScriptEditorConfiguration config) + return; SyntaxHighlighting = new SyntaxHighlighting(config.ColorScheme); @@ -444,7 +427,7 @@ private void HandleDefinitionToolTips(MouseEventArgs e) if (HasDiagnosticsOnLine(hoveredLine)) return; - string hoveredWord = WordParser.GetWordFromOffset(Document, hoveredOffset); + string? hoveredWord = WordParser.GetWordFromOffset(Document, hoveredOffset); WordType type = WordParser.GetWordTypeFromOffset(Document, hoveredOffset); if (type == WordType.MnemonicConstant && !MnemonicData.AllConstantFlags.Any(x => x.Equals(hoveredWord, StringComparison.OrdinalIgnoreCase))) @@ -459,11 +442,14 @@ private void HandleDefinitionToolTips(MouseEventArgs e) hoveredWord = hoveredWord.Split(' ')[0]; } + if (string.IsNullOrEmpty(hoveredWord)) + return; + if (type != WordType.Unknown) { if (type == WordType.MnemonicConstant || type == WordType.Hexadecimal || type == WordType.Decimal) { - string currentFlagPrefix = ArgumentParser.GetFlagPrefixOfCurrentArgument(Document, hoveredOffset); + string? currentFlagPrefix = ArgumentParser.GetFlagPrefixOfCurrentArgument(Document, hoveredOffset); if (currentFlagPrefix == null) { @@ -475,25 +461,25 @@ private void HandleDefinitionToolTips(MouseEventArgs e) else { DataTable dataTable = MnemonicData.MnemonicConstantsDataTable; - DataRow row = null; + DataRow? row = null; switch (type) { case WordType.MnemonicConstant: row = dataTable.Rows.Cast().FirstOrDefault(r - => r[2].ToString().Equals(hoveredWord, StringComparison.OrdinalIgnoreCase)); + => string.Equals(r[2]?.ToString(), hoveredWord, StringComparison.OrdinalIgnoreCase)); break; case WordType.Hexadecimal: row = dataTable.Rows.Cast().FirstOrDefault(r - => r[1].ToString().Equals(hoveredWord, StringComparison.OrdinalIgnoreCase) - && r[2].ToString().StartsWith(currentFlagPrefix, StringComparison.OrdinalIgnoreCase)); + => string.Equals(r[1]?.ToString(), hoveredWord, StringComparison.OrdinalIgnoreCase) + && (r[2]?.ToString()?.StartsWith(currentFlagPrefix, StringComparison.OrdinalIgnoreCase) ?? false)); break; case WordType.Decimal: row = dataTable.Rows.Cast().FirstOrDefault(r - => r[0].ToString().Equals(hoveredWord, StringComparison.OrdinalIgnoreCase) - && r[2].ToString().StartsWith(currentFlagPrefix, StringComparison.OrdinalIgnoreCase)); + => string.Equals(r[0]?.ToString(), hoveredWord, StringComparison.OrdinalIgnoreCase) + && (r[2]?.ToString()?.StartsWith(currentFlagPrefix, StringComparison.OrdinalIgnoreCase) ?? false)); break; } @@ -515,22 +501,22 @@ private void HandleDefinitionToolTips(MouseEventArgs e) } } - private WordDefinitionEventArgs HoveredWordArgs = null; + private WordDefinitionEventArgs? HoveredWordArgs; public delegate void WordDefinitionRequestedEventHandler(object sender, WordDefinitionEventArgs e); - public event WordDefinitionRequestedEventHandler WordDefinitionRequested; + public event WordDefinitionRequestedEventHandler? WordDefinitionRequested; public void OnWordDefinitionRequested(WordDefinitionEventArgs e) => WordDefinitionRequested?.Invoke(this, e); [Obsolete("This method shouldn't be used for ClassicScript.\nUse WordParser.GetWordFromOffset() instead.")] public new void GetWordFromOffset(int offset) => base.GetWordFromOffset(offset); - public override void GoToObject(string objectName, object identifyingObject = null) + public override void GoToObject(string objectName, object? identifyingObject = null) { if (identifyingObject is ObjectType type) { - DocumentLine objectLine = DocumentParser.FindDocumentLineOfObject(Document, objectName, type); + DocumentLine? objectLine = DocumentParser.FindDocumentLineOfObject(Document, objectName, type); if (objectLine != null) { diff --git a/TombLib/TombLib.Scripting.GameFlowScript/GameFlowEditor.cs b/TombLib/TombLib.Scripting.GameFlowScript/GameFlowEditor.cs index dbe648cb48..f4a6b61689 100644 --- a/TombLib/TombLib.Scripting.GameFlowScript/GameFlowEditor.cs +++ b/TombLib/TombLib.Scripting.GameFlowScript/GameFlowEditor.cs @@ -1,4 +1,5 @@ -using ICSharpCode.AvalonEdit.CodeCompletion; +#nullable enable + using ICSharpCode.AvalonEdit.Document; using System; using System.Windows; @@ -11,6 +12,7 @@ using TombLib.Scripting.GameFlowScript.Parsers; using TombLib.Scripting.GameFlowScript.Utils; using TombLib.Scripting.Objects; +using TombLib.Scripting.Utils; namespace TombLib.Scripting.GameFlowScript { @@ -33,28 +35,7 @@ private void BindEventMethods() private void TextArea_TextEntering(object sender, TextCompositionEventArgs e) { - if (AutocompleteEnabled && e.Text == " " && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) - { - if (_completionWindow == null) - { - InitializeCompletionWindow(); - - int wordStartOffset = - TextUtilities.GetNextCaretPosition(Document, CaretOffset, LogicalDirection.Backward, CaretPositioningMode.WordStartOrSymbol); - - string word = Document.GetText(wordStartOffset, CaretOffset - wordStartOffset); - - if (!word.StartsWith(":")) - _completionWindow.StartOffset = wordStartOffset; - - foreach (ICompletionData item in Autocomplete.GetAutocompleteData()) - _completionWindow.CompletionList.CompletionData.Add(item); - - ShowCompletionWindow(); - } - - e.Handled = true; - } + TryHandleCtrlSpaceCompletion(e, TryShowAutocompleteWindow); } private void TextEditor_TextEntered(object sender, TextCompositionEventArgs e) @@ -67,23 +48,19 @@ private void HandleAutocomplete() { string currentLineText = LineParser.EscapeComments(Document.GetText(Document.GetLineByOffset(CaretOffset))).Trim(); - if (currentLineText.Length == 1) - { - InitializeCompletionWindow(); - - int wordStartOffset = - TextUtilities.GetNextCaretPosition(Document, CaretOffset, LogicalDirection.Backward, CaretPositioningMode.WordStartOrSymbol); - - string word = Document.GetText(wordStartOffset, CaretOffset - wordStartOffset); + if (EditorCompletionTriggerHelper.IsSingleCharacterLine(currentLineText)) + TryShowAutocompleteWindow(); + } - if (!word.StartsWith(":")) - _completionWindow.StartOffset = wordStartOffset; + private void TryShowAutocompleteWindow() + { + int wordStartOffset = + TextUtilities.GetNextCaretPosition(Document, CaretOffset, LogicalDirection.Backward, CaretPositioningMode.WordStartOrSymbol); - foreach (ICompletionData item in Autocomplete.GetAutocompleteData()) - _completionWindow.CompletionList.CompletionData.Add(item); + string word = Document.GetText(wordStartOffset, CaretOffset - wordStartOffset); + int? startOffset = word.StartsWith(":") ? null : wordStartOffset; - ShowCompletionWindow(); - } + TryOpenCompletionWindow(Autocomplete.GetAutocompleteData(), startOffset); } public override void TidyCode(bool trimOnly = false) @@ -100,7 +77,8 @@ public override void TidyCode(bool trimOnly = false) public override void UpdateSettings(Bases.ConfigurationBase configuration) { - var config = configuration as GameFlowEditorConfiguration; + if (configuration is not GameFlowEditorConfiguration config) + return; SyntaxHighlighting = new SyntaxHighlighting(config.ColorScheme); @@ -110,11 +88,11 @@ public override void UpdateSettings(Bases.ConfigurationBase configuration) base.UpdateSettings(configuration); } - public override void GoToObject(string objectName, object identifyingObject = null) + public override void GoToObject(string objectName, object? identifyingObject = null) { if (identifyingObject is ObjectType type) { - DocumentLine objectLine = DocumentParser.FindDocumentLineOfObject(Document, objectName, type); + DocumentLine? objectLine = DocumentParser.FindDocumentLineOfObject(Document, objectName, type); if (objectLine != null) { diff --git a/TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs b/TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs index d80ca17cd1..1133e7c339 100644 --- a/TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs +++ b/TombLib/TombLib.Scripting.Lua/Editor/Completion/LuaCompletionController.cs @@ -24,6 +24,9 @@ public sealed partial class LuaEditor private void CloseCompletionWindow() => _completionController.CloseWindow(); + private void CloseSharedCompletionWindow() + => base.CloseCompletionWindowCore(); + private void ScheduleCompletionRequest() => _completionController.ScheduleRequest(); @@ -63,6 +66,9 @@ private static bool IsCompletionItemCurrent(int? requestDocumentVersion, private void ScheduleCloseIfEmpty() => _completionController.ScheduleCloseIfEmpty(); + /// + /// Owns Lua completion scheduling, popup lifecycle, tooltip resolution, and AvalonEdit-specific completion-window behavior. + /// private sealed class LuaCompletionController { private const double CompletionRequestDebounceDelayInMilliseconds = 120.0; @@ -95,12 +101,12 @@ private sealed class LuaCompletionController private int _completionToolTipUpdateToken; private ToolTip? _pendingCompletionToolTip; - public LuaCompletionController(LuaEditor editor) + internal LuaCompletionController(LuaEditor editor) { _editor = editor; } - public void InitializeScheduling() + internal void InitializeScheduling() { _completionRequestTimer.Interval = TimeSpan.FromMilliseconds(CompletionRequestDebounceDelayInMilliseconds); _completionRequestTimer.Tick -= CompletionRequestTimer_Tick; @@ -111,25 +117,25 @@ public void InitializeScheduling() _completionToolTipUpdateTimer.Tick += CompletionToolTipUpdateTimer_Tick; } - public void CloseWindow() + internal void CloseWindow() { InvalidateRequests(); CloseWindowCore(); } - public void CloseWindowForRefresh() + private void CloseWindowForRefresh() => CloseWindowCore(); - public void ScheduleRequest() + internal void ScheduleRequest() { _completionRequestTimer.Stop(); _completionRequestTimer.Start(); } - public void CancelPendingRequest() + internal void CancelPendingRequest() => _completionRequestTimer.Stop(); - public async Task RequestAsync(int offset, char? triggerCharacter) + internal async Task RequestAsync(int offset, char? triggerCharacter) { CancellationToken cancellationToken = CancellationToken.None; int requestToken = ++_completionRequestToken; @@ -184,6 +190,10 @@ public async Task RequestAsync(int offset, char? triggerCharacter) CloseWindowForRefresh(); InitializeWindow(); + + if (_editor._completionWindow is null) + return; + ResizeWindow(completionDataItems); SetWindowOffsets(offset); @@ -206,7 +216,7 @@ public async Task RequestAsync(int offset, char? triggerCharacter) } } - public void RebaseOpenCompletionItems() + internal void RebaseOpenCompletionItems() { if (_editor._completionWindow?.CompletionList?.CompletionData is null) return; @@ -218,18 +228,22 @@ public void RebaseOpenCompletionItems() } } - public Task UpdateTooltipAsync(ToolTip tooltip, int updateToken) + private Task UpdateTooltipAsync(ToolTip tooltip, int updateToken) => UpdateTooltipCoreAsync(tooltip, updateToken); - public void ScheduleCloseIfEmpty() + internal void ScheduleCloseIfEmpty() => _editor.Dispatcher.BeginInvoke(new Action(() => CloseWindowIfEmpty()), DispatcherPriority.Background); - public void InvalidateRequests() + internal void InvalidateRequests() => _completionRequestToken++; private void InitializeWindow() { _editor.InitializeCompletionWindow(CompletionWindowMinWidth, CompletionWindowHeight); + + if (_editor._completionWindow is null) + return; + LuaCompletionWindowStyle.Apply(_editor._completionWindow, _editor.GetThemeBrushSet()); StyleTooltip(); MakeWindowNonActivatable(); @@ -246,8 +260,7 @@ private void CloseWindowCore() if (CompletionToolTipField?.GetValue(_editor._completionWindow) is ToolTip tooltip) tooltip.IsOpen = false; - _editor._completionWindow.Close(); - _editor._completionWindow = null; + _editor.CloseSharedCompletionWindow(); } private async void CompletionRequestTimer_Tick(object? sender, EventArgs e) @@ -432,7 +445,7 @@ private static void ApplyTooltipContent(ToolTip tooltip, object content) } } - public void CancelTooltipUpdate() + internal void CancelTooltipUpdate() { _completionToolTipUpdateToken++; _pendingCompletionToolTip = null; @@ -453,6 +466,9 @@ private void SelectInitialItem() private void MakeWindowNonActivatable() { + if (_editor._completionWindow is null) + return; + _editor._completionWindow.SourceInitialized += (s, e) => { if (s is Window window && PresentationSource.FromVisual(window) is HwndSource source) @@ -503,6 +519,9 @@ private string GetCompletionWindowQuery() private void SetWindowOffsets(int offset) { + if (_editor._completionWindow is null) + return; + int startOffset = Math.Max(0, Math.Min(offset, _editor.Document.TextLength)); while (startOffset > 0) diff --git a/TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs b/TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs index 889dfc4b1a..21058b4f18 100644 --- a/TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs +++ b/TombLib/TombLib.Scripting.Lua/Editor/Hover/LuaHoverController.cs @@ -21,25 +21,28 @@ private static FrameworkElement CreateHoverToolTipContent(LuaHoverInfo hoverInfo ? MarkdownToolTipRenderer.CreateContent(hoverInfo.Content, ToolTipForeground, DefaultToolTipBackground) : MarkdownToolTipRenderer.CreatePlainTextContent(hoverInfo.Content, ToolTipForeground); + /// + /// Owns Lua hover request state, request eligibility checks, and hover-versus-diagnostic tooltip presentation. + /// private sealed class LuaHoverController { private readonly LuaEditor _editor; private CancellationTokenSource? _hoverCancellationTokenSource; private int _hoverRequestToken; - public LuaHoverController(LuaEditor editor) + internal LuaHoverController(LuaEditor editor) { _editor = editor; } - public async Task HandleMouseHoverAsync(MouseEventArgs e) + internal async Task HandleMouseHoverAsync(MouseEventArgs e) { int hoveredOffset = _editor.GetOffsetFromPoint(e.GetPosition(_editor)); if (hoveredOffset == -1) return; - bool hasDiagnostic = _editor.TryGetDiagnosticInfo(hoveredOffset, out string diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity, allowLineFallback: false); + bool hasDiagnostic = _editor.TryGetDiagnosticInfo(hoveredOffset, out string? diagnosticMessage, out TextEditorDiagnosticSeverity diagnosticSeverity, allowLineFallback: false); bool canShowDiagnosticFallback = _editor._completionWindow is null && !_editor._signatureHelpController.IsVisible; if (!TryGetRequestOffset(hoveredOffset, out int hoverOffset) || !_editor.IsIntellisenseAvailable()) @@ -79,13 +82,13 @@ public async Task HandleMouseHoverAsync(MouseEventArgs e) } } - public void CancelPendingRequest() + internal void CancelPendingRequest() => CancelAndDispose(ref _hoverCancellationTokenSource); - public void InvalidateRequests() + internal void InvalidateRequests() => _hoverRequestToken++; - public bool TryGetRequestOffset(int hoveredOffset, out int hoverOffset) + private bool TryGetRequestOffset(int hoveredOffset, out int hoverOffset) { hoverOffset = 0; @@ -98,15 +101,17 @@ public bool TryGetRequestOffset(int hoveredOffset, out int hoverOffset) return !string.IsNullOrWhiteSpace(_editor.GetWordFromOffset(hoverOffset)); } - public void ShowDiagnosticToolTipIfAvailable(bool canShowDiagnosticFallback, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + private void ShowDiagnosticToolTipIfAvailable(bool canShowDiagnosticFallback, bool hasDiagnostic, string? diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) { - if (canShowDiagnosticFallback && hasDiagnostic) + if (canShowDiagnosticFallback && hasDiagnostic && !string.IsNullOrWhiteSpace(diagnosticMessage)) _editor.ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); } - public void ShowBestToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) + private void ShowBestToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string? diagnosticMessage, TextEditorDiagnosticSeverity diagnosticSeverity) { bool canShowToolTip = _editor._completionWindow is null && !_editor._signatureHelpController.IsVisible; + bool hasDisplayableDiagnostic = hasDiagnostic && !string.IsNullOrWhiteSpace(diagnosticMessage); + string diagnosticText = diagnosticMessage ?? string.Empty; if (!canShowToolTip) return; @@ -115,12 +120,12 @@ public void ShowBestToolTip(LuaHoverInfo? hoverInfo, bool hasDiagnostic, string ? hoverInfo : null; - if (displayableHoverInfo is not null && hasDiagnostic) - ShowCombinedToolTip(displayableHoverInfo, diagnosticMessage, diagnosticSeverity); + if (displayableHoverInfo is not null && hasDisplayableDiagnostic) + ShowCombinedToolTip(displayableHoverInfo, diagnosticText, diagnosticSeverity); else if (displayableHoverInfo is not null) ShowHoverToolTip(displayableHoverInfo); - else if (hasDiagnostic) - _editor.ShowDiagnosticToolTip(diagnosticMessage, diagnosticSeverity); + else if (hasDisplayableDiagnostic) + _editor.ShowDiagnosticToolTip(diagnosticText, diagnosticSeverity); } private void ShowCombinedToolTip(LuaHoverInfo hoverInfo, string diagnosticMessage, TextEditorDiagnosticSeverity severity) diff --git a/TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs b/TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs index ebeed12f23..12c1aef7e7 100644 --- a/TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs +++ b/TombLib/TombLib.Scripting.Lua/Editor/Navigation/LuaDefinitionNavigationController.cs @@ -8,24 +8,27 @@ namespace TombLib.Scripting.Lua; public sealed partial class LuaEditor { + /// + /// Owns Lua definition-navigation request state and the editor-side flow for F12 and Ctrl+Click navigation. + /// private sealed class LuaDefinitionNavigationController { private readonly LuaEditor _editor; private CancellationTokenSource? _definitionCancellationTokenSource; private int _definitionRequestToken; - public LuaDefinitionNavigationController(LuaEditor editor) + internal LuaDefinitionNavigationController(LuaEditor editor) { _editor = editor; } - public void CancelPendingRequest() + internal void CancelPendingRequest() => CancelAndDispose(ref _definitionCancellationTokenSource); - public void InvalidateRequests() + internal void InvalidateRequests() => _definitionRequestToken++; - public async Task TryNavigateAsync(int offset, CancellationToken cancellationToken) + internal async Task TryNavigateAsync(int offset, CancellationToken cancellationToken) { if (!_editor.IsIntellisenseAvailable()) return false; diff --git a/TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs b/TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs index 9bc7132393..9138617788 100644 --- a/TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs +++ b/TombLib/TombLib.Scripting.Lua/Editor/SignatureHelp/LuaSignatureHelpController.cs @@ -97,6 +97,9 @@ private static bool TryGetActiveParameterRange(string label, LuaSignatureInfo si return true; } + /// + /// Owns signature-help popup state, refresh scheduling, and provider request flow for Lua call-site assistance. + /// private sealed class LuaSignatureHelpController { private const double SignatureHelpRefreshDebounceDelayInMilliseconds = 50.0; @@ -112,16 +115,16 @@ private sealed class LuaSignatureHelpController private readonly ContentPresenter _signaturePopupPresenter = new(); private readonly DispatcherTimer _signatureRefreshTimer = new(); - public LuaSignatureHelpController(LuaEditor editor) + internal LuaSignatureHelpController(LuaEditor editor) { _editor = editor; } - public bool IsVisible => _signaturePopup.IsOpen; + internal bool IsVisible => _signaturePopup.IsOpen; - public bool IsActiveOrPending => _signaturePopup.IsOpen || _signatureRequestInFlight || _signatureRefreshPending; + internal bool IsActiveOrPending => _signaturePopup.IsOpen || _signatureRequestInFlight || _signatureRefreshPending; - public void InitializePopup() + internal void InitializePopup() { _signaturePopup.AllowsTransparency = true; _signaturePopup.PopupAnimation = PopupAnimation.None; @@ -143,7 +146,7 @@ public void InitializePopup() _signatureRefreshTimer.Tick += SignatureRefreshTimer_Tick; } - public void Dismiss() + internal void Dismiss() { CancelPendingRefresh(); InvalidateRequests(); @@ -154,10 +157,10 @@ public void Dismiss() _signaturePopupPresenter.Content = null; } - public Task RequestAsync(int offset) + internal Task RequestAsync(int offset) => RequestAsyncCore(offset); - public void ScheduleRefresh() + internal void ScheduleRefresh() { _pendingSignatureHelpOffset = _editor.CaretOffset; _signatureRefreshPending = true; @@ -165,20 +168,20 @@ public void ScheduleRefresh() _signatureRefreshTimer.Start(); } - public void CancelPendingRefresh() + internal void CancelPendingRefresh() { _signatureRefreshTimer.Stop(); _signatureRefreshPending = false; _pendingSignatureHelpOffset = -1; } - public void InvalidateRequests() + internal void InvalidateRequests() { _signatureRequestToken++; _signatureRequestInFlight = false; } - public void HandleRefreshTimerTick(object? sender, EventArgs e) + private void HandleRefreshTimerTick(object? sender, EventArgs e) => SignatureRefreshTimer_Tick(sender, e); private void ShowToolTip(LuaSignatureInfo signatureInfo) diff --git a/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/AutocompleteManager.cs b/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/AutocompleteManager.cs index 9e72ee2a69..dbabace25e 100644 --- a/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/AutocompleteManager.cs +++ b/TombLib/TombLib.Scripting.Tomb1Main/Services/Implementations/AutocompleteManager.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using TombLib.Scripting.Tomb1Main.Parsers; +using TombLib.Scripting.Utils; namespace TombLib.Scripting.Tomb1Main.Services.Implementations; @@ -54,7 +55,8 @@ public List FilterCompletions(List autocomplet public bool ShouldTriggerAutocompleteOnEmptyLine(TextDocument document, int caretOffset) { string currentLineText = LineParser.EscapeComments(document.GetText(document.GetLineByOffset(caretOffset))).Trim(); - return (currentLineText.Length == 1 && char.IsLetter(currentLineText[0])) || currentLineText.Equals("\"\""); + return EditorCompletionTriggerHelper.IsSingleCharacterLine(currentLineText, char.IsLetter) + || currentLineText.Equals("\"\""); } public (int startOffset, int endOffset) GetCompletionWindowOffsets(TextDocument document, int caretOffset, string currentWord) diff --git a/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs b/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs index e2ff039545..c13c0c6f99 100644 --- a/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs +++ b/TombLib/TombLib.Scripting.Tomb1Main/Tomb1MainEditor.cs @@ -1,8 +1,6 @@ #nullable enable -using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; -using ICSharpCode.AvalonEdit.Rendering; using System; using System.Collections.Generic; using System.ComponentModel; @@ -17,6 +15,7 @@ using TombLib.Scripting.Tomb1Main.Services; using TombLib.Scripting.Tomb1Main.Services.Implementations; using TombLib.Scripting.Tomb1Main.Utils; +using TombLib.Scripting.Utils; using TombLib.Scripting.Workers; namespace TombLib.Scripting.Tomb1Main @@ -71,9 +70,8 @@ private void BindEventMethods() private void TextArea_TextEntering(object sender, TextCompositionEventArgs e) { // Handle Ctrl+Space autocomplete - if (AutocompleteEnabled && IsCtrlSpaceInput(e.Text, Keyboard.Modifiers)) + if (TryHandleCtrlSpaceCompletion(e, HandleCtrlSpaceAutocomplete)) { - HandleCtrlSpaceAutocomplete(e); return; } @@ -143,9 +141,6 @@ private void ErrorWorker_RunWorkerCompleted(object? sender, RunWorkerCompletedEv #region Text input handling - private static bool IsCtrlSpaceInput(string inputText, ModifierKeys modifiers) - => inputText == " " && modifiers.HasFlag(ModifierKeys.Control); - private static bool ShouldTriggerAutocomplete(string inputText) => inputText == "\""; @@ -153,7 +148,7 @@ private static bool ShouldTriggerAutocomplete(string inputText) #region Autocomplete handling - private void HandleCtrlSpaceAutocomplete(TextCompositionEventArgs e) + private void HandleCtrlSpaceAutocomplete() { // Only allow Ctrl+Space if caret is at end of word or in whitespace if (_textAnalysisService.IsValidPositionForCtrlSpaceAutocomplete(Document, CaretOffset) && _completionWindow is null) @@ -161,8 +156,6 @@ private void HandleCtrlSpaceAutocomplete(TextCompositionEventArgs e) string currentWord = _textAnalysisService.GetCurrentWordBeingTyped(Document, CaretOffset); TryShowCompletionWindow(currentWord); } - - e.Handled = true; // Prevents the space character from being inserted } private void HandleAutocompleteOnTextEntered(TextCompositionEventArgs e) @@ -190,8 +183,7 @@ private void UpdateExistingCompletionWindow() if (matchingCompletions.Count == 0) { - _completionWindow.Close(); - _completionWindow = null; + CloseCompletionWindowCore(); } } @@ -204,33 +196,20 @@ private void TryHandleAutocompleteOnEmptyLine() } } - private bool TryShowCompletionWindow(string currentWord = "") + private void TryShowCompletionWindow(string currentWord = "") { var autocompleteData = _autocompleteService.GetAutocompleteData(); if (autocompleteData.Count == 0) - return false; + return; var filteredCompletions = _autocompleteManager.FilterCompletions(autocompleteData, currentWord); if (filteredCompletions.Count == 0) - return false; - - InitializeCompletionWindow(); - SetCompletionWindowOffsets(currentWord); - - foreach (ICompletionData item in filteredCompletions) - _completionWindow.CompletionList.CompletionData.Add(item); - - ShowCompletionWindow(); - return true; - } + return; - private void SetCompletionWindowOffsets(string currentWord) - { var (startOffset, endOffset) = _autocompleteManager.GetCompletionWindowOffsets(Document, CaretOffset, currentWord); - _completionWindow.StartOffset = startOffset; - _completionWindow.EndOffset = endOffset; + TryOpenCompletionWindow(filteredCompletions, startOffset, endOffset); } #endregion Autocomplete handling diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index 29e345de27..e3956a4581 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -1,7 +1,14 @@ -using DarkUI.Forms; +#nullable enable + +using DarkUI.Forms; +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Rendering; using System; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Text; @@ -12,22 +19,19 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; -using ICSharpCode.AvalonEdit; -using ICSharpCode.AvalonEdit.CodeCompletion; -using ICSharpCode.AvalonEdit.Document; -using ICSharpCode.AvalonEdit.Rendering; using TombLib.Scripting.Enums; using TombLib.Scripting.Interfaces; using TombLib.Scripting.Objects; using TombLib.Scripting.Rendering; using TombLib.Scripting.Resources; +using TombLib.Scripting.Services; using TombLib.Scripting.Utils; using TombLib.Scripting.Workers; using static TombLib.WPF.BrushHelpers; namespace TombLib.Scripting.Bases { - public abstract class TextEditorBase : TextEditor, IEditorControl, ISupportsFindReplace + public abstract class TextEditorBase : TextEditor, IEditorControl { protected const double ToolTipTextMaxWidth = 500.0; protected static readonly double ToolTipTextFontSize = Math.Max(SystemFonts.MessageFontSize + 1.0, 14.0); @@ -121,16 +125,16 @@ public TimeSpan TextChangedDelayedInterval #region Fields - protected Popup _specialToolTip = new Popup(); - protected CompletionWindow _completionWindow; + protected Popup _specialToolTip; + protected CompletionWindow? _completionWindow; private ContentChangedWorker _contentChangedWorker; + private readonly CompletionWindowHost _completionWindowHost; + private readonly EditorToolTipPresenter _toolTipPresenter; - private DispatcherTimer _textChangedDelayedTimer = new DispatcherTimer(); - private DispatcherTimer _toolTipCloseTimer = new DispatcherTimer(); - private bool _toolTipContentHovered; - private readonly Border _specialToolTipBorder = new Border(); - private readonly ContentPresenter _specialToolTipPresenter = new ContentPresenter(); + private readonly DispatcherTimer _textChangedDelayedTimer = new DispatcherTimer(); + private readonly Border _specialToolTipBorder; + private readonly ContentPresenter _specialToolTipPresenter; private readonly List _bookmarkAnchors = new List(); private IReadOnlyList _diagnostics = Array.Empty(); @@ -146,10 +150,14 @@ public TimeSpan TextChangedDelayedInterval public TextEditorBase(Version engineVersion) { SetNewDefaultSettings(); + _completionWindowHost = new CompletionWindowHost(TextArea); + _toolTipPresenter = new EditorToolTipPresenter(this); + _specialToolTip = _toolTipPresenter.Popup; + _specialToolTipBorder = _toolTipPresenter.Border; + _specialToolTipPresenter = _toolTipPresenter.ContentPresenter; InitializeBackgroundWorkers(); InitializeTimers(); - InitializeToolTip(); InitializeRenderers(); BindEventMethods(); @@ -174,6 +182,7 @@ private void SetNewDefaultSettings() VerticalScrollBarVisibility = ScrollBarVisibility.Auto; } + [MemberNotNull(nameof(_contentChangedWorker))] private void InitializeBackgroundWorkers() { _contentChangedWorker = new ContentChangedWorker(); @@ -184,28 +193,9 @@ private void InitializeTimers() { TextChangedDelayedInterval = new TimeSpan(0, 0, 0, 0, 300); _textChangedDelayedTimer.Tick += TextChangedDelayedTimer_Tick; - _toolTipCloseTimer.Interval = new TimeSpan(0, 0, 0, 0, 900); - _toolTipCloseTimer.Tick += ToolTipCloseTimer_Tick; - } - - private void InitializeToolTip() - { - _specialToolTip.AllowsTransparency = true; - _specialToolTip.PopupAnimation = PopupAnimation.None; - _specialToolTip.StaysOpen = true; - _specialToolTip.Placement = PlacementMode.RelativePoint; - - _specialToolTipBorder.SnapsToDevicePixels = true; - _specialToolTipBorder.CornerRadius = new CornerRadius(3.0); - _specialToolTipBorder.BorderThickness = new Thickness(1.0); - _specialToolTipBorder.Padding = new Thickness(8.0, 6.0, 8.0, 6.0); - _specialToolTipBorder.Child = _specialToolTipPresenter; - _specialToolTipBorder.MouseEnter += SpecialToolTip_MouseEnter; - _specialToolTipBorder.MouseLeave += SpecialToolTip_MouseLeave; - - _specialToolTip.Child = _specialToolTipBorder; } + [MemberNotNull(nameof(_bookmarkRenderer), nameof(_errorRenderer))] private void InitializeRenderers() { _bookmarkRenderer = new BookmarkRenderer(this); @@ -234,39 +224,39 @@ private void BindEventMethods() #region Events - public event EventHandler StatusChanged; + public event EventHandler? StatusChanged; protected virtual void OnStatusChanged(EventArgs e) => StatusChanged?.Invoke(this, e); - public event EventHandler ZoomChanged; + public event EventHandler? ZoomChanged; protected virtual void OnZoomChanged(EventArgs e) { ZoomChanged?.Invoke(this, e); OnStatusChanged(EventArgs.Empty); } - public event EventHandler TextChangedDelayed; + public event EventHandler? TextChangedDelayed; protected virtual void OnTextChangedDelayed(EventArgs e) => TextChangedDelayed?.Invoke(this, e); - public event EventHandler ContentChangedWorkerRunCompleted; + public event EventHandler? ContentChangedWorkerRunCompleted; protected virtual void OnContentChangedWorkerRunCompleted(EventArgs e) => ContentChangedWorkerRunCompleted?.Invoke(this, e); - private void ContentChangedWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + private void ContentChangedWorker_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e) { LastModified = DateTime.Now; - IsContentChanged = (bool)e.Result; + IsContentChanged = e.Result is bool isContentChanged && isContentChanged; OnContentChangedWorkerRunCompleted(EventArgs.Empty); } - private void TextArea_TextEntering(object sender, TextCompositionEventArgs e) + private void TextArea_TextEntering(object? sender, TextCompositionEventArgs e) { CloseDefinitionToolTip(true); // Prevents the ToolTip from covering the screen while typing HandleAutoClosing(e); } - private void TextEditor_TextChanged(object sender, EventArgs e) + private void TextEditor_TextChanged(object? sender, EventArgs e) { IsContentChanged = true; @@ -274,7 +264,7 @@ private void TextEditor_TextChanged(object sender, EventArgs e) _textChangedDelayedTimer.Start(); } - private void TextChangedDelayedTimer_Tick(object sender, EventArgs e) + private void TextChangedDelayedTimer_Tick(object? sender, EventArgs e) { TryRunContentChangedWorker(); @@ -282,66 +272,41 @@ private void TextChangedDelayedTimer_Tick(object sender, EventArgs e) _textChangedDelayedTimer.Stop(); } - private void TextEditor_MouseHover(object sender, MouseEventArgs e) + private void TextEditor_MouseHover(object? sender, MouseEventArgs e) => HandleMouseHover(e); protected virtual void HandleMouseHover(MouseEventArgs e) => HandleErrorToolTips(e); - private void TextEditor_MouseHoverStopped(object sender, MouseEventArgs e) + private void TextEditor_MouseHoverStopped(object? sender, MouseEventArgs e) => ScheduleDefinitionToolTipClose(); - private void TextEditor_PreviewMouseWheel(object sender, MouseWheelEventArgs e) + private void TextEditor_PreviewMouseWheel(object? sender, MouseWheelEventArgs e) { if (Keyboard.Modifiers == ModifierKeys.Control) HandleZoom(e); } - private void TextEditor_MouseRightButtonDown(object sender, MouseButtonEventArgs e) + private void TextEditor_MouseRightButtonDown(object? sender, MouseButtonEventArgs e) => MoveCaretToMousePosition(); - private void ToolTipCloseTimer_Tick(object sender, EventArgs e) - { - _toolTipCloseTimer.Stop(); - - if (!_toolTipContentHovered && !_specialToolTipBorder.IsMouseOver) - CloseDefinitionToolTip(true); - } - - private void SpecialToolTip_MouseEnter(object sender, MouseEventArgs e) - { - _toolTipContentHovered = true; - _toolTipCloseTimer.Stop(); - } - - private void SpecialToolTip_MouseLeave(object sender, MouseEventArgs e) - { - _toolTipContentHovered = false; - ScheduleDefinitionToolTipClose(); - } - protected void CloseDefinitionToolTip(bool force = false) - { - _toolTipCloseTimer.Stop(); + => _toolTipPresenter.Close(force); - if (!force && (_toolTipContentHovered || _specialToolTipBorder.IsMouseOver)) - return; + protected bool TryHandleCtrlSpaceCompletion(TextCompositionEventArgs e, Action onTriggered) + { + if (!AutocompleteEnabled || !EditorCompletionTriggerHelper.IsCtrlSpaceInput(e.Text, Keyboard.Modifiers)) + return false; - if (_specialToolTip.IsOpen) - _specialToolTip.IsOpen = false; + if (_completionWindow is null) + onTriggered(); - _specialToolTipPresenter.Content = null; - _toolTipContentHovered = false; + e.Handled = true; + return true; } private void ScheduleDefinitionToolTipClose() - { - if (!_specialToolTip.IsOpen) - return; - - _toolTipCloseTimer.Stop(); - _toolTipCloseTimer.Start(); - } + => _toolTipPresenter.ScheduleClose(); private void MoveCaretToMousePosition() { @@ -506,7 +471,7 @@ private void HandleErrorToolTips(MouseEventArgs e) TryShowDiagnosticToolTip(hoveredOffset); } - protected bool TryGetDiagnosticInfo(int hoveredOffset, out string message, out TextEditorDiagnosticSeverity severity, bool allowLineFallback = true) + protected bool TryGetDiagnosticInfo(int hoveredOffset, [NotNullWhen(true)] out string? message, out TextEditorDiagnosticSeverity severity, bool allowLineFallback = true) { message = null; severity = TextEditorDiagnosticSeverity.Error; @@ -545,7 +510,8 @@ protected void ShowDiagnosticToolTip(string message, TextEditorDiagnosticSeverit protected bool TryShowDiagnosticToolTip(int hoveredOffset) { - if (!TryGetDiagnosticInfo(hoveredOffset, out string message, out TextEditorDiagnosticSeverity severity)) + if (!TryGetDiagnosticInfo(hoveredOffset, out string? message, out TextEditorDiagnosticSeverity severity) + || string.IsNullOrWhiteSpace(message)) return false; ShowDiagnosticToolTip(message, severity); @@ -712,7 +678,7 @@ public void ToggleBookmark() { DocumentLine currentLine = Document.GetLineByOffset(CaretOffset); - TextAnchor bookmarkAnchor = FindBookmarkAnchor(currentLine); + TextAnchor? bookmarkAnchor = FindBookmarkAnchor(currentLine); if (bookmarkAnchor is null) AddBookmark(currentLine); @@ -799,24 +765,46 @@ private void HandleZoom(MouseWheelEventArgs e) #region CompletionWindow public void InitializeCompletionWindow(int width = 300, int height = 300) + => _completionWindow = _completionWindowHost.Create(width, height, DefaultToolTipBorder, DefaultToolTipBackground, ToolTipForeground); + + public void ShowCompletionWindow() { - _completionWindow = new CompletionWindow(TextArea) - { - WindowStyle = WindowStyle.None, - ResizeMode = ResizeMode.NoResize, - BorderThickness = new Thickness(1.0), - Background = DefaultToolTipBackground, - Foreground = ToolTipForeground, - BorderBrush = DefaultToolTipBorder, - Width = width, - Height = height - }; + if (_completionWindow is null) + return; + + _completionWindowHost.Show(_completionWindow, () => _completionWindow = null); } - public void ShowCompletionWindow() + protected void CloseCompletionWindowCore() + => _completionWindowHost.Close(_completionWindow, () => _completionWindow = null); + + protected bool TryOpenCompletionWindow(IEnumerable items, + int? startOffset = null, + int? endOffset = null, + int width = 300, + int height = 300) { - _completionWindow.Show(); - _completionWindow.Closed += delegate { _completionWindow = null; }; + ICompletionData[] completionItems = items?.ToArray() ?? []; + + if (completionItems.Length == 0) + return false; + + InitializeCompletionWindow(width, height); + + if (_completionWindow is null) + return false; + + if (startOffset.HasValue) + _completionWindow.StartOffset = startOffset.Value; + + if (endOffset.HasValue) + _completionWindow.EndOffset = endOffset.Value; + + foreach (ICompletionData item in completionItems) + _completionWindow.CompletionList.CompletionData.Add(item); + + ShowCompletionWindow(); + return true; } #endregion CompletionWindow @@ -894,7 +882,7 @@ public int GetOffsetFromPoint(Point point) return TextArea.TextView.GetPosition(textViewPoint + TextArea.TextView.ScrollOffset); } - public string GetWordFromOffset(int offset) + public string? GetWordFromOffset(int offset) { int wordStart = TextUtilities.GetNextCaretPosition(Document, offset, LogicalDirection.Backward, CaretPositioningMode.WordBorder); int wordEnd = TextUtilities.GetNextCaretPosition(Document, offset, LogicalDirection.Forward, CaretPositioningMode.WordBorder); @@ -924,19 +912,7 @@ public void ShowMarkdownToolTip(string content, SolidColorBrush border, SolidCol => ShowToolTip(CreateMarkdownToolTipContent(content, foreground, background), border, background); protected void ShowToolTip(object content, SolidColorBrush border, SolidColorBrush background) - { - _toolTipCloseTimer.Stop(); - _toolTipContentHovered = false; - _specialToolTip.PlacementTarget = this; - Point mousePosition = Mouse.GetPosition(this); - _specialToolTip.HorizontalOffset = mousePosition.X + 14.0; - _specialToolTip.VerticalOffset = mousePosition.Y + 20.0; - - _specialToolTipBorder.BorderBrush = border; - _specialToolTipBorder.Background = background; - _specialToolTipPresenter.Content = content; - _specialToolTip.IsOpen = true; - } + => _toolTipPresenter.Show(content, border, background); private static bool IsSeverityPrefixed(string message) => !string.IsNullOrWhiteSpace(message) @@ -972,7 +948,7 @@ private List CollectBookmarkedLines() foreach (TextAnchor anchor in _bookmarkAnchors) { - DocumentLine line = GetBookmarkedLine(anchor); + DocumentLine? line = GetBookmarkedLine(anchor); if (line is null) { @@ -1005,14 +981,14 @@ private void AddBookmark(DocumentLine line) _bookmarkAnchors.Add(anchor); } - private TextAnchor FindBookmarkAnchor(DocumentLine line) + private TextAnchor? FindBookmarkAnchor(DocumentLine line) { if (line is null) return null; foreach (TextAnchor anchor in _bookmarkAnchors) { - DocumentLine bookmarkedLine = GetBookmarkedLine(anchor); + DocumentLine? bookmarkedLine = GetBookmarkedLine(anchor); if (bookmarkedLine is not null && bookmarkedLine.LineNumber == line.LineNumber) return anchor; @@ -1021,7 +997,7 @@ private TextAnchor FindBookmarkAnchor(DocumentLine line) return null; } - private DocumentLine GetBookmarkedLine(TextAnchor anchor) + private DocumentLine? GetBookmarkedLine(TextAnchor anchor) { if (anchor is null || anchor.IsDeleted || Document.LineCount == 0) return null; @@ -1035,7 +1011,7 @@ private List GetDiagnosticsAtOffset(int offset) .Where(diagnostic => diagnostic.ContainsOffset(offset)) .ToList(); - private List GetDiagnosticsForLine(DocumentLine line) + private List GetDiagnosticsForLine(DocumentLine? line) { if (line is null || _diagnostics.Count == 0) return new List(); @@ -1087,7 +1063,8 @@ protected static void GetDiagnosticToolTipColors(TextEditorDiagnosticSeverity se public virtual void UpdateSettings(ConfigurationBase configuration) { - var config = configuration as TextEditorConfigBase; + if (configuration is not TextEditorConfigBase config) + return; FontSize = config.FontSize; DefaultFontSize = config.FontSize; @@ -1123,7 +1100,7 @@ public virtual void TidyCode(bool trimOnly = false) void IEditorControl.Undo() => Undo(); void IEditorControl.Redo() => Redo(); - public virtual void GoToObject(string objectName, object identifyingObject = null) + public virtual void GoToObject(string objectName, object? identifyingObject = null) { } // Bruh public void Dispose() diff --git a/TombLib/TombLib.Scripting/Interfaces/ISupportsFindReplace.cs b/TombLib/TombLib.Scripting/Interfaces/ISupportsFindReplace.cs deleted file mode 100644 index 5d534a877c..0000000000 --- a/TombLib/TombLib.Scripting/Interfaces/ISupportsFindReplace.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TombLib.Scripting.Interfaces -{ - internal interface ISupportsFindReplace - { - // TODO - } -} diff --git a/TombLib/TombLib.Scripting/Services/CompletionWindowHost.cs b/TombLib/TombLib.Scripting/Services/CompletionWindowHost.cs new file mode 100644 index 0000000000..246f85cea5 --- /dev/null +++ b/TombLib/TombLib.Scripting/Services/CompletionWindowHost.cs @@ -0,0 +1,93 @@ +#nullable enable + +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Editing; +using System; +using System.Windows; +using System.Windows.Media; + +namespace TombLib.Scripting.Services; + +internal sealed class CompletionWindowHost +{ + private readonly TextArea _textArea; + private EventHandler? _closedHandler; + private Action? _trackedClosedAction; + private CompletionWindow? _trackedWindow; + + public CompletionWindowHost(TextArea textArea) + => _textArea = textArea; + + public CompletionWindow Create(double width, double height, Brush borderBrush, Brush background, Brush foreground) + { + CloseTrackedWindow(); + + return new(_textArea) + { + WindowStyle = WindowStyle.None, + ResizeMode = ResizeMode.NoResize, + BorderThickness = new Thickness(1.0), + Background = background, + Foreground = foreground, + BorderBrush = borderBrush, + Width = width, + Height = height + }; + } + + public void Show(CompletionWindow completionWindow, Action onClosed) + { + TrackWindow(completionWindow, onClosed); + + completionWindow.Show(); + } + + public void Close(CompletionWindow? completionWindow, Action onClosed) + { + if (completionWindow is null) + return; + + UntrackWindow(completionWindow); + completionWindow.Close(); + onClosed(); + } + + private void TrackWindow(CompletionWindow completionWindow, Action onClosed) + { + UntrackWindow(_trackedWindow); + + _trackedWindow = completionWindow; + _trackedClosedAction = onClosed; + _closedHandler = (sender, e) => + { + UntrackWindow(completionWindow); + onClosed(); + }; + + completionWindow.Closed += _closedHandler; + } + + private void UntrackWindow(CompletionWindow? completionWindow) + { + if (completionWindow is null || _closedHandler is null || !ReferenceEquals(completionWindow, _trackedWindow)) + return; + + completionWindow.Closed -= _closedHandler; + _closedHandler = null; + _trackedClosedAction = null; + _trackedWindow = null; + } + + private void CloseTrackedWindow() + { + if (_trackedWindow is null) + return; + + CompletionWindow trackedWindow = _trackedWindow; + Action? onClosed = _trackedClosedAction; + + UntrackWindow(trackedWindow); + trackedWindow.Close(); + onClosed?.Invoke(); + } +} diff --git a/TombLib/TombLib.Scripting/Services/EditorToolTipPresenter.cs b/TombLib/TombLib.Scripting/Services/EditorToolTipPresenter.cs new file mode 100644 index 0000000000..7ec7eb3dba --- /dev/null +++ b/TombLib/TombLib.Scripting/Services/EditorToolTipPresenter.cs @@ -0,0 +1,116 @@ +#nullable enable + +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Threading; + +namespace TombLib.Scripting.Services; + +internal sealed class EditorToolTipPresenter +{ + private static readonly TimeSpan CloseDelay = TimeSpan.FromMilliseconds(900.0); + + private readonly FrameworkElement _owner; + private readonly DispatcherTimer _closeTimer = new(); + private bool _contentHovered; + + public EditorToolTipPresenter(FrameworkElement owner) + { + _owner = owner; + + Popup = new Popup + { + AllowsTransparency = true, + PopupAnimation = PopupAnimation.None, + StaysOpen = true, + Placement = PlacementMode.RelativePoint + }; + + Border = new Border + { + SnapsToDevicePixels = true, + CornerRadius = new CornerRadius(3.0), + BorderThickness = new Thickness(1.0), + Padding = new Thickness(8.0, 6.0, 8.0, 6.0) + }; + + ContentPresenter = new ContentPresenter(); + Border.Child = ContentPresenter; + Border.MouseEnter += Border_MouseEnter; + Border.MouseLeave += Border_MouseLeave; + + Popup.Child = Border; + + _closeTimer.Interval = CloseDelay; + _closeTimer.Tick += CloseTimer_Tick; + } + + public Popup Popup { get; } + + public Border Border { get; } + + public ContentPresenter ContentPresenter { get; } + + public void Show(object content, Brush borderBrush, Brush background) + { + _closeTimer.Stop(); + _contentHovered = false; + Popup.PlacementTarget = _owner; + + Point mousePosition = Mouse.GetPosition(_owner); + Popup.HorizontalOffset = mousePosition.X + 14.0; + Popup.VerticalOffset = mousePosition.Y + 20.0; + + Border.BorderBrush = borderBrush; + Border.Background = background; + ContentPresenter.Content = content; + Popup.IsOpen = true; + } + + public void Close(bool force = false) + { + _closeTimer.Stop(); + + if (!force && (_contentHovered || Border.IsMouseOver)) + return; + + if (Popup.IsOpen) + Popup.IsOpen = false; + + ContentPresenter.Content = null; + _contentHovered = false; + } + + public void ScheduleClose() + { + if (!Popup.IsOpen) + return; + + _closeTimer.Stop(); + _closeTimer.Start(); + } + + private void CloseTimer_Tick(object? sender, EventArgs e) + { + _closeTimer.Stop(); + + if (!_contentHovered && !Border.IsMouseOver) + Close(true); + } + + private void Border_MouseEnter(object sender, MouseEventArgs e) + { + _contentHovered = true; + _closeTimer.Stop(); + } + + private void Border_MouseLeave(object sender, MouseEventArgs e) + { + _contentHovered = false; + ScheduleClose(); + } +} diff --git a/TombLib/TombLib.Scripting/Utils/EditorCompletionTriggerHelper.cs b/TombLib/TombLib.Scripting/Utils/EditorCompletionTriggerHelper.cs new file mode 100644 index 0000000000..ba918ab349 --- /dev/null +++ b/TombLib/TombLib.Scripting/Utils/EditorCompletionTriggerHelper.cs @@ -0,0 +1,18 @@ +#nullable enable + +using System; +using System.Windows.Input; + +namespace TombLib.Scripting.Utils; + +public static class EditorCompletionTriggerHelper +{ + public static bool IsCtrlSpaceInput(string? inputText, ModifierKeys modifiers) + => inputText == " " && modifiers.HasFlag(ModifierKeys.Control); + + public static bool IsSingleCharacterLine(string? currentLineText) + => currentLineText?.Length == 1; + + public static bool IsSingleCharacterLine(string? currentLineText, Func characterPredicate) + => currentLineText?.Length == 1 && characterPredicate(currentLineText[0]); +} diff --git a/TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs b/TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs new file mode 100644 index 0000000000..06d9968300 --- /dev/null +++ b/TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs @@ -0,0 +1,130 @@ +using ICSharpCode.AvalonEdit.CodeCompletion; +using System; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Windows; +using System.Windows.Threading; +using TombLib.Scripting.ClassicScript; + +namespace TombLib.Test; + +[TestClass] +public class ClassicScriptEditorCompletionWindowTests +{ + [TestMethod] + public void HandleAutocompleteOnEmptyLine_OpensCompletionWindowAtLineOffset() + { + RunInSta(() => + { + var editor = new ClassicScriptEditor(new Version(1, 0)) + { + Text = string.Empty + }; + Window hostWindow = ShowInHostWindow(editor); + + try + { + InvokeInstanceMethod(editor, "HandleAutocompleteOnEmptyLine", Type.EmptyTypes); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + + CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + + Assert.IsTrue(completionWindow.CompletionList.CompletionData.Count > 0); + Assert.AreEqual(0, completionWindow.StartOffset); + } + finally + { + GetPrivateField(editor, "_completionWindow").Close(); + hostWindow.Close(); + } + }); + } + + private static object? InvokeInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = instance.GetType().GetMethod( + methodName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Instance method '{methodName}' was not found."); + + return method.Invoke(instance, arguments); + } + + private static T GetPrivateField(object instance, string fieldName) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return (T)(field.GetValue(instance) + ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); + } + + private static FieldInfo? FindInstanceField(Type type, string fieldName) + { + for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) + { + FieldInfo? field = currentType.GetField( + fieldName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); + + if (field is not null) + return field; + } + + return null; + } + + private static Window ShowInHostWindow(FrameworkElement content) + { + var window = new Window + { + Content = content, + Width = 800.0, + Height = 600.0, + ShowActivated = false, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None + }; + + window.Show(); + PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); + return window; + } + + private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) + => dispatcher.Invoke(priority, new Action(() => { })); + + private static void RunInSta(Action action) + { + Exception? capturedException = null; + using var completed = new ManualResetEventSlim(false); + + var thread = new Thread(() => + { + try + { + action(); + } + catch (Exception exception) + { + capturedException = exception; + } + finally + { + completed.Set(); + } + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + completed.Wait(); + thread.Join(); + + if (capturedException is not null) + ExceptionDispatchInfo.Capture(capturedException).Throw(); + } +} diff --git a/TombLib/TombLib.Test/EditorCompletionTriggerHelperTests.cs b/TombLib/TombLib.Test/EditorCompletionTriggerHelperTests.cs new file mode 100644 index 0000000000..7376534b67 --- /dev/null +++ b/TombLib/TombLib.Test/EditorCompletionTriggerHelperTests.cs @@ -0,0 +1,29 @@ +using System.Windows.Input; +using TombLib.Scripting.Utils; + +namespace TombLib.Test; + +[TestClass] +public class EditorCompletionTriggerHelperTests +{ + [TestMethod] + public void IsCtrlSpaceInput_ReturnsTrueOnlyForCtrlSpace() + { + Assert.IsTrue(EditorCompletionTriggerHelper.IsCtrlSpaceInput(" ", ModifierKeys.Control)); + Assert.IsTrue(EditorCompletionTriggerHelper.IsCtrlSpaceInput(" ", ModifierKeys.Control | ModifierKeys.Shift)); + Assert.IsFalse(EditorCompletionTriggerHelper.IsCtrlSpaceInput("a", ModifierKeys.Control)); + Assert.IsFalse(EditorCompletionTriggerHelper.IsCtrlSpaceInput(" ", ModifierKeys.None)); + } + + [TestMethod] + public void IsSingleCharacterLine_HandlesGeneralAndPredicateChecks() + { + Assert.IsTrue(EditorCompletionTriggerHelper.IsSingleCharacterLine("a")); + Assert.IsFalse(EditorCompletionTriggerHelper.IsSingleCharacterLine(string.Empty)); + Assert.IsFalse(EditorCompletionTriggerHelper.IsSingleCharacterLine("ab")); + Assert.IsFalse(EditorCompletionTriggerHelper.IsSingleCharacterLine(null)); + + Assert.IsTrue(EditorCompletionTriggerHelper.IsSingleCharacterLine("a", char.IsLetter)); + Assert.IsFalse(EditorCompletionTriggerHelper.IsSingleCharacterLine("1", char.IsLetter)); + } +} diff --git a/TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs b/TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs new file mode 100644 index 0000000000..be319e9ff5 --- /dev/null +++ b/TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs @@ -0,0 +1,170 @@ +using ICSharpCode.AvalonEdit.CodeCompletion; +using ICSharpCode.AvalonEdit.Document; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Windows; +using System.Windows.Threading; +using TombLib.Scripting.GameFlowScript; +using TombLib.Scripting.Objects; + +namespace TombLib.Test; + +[TestClass] +public class GameFlowEditorCompletionWindowTests +{ + [TestMethod] + public void ShowCompletionWindow_ClearsFieldWhenWindowCloses() + { + RunInSta(() => + { + var editor = new GameFlowEditor(new Version(1, 0)); + Window hostWindow = ShowInHostWindow(editor); + + try + { + editor.InitializeCompletionWindow(); + editor.ShowCompletionWindow(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + + CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + completionWindow.Close(); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + + Assert.IsNull(FindInstanceField(editor.GetType(), "_completionWindow")?.GetValue(editor)); + } + finally + { + hostWindow.Close(); + } + }); + } + + [TestMethod] + public void TryOpenCompletionWindow_PopulatesItemsAndOffsets() + { + RunInSta(() => + { + var editor = new GameFlowEditor(new Version(1, 0)) + { + Text = "test" + }; + Window hostWindow = ShowInHostWindow(editor); + + try + { + bool opened = InvokeInstanceMethod( + editor, + "TryOpenCompletionWindow", + [typeof(IEnumerable), typeof(int?), typeof(int?), typeof(int), typeof(int)], + new List { new CompletionData("Level") }, + 1, + 3, + 300, + 300) is true; + + PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + + CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + + Assert.IsTrue(opened); + Assert.AreEqual(1, completionWindow.CompletionList.CompletionData.Count); + Assert.AreEqual(1, completionWindow.StartOffset); + Assert.AreEqual(3, completionWindow.EndOffset); + } + finally + { + GetPrivateField(editor, "_completionWindow").Close(); + hostWindow.Close(); + } + }); + } + + private static object? InvokeInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = instance.GetType().GetMethod( + methodName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Instance method '{methodName}' was not found."); + + return method.Invoke(instance, arguments); + } + + private static T GetPrivateField(object instance, string fieldName) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return (T)(field.GetValue(instance) + ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); + } + + private static FieldInfo? FindInstanceField(Type type, string fieldName) + { + for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) + { + FieldInfo? field = currentType.GetField( + fieldName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); + + if (field is not null) + return field; + } + + return null; + } + + private static Window ShowInHostWindow(FrameworkElement content) + { + var window = new Window + { + Content = content, + Width = 800.0, + Height = 600.0, + ShowActivated = false, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None + }; + + window.Show(); + PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); + return window; + } + + private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) + => dispatcher.Invoke(priority, new Action(() => { })); + + private static void RunInSta(Action action) + { + Exception? capturedException = null; + using var completed = new ManualResetEventSlim(false); + + var thread = new Thread(() => + { + try + { + action(); + } + catch (Exception exception) + { + capturedException = exception; + } + finally + { + completed.Set(); + } + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + completed.Wait(); + thread.Join(); + + if (capturedException is not null) + ExceptionDispatchInfo.Capture(capturedException).Throw(); + } +} diff --git a/TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs b/TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs new file mode 100644 index 0000000000..26f8a72779 --- /dev/null +++ b/TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs @@ -0,0 +1,133 @@ +using System; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Threading; +using TombLib.Scripting.Tomb1Main; + +namespace TombLib.Test; + +[TestClass] +public class Tomb1MainEditorToolTipTests +{ + [TestMethod] + public void ShowMarkdownToolTip_OpensPopupAndForceCloseClearsContent() + { + RunInSta(() => + { + var editor = new Tomb1MainEditor(new Version(1, 0)); + Window hostWindow = ShowInHostWindow(editor); + + try + { + editor.ShowMarkdownToolTip("`Level` tooltip"); + PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + + Popup popup = GetPrivateField(editor, "_specialToolTip"); + ContentPresenter presenter = GetPrivateField(editor, "_specialToolTipPresenter"); + + Assert.IsTrue(popup.IsOpen); + Assert.IsNotNull(presenter.Content); + + InvokeInstanceMethod(editor, "CloseDefinitionToolTip", [typeof(bool)], true); + + Assert.IsFalse(popup.IsOpen); + Assert.IsNull(presenter.Content); + } + finally + { + hostWindow.Close(); + } + }); + } + + private static object? InvokeInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = instance.GetType().GetMethod( + methodName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Instance method '{methodName}' was not found."); + + return method.Invoke(instance, arguments); + } + + private static T GetPrivateField(object instance, string fieldName) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return (T)(field.GetValue(instance) + ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); + } + + private static FieldInfo? FindInstanceField(Type type, string fieldName) + { + for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) + { + FieldInfo? field = currentType.GetField( + fieldName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); + + if (field is not null) + return field; + } + + return null; + } + + private static Window ShowInHostWindow(FrameworkElement content) + { + var window = new Window + { + Content = content, + Width = 800.0, + Height = 600.0, + ShowActivated = false, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None + }; + + window.Show(); + PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); + return window; + } + + private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) + => dispatcher.Invoke(priority, new Action(() => { })); + + private static void RunInSta(Action action) + { + Exception? capturedException = null; + using var completed = new ManualResetEventSlim(false); + + var thread = new Thread(() => + { + try + { + action(); + } + catch (Exception exception) + { + capturedException = exception; + } + finally + { + completed.Set(); + } + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + completed.Wait(); + thread.Join(); + + if (capturedException is not null) + ExceptionDispatchInfo.Capture(capturedException).Throw(); + } +} From d0d5886d503b5bd7fd7ed68921dda8a5d25a7472 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 10 May 2026 14:51:19 +0100 Subject: [PATCH 30/34] Test cleanups --- ...lassicScriptEditorCompletionWindowTests.cs | 102 +----------- .../GameFlowEditorCompletionWindowTests.cs | 151 ++++++------------ .../LuaEditorCompletionWindowTests.cs | 104 +----------- .../LuaEditorIntellisenseStateTests.cs | 137 ++-------------- .../MarkdownToolTipRendererTests.cs | 34 +--- .../Tomb1MainEditorToolTipTests.cs | 102 +----------- TombLib/TombLib.Test/WpfTestHelper.cs | 127 +++++++++++++++ 7 files changed, 203 insertions(+), 554 deletions(-) create mode 100644 TombLib/TombLib.Test/WpfTestHelper.cs diff --git a/TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs b/TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs index 06d9968300..73a45fa03a 100644 --- a/TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs +++ b/TombLib/TombLib.Test/ClassicScriptEditorCompletionWindowTests.cs @@ -1,8 +1,5 @@ using ICSharpCode.AvalonEdit.CodeCompletion; using System; -using System.Reflection; -using System.Runtime.ExceptionServices; -using System.Threading; using System.Windows; using System.Windows.Threading; using TombLib.Scripting.ClassicScript; @@ -15,116 +12,29 @@ public class ClassicScriptEditorCompletionWindowTests [TestMethod] public void HandleAutocompleteOnEmptyLine_OpensCompletionWindowAtLineOffset() { - RunInSta(() => + WpfTestHelper.RunInSta(() => { var editor = new ClassicScriptEditor(new Version(1, 0)) { Text = string.Empty }; - Window hostWindow = ShowInHostWindow(editor); + Window hostWindow = WpfTestHelper.ShowInHostWindow(editor); try { - InvokeInstanceMethod(editor, "HandleAutocompleteOnEmptyLine", Type.EmptyTypes); - PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + WpfTestHelper.InvokeInstanceMethod(editor, "HandleAutocompleteOnEmptyLine", Type.EmptyTypes); + WpfTestHelper.PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); - CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + CompletionWindow completionWindow = WpfTestHelper.GetPrivateField(editor, "_completionWindow"); Assert.IsTrue(completionWindow.CompletionList.CompletionData.Count > 0); Assert.AreEqual(0, completionWindow.StartOffset); } finally { - GetPrivateField(editor, "_completionWindow").Close(); + WpfTestHelper.GetPrivateField(editor, "_completionWindow").Close(); hostWindow.Close(); } }); } - - private static object? InvokeInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) - { - MethodInfo method = instance.GetType().GetMethod( - methodName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - binder: null, - parameterTypes, - modifiers: null) - ?? throw new InvalidOperationException($"Instance method '{methodName}' was not found."); - - return method.Invoke(instance, arguments); - } - - private static T GetPrivateField(object instance, string fieldName) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - return (T)(field.GetValue(instance) - ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); - } - - private static FieldInfo? FindInstanceField(Type type, string fieldName) - { - for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) - { - FieldInfo? field = currentType.GetField( - fieldName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - - if (field is not null) - return field; - } - - return null; - } - - private static Window ShowInHostWindow(FrameworkElement content) - { - var window = new Window - { - Content = content, - Width = 800.0, - Height = 600.0, - ShowActivated = false, - ShowInTaskbar = false, - WindowStyle = WindowStyle.None - }; - - window.Show(); - PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); - return window; - } - - private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) - => dispatcher.Invoke(priority, new Action(() => { })); - - private static void RunInSta(Action action) - { - Exception? capturedException = null; - using var completed = new ManualResetEventSlim(false); - - var thread = new Thread(() => - { - try - { - action(); - } - catch (Exception exception) - { - capturedException = exception; - } - finally - { - completed.Set(); - } - }); - - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - completed.Wait(); - thread.Join(); - - if (capturedException is not null) - ExceptionDispatchInfo.Capture(capturedException).Throw(); - } } diff --git a/TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs b/TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs index be319e9ff5..4aa5ce5847 100644 --- a/TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs +++ b/TombLib/TombLib.Test/GameFlowEditorCompletionWindowTests.cs @@ -1,9 +1,6 @@ using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; using System.Collections.Generic; -using System.Reflection; -using System.Runtime.ExceptionServices; -using System.Threading; using System.Windows; using System.Windows.Threading; using TombLib.Scripting.GameFlowScript; @@ -17,22 +14,22 @@ public class GameFlowEditorCompletionWindowTests [TestMethod] public void ShowCompletionWindow_ClearsFieldWhenWindowCloses() { - RunInSta(() => + WpfTestHelper.RunInSta(() => { var editor = new GameFlowEditor(new Version(1, 0)); - Window hostWindow = ShowInHostWindow(editor); + Window hostWindow = WpfTestHelper.ShowInHostWindow(editor); try { editor.InitializeCompletionWindow(); editor.ShowCompletionWindow(); - PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + WpfTestHelper.PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); - CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + CompletionWindow completionWindow = WpfTestHelper.GetPrivateField(editor, "_completionWindow"); completionWindow.Close(); - PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + WpfTestHelper.PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); - Assert.IsNull(FindInstanceField(editor.GetType(), "_completionWindow")?.GetValue(editor)); + Assert.IsNull(WpfTestHelper.FindInstanceField(editor.GetType(), "_completionWindow")?.GetValue(editor)); } finally { @@ -41,20 +38,54 @@ public void ShowCompletionWindow_ClearsFieldWhenWindowCloses() }); } + [TestMethod] + public void InitializeCompletionWindow_ReplacesVisibleWindowInsteadOfLeavingItOpen() + { + WpfTestHelper.RunInSta(() => + { + var editor = new GameFlowEditor(new Version(1, 0)); + Window hostWindow = WpfTestHelper.ShowInHostWindow(editor); + + try + { + editor.InitializeCompletionWindow(); + editor.ShowCompletionWindow(); + WpfTestHelper.PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + + CompletionWindow firstWindow = WpfTestHelper.GetPrivateField(editor, "_completionWindow"); + + editor.InitializeCompletionWindow(); + editor.ShowCompletionWindow(); + WpfTestHelper.PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + + CompletionWindow secondWindow = WpfTestHelper.GetPrivateField(editor, "_completionWindow"); + + Assert.AreNotSame(firstWindow, secondWindow); + Assert.IsFalse(firstWindow.IsVisible); + Assert.IsTrue(secondWindow.IsVisible); + } + finally + { + WpfTestHelper.GetPrivateField(editor, "_completionWindow").Close(); + hostWindow.Close(); + } + }); + } + [TestMethod] public void TryOpenCompletionWindow_PopulatesItemsAndOffsets() { - RunInSta(() => + WpfTestHelper.RunInSta(() => { var editor = new GameFlowEditor(new Version(1, 0)) { Text = "test" }; - Window hostWindow = ShowInHostWindow(editor); + Window hostWindow = WpfTestHelper.ShowInHostWindow(editor); try { - bool opened = InvokeInstanceMethod( + bool opened = (bool)(WpfTestHelper.InvokeInstanceMethod( editor, "TryOpenCompletionWindow", [typeof(IEnumerable), typeof(int?), typeof(int?), typeof(int), typeof(int)], @@ -62,11 +93,12 @@ public void TryOpenCompletionWindow_PopulatesItemsAndOffsets() 1, 3, 300, - 300) is true; + 300) + ?? throw new InvalidOperationException("Instance method 'TryOpenCompletionWindow' returned null.")); - PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + WpfTestHelper.PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); - CompletionWindow completionWindow = GetPrivateField(editor, "_completionWindow"); + CompletionWindow completionWindow = WpfTestHelper.GetPrivateField(editor, "_completionWindow"); Assert.IsTrue(opened); Assert.AreEqual(1, completionWindow.CompletionList.CompletionData.Count); @@ -75,96 +107,9 @@ public void TryOpenCompletionWindow_PopulatesItemsAndOffsets() } finally { - GetPrivateField(editor, "_completionWindow").Close(); + WpfTestHelper.GetPrivateField(editor, "_completionWindow").Close(); hostWindow.Close(); } }); } - - private static object? InvokeInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) - { - MethodInfo method = instance.GetType().GetMethod( - methodName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - binder: null, - parameterTypes, - modifiers: null) - ?? throw new InvalidOperationException($"Instance method '{methodName}' was not found."); - - return method.Invoke(instance, arguments); - } - - private static T GetPrivateField(object instance, string fieldName) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - return (T)(field.GetValue(instance) - ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); - } - - private static FieldInfo? FindInstanceField(Type type, string fieldName) - { - for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) - { - FieldInfo? field = currentType.GetField( - fieldName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - - if (field is not null) - return field; - } - - return null; - } - - private static Window ShowInHostWindow(FrameworkElement content) - { - var window = new Window - { - Content = content, - Width = 800.0, - Height = 600.0, - ShowActivated = false, - ShowInTaskbar = false, - WindowStyle = WindowStyle.None - }; - - window.Show(); - PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); - return window; - } - - private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) - => dispatcher.Invoke(priority, new Action(() => { })); - - private static void RunInSta(Action action) - { - Exception? capturedException = null; - using var completed = new ManualResetEventSlim(false); - - var thread = new Thread(() => - { - try - { - action(); - } - catch (Exception exception) - { - capturedException = exception; - } - finally - { - completed.Set(); - } - }); - - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - completed.Wait(); - thread.Join(); - - if (capturedException is not null) - ExceptionDispatchInfo.Capture(capturedException).Throw(); - } } diff --git a/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs b/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs index 6444c98529..17dd8318d7 100644 --- a/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs +++ b/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs @@ -1,7 +1,5 @@ using ICSharpCode.AvalonEdit.CodeCompletion; using System.Reflection; -using System.Runtime.ExceptionServices; -using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -10,6 +8,7 @@ using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; using TombLib.Scripting.Objects; +using static TombLib.Test.WpfTestHelper; namespace TombLib.Test; @@ -276,28 +275,15 @@ private static LuaEditor CreateEditor(ILuaIntellisenseProvider provider, string }; private static Task InvokePrivateTask(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) - => (Task)(InvokePrivateInstanceMethod(instance, methodName, parameterTypes, arguments) + => (Task)(InvokeInstanceMethod(instance, methodName, parameterTypes, arguments) ?? throw new InvalidOperationException($"Private instance method '{methodName}' returned null.")); private static Task InvokeControllerTask(LuaEditor editor, string controllerFieldName, string methodName, Type[] parameterTypes, params object?[] arguments) - => (Task)(InvokePrivateInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName, parameterTypes, arguments) + => (Task)(InvokeInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName, parameterTypes, arguments) ?? throw new InvalidOperationException($"Controller method '{methodName}' returned null.")); - private static object? InvokePrivateInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) - { - MethodInfo method = instance.GetType().GetMethod( - methodName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - binder: null, - parameterTypes, - modifiers: null) - ?? throw new InvalidOperationException($"Private instance method '{methodName}' was not found."); - - return method.Invoke(instance, arguments); - } - private static void CloseCompletionWindow(LuaEditor editor) - => InvokePrivateInstanceMethod(editor, "CloseCompletionWindow", Type.EmptyTypes); + => InvokeInstanceMethod(editor, "CloseCompletionWindow", Type.EmptyTypes); private static object GetCompletionController(LuaEditor editor) => GetPrivateField(editor, "_completionController"); @@ -308,38 +294,6 @@ private static T GetSignatureHelpField(LuaEditor editor, string fieldName) private static void SetSignatureHelpField(LuaEditor editor, string fieldName, object value) => SetPrivateField(GetPrivateField(editor, "_signatureHelpController"), fieldName, value); - private static T GetPrivateField(object instance, string fieldName) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - return (T)(field.GetValue(instance) - ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); - } - - private static void SetPrivateField(object instance, string fieldName, object value) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - field.SetValue(instance, value); - } - - private static FieldInfo? FindInstanceField(Type type, string fieldName) - { - for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) - { - FieldInfo? field = currentType.GetField( - fieldName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - - if (field is not null) - return field; - } - - return null; - } - private static ToolTip GetCompletionToolTip(CompletionWindow completionWindow) { FieldInfo field = typeof(CompletionWindow).GetField("toolTip", BindingFlags.Instance | BindingFlags.NonPublic) @@ -349,56 +303,6 @@ private static ToolTip GetCompletionToolTip(CompletionWindow completionWindow) ?? throw new InvalidOperationException("CompletionWindow private field 'toolTip' returned null.")); } - private static Window ShowInHostWindow(FrameworkElement content) - { - var window = new Window - { - Content = content, - Width = 800.0, - Height = 600.0, - ShowActivated = false, - ShowInTaskbar = false, - WindowStyle = WindowStyle.None - }; - - window.Show(); - PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); - return window; - } - - private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) - => dispatcher.Invoke(priority, new Action(() => { })); - - private static void RunInSta(Action action) - { - Exception? capturedException = null; - using var completed = new ManualResetEventSlim(false); - - var thread = new Thread(() => - { - try - { - action(); - } - catch (Exception exception) - { - capturedException = exception; - } - finally - { - completed.Set(); - } - }); - - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - completed.Wait(); - thread.Join(); - - if (capturedException is not null) - ExceptionDispatchInfo.Capture(capturedException).Throw(); - } - private readonly record struct CompletionRequest(string FilePath, string Content, int Line, int Column, char? TriggerCharacter); private sealed class FakeLuaCompletionProvider : ILuaIntellisenseProvider diff --git a/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs index 06fda73c32..f0e7e80a38 100644 --- a/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs +++ b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Reflection; -using System.Runtime.ExceptionServices; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -12,6 +11,7 @@ using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; using TombLib.Scripting.Objects; +using static TombLib.Test.WpfTestHelper; namespace TombLib.Test; @@ -115,7 +115,7 @@ public void DismissSignatureHelp_ClearsPendingStateAndInvalidatesOutstandingRequ SetSignatureHelpField(editor, "_signatureRefreshPending", true); SetSignatureHelpField(editor, "_pendingSignatureHelpOffset", 9); - InvokePrivateInstanceMethod(editor, "DismissSignatureHelp"); + InvokeInstanceMethod(editor, "DismissSignatureHelp", Type.EmptyTypes); Assert.IsFalse(GetSignatureHelpField(editor, "_signatureRequestInFlight")); Assert.AreEqual(6, GetSignatureHelpField(editor, "_signatureRequestToken")); @@ -368,7 +368,7 @@ public void CloseCompletionWindow_InvalidatesPendingRequests_ButRefreshCloseDoes object completionController = GetCompletionController(editor); SetPrivateField(completionController, "_completionRequestToken", 5); - InvokePrivateInstanceMethod(editor, "CloseCompletionWindow"); + InvokeInstanceMethod(editor, "CloseCompletionWindow", Type.EmptyTypes); Assert.AreEqual(6, GetPrivateField(completionController, "_completionRequestToken")); InvokeControllerInstanceMethod(editor, "_completionController", "CloseWindowForRefresh"); @@ -537,7 +537,7 @@ public void DismissTransientToolTips_CancelsHoverAndClearsTransientUi() editor.InitializeCompletionWindow(); editor.ShowToolTip("Hover docs."); - InvokePrivateInstanceMethod(editor, "DismissTransientToolTips"); + InvokeInstanceMethod(editor, "DismissTransientToolTips", Type.EmptyTypes); Assert.IsTrue(hoverCancellationTokenSource.IsCancellationRequested); Assert.IsNull(GetHoverFieldValue(editor, "_hoverCancellationTokenSource")); @@ -654,7 +654,7 @@ public void RequestSignatureHelpAsync_DismissesExistingPopupWhenProviderReturnsN presenter.Content = new TextBlock { Text = "signature" }; popup.IsOpen = true; - Task requestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) + Task requestTask = (Task)(InvokeInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); requestTask.GetAwaiter().GetResult(); @@ -706,10 +706,10 @@ public void RequestSignatureHelpAsync_WhenRequestIsInFlight_DefersRefreshToLates try { - Task firstRequestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) + Task firstRequestTask = (Task)(InvokeInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); - Task deferredRequestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 11) + Task deferredRequestTask = (Task)(InvokeInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 11) ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); deferredRequestTask.GetAwaiter().GetResult(); @@ -769,7 +769,7 @@ [new LuaParameterInfo("room", "Room id.")], try { - Task requestTask = (Task)(InvokePrivateInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) + Task requestTask = (Task)(InvokeInstanceMethod(editor, "RequestSignatureHelpAsync", [typeof(int)], 6) ?? throw new InvalidOperationException("Private instance method 'RequestSignatureHelpAsync' returned null.")); requestTask.GetAwaiter().GetResult(); @@ -792,14 +792,7 @@ [new LuaParameterInfo("room", "Room id.")], private static bool InvokePrivateStaticBooleanMethod(string methodName, Type[] parameterTypes, params object?[] arguments) { - MethodInfo method = typeof(LuaEditor).GetMethod(methodName, - BindingFlags.Static | BindingFlags.NonPublic, - binder: null, - parameterTypes, - modifiers: null) - ?? throw new InvalidOperationException($"Private static method '{methodName}' was not found."); - - return (bool)(method.Invoke(null, arguments) + return (bool)(InvokeStaticMethod(typeof(LuaEditor), methodName, parameterTypes, arguments) ?? throw new InvalidOperationException($"Private static method '{methodName}' returned null.")); } @@ -839,19 +832,11 @@ private static bool InvokeTryGetHoverRequestOffset(LuaEditor editor, int hovered return result; } - private static void InvokePrivateInstanceMethod(object instance, string methodName) - { - MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) - ?? throw new InvalidOperationException($"Private instance method '{methodName}' was not found."); - - method.Invoke(instance, null); - } - private static void InvokeControllerInstanceMethod(LuaEditor editor, string controllerFieldName, string methodName) - => InvokePrivateInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName); + => InvokeInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName, Type.EmptyTypes); private static object? InvokeControllerInstanceMethod(LuaEditor editor, string controllerFieldName, string methodName, Type[] parameterTypes, params object?[] arguments) - => InvokePrivateInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName, parameterTypes, arguments); + => InvokeInstanceMethod(GetPrivateField(editor, controllerFieldName), methodName, parameterTypes, arguments); private static object GetCompletionController(LuaEditor editor) => GetPrivateField(editor, "_completionController"); @@ -877,106 +862,6 @@ private static void SetHoverField(LuaEditor editor, string fieldName, object val private static void SetSignatureHelpField(LuaEditor editor, string fieldName, object value) => SetPrivateField(GetSignatureHelpController(editor), fieldName, value); - private static object? InvokePrivateInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) - { - MethodInfo method = instance.GetType().GetMethod( - methodName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - binder: null, - parameterTypes, - modifiers: null) - ?? throw new InvalidOperationException($"Private instance method '{methodName}' was not found."); - - return method.Invoke(instance, arguments); - } - - private static T GetPrivateField(object instance, string fieldName) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - return (T)(field.GetValue(instance) - ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); - } - - private static void SetPrivateField(object instance, string fieldName, object value) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - field.SetValue(instance, value); - } - - private static object? GetPrivateFieldValue(object instance, string fieldName) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - return field.GetValue(instance); - } - - private static FieldInfo? FindInstanceField(Type type, string fieldName) - { - for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) - { - FieldInfo? field = currentType.GetField( - fieldName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - - if (field is not null) - return field; - } - - return null; - } - - private static Window ShowInHostWindow(FrameworkElement content) - { - var window = new Window - { - Content = content, - Width = 800.0, - Height = 600.0, - ShowActivated = false, - ShowInTaskbar = false, - WindowStyle = WindowStyle.None - }; - - window.Show(); - window.Dispatcher.Invoke(DispatcherPriority.Background, new Action(() => { })); - return window; - } - - private static void RunInSta(Action action) - { - Exception? capturedException = null; - using var completed = new ManualResetEventSlim(false); - - var thread = new Thread(() => - { - try - { - action(); - } - catch (Exception exception) - { - capturedException = exception; - } - finally - { - completed.Set(); - } - }); - - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - completed.Wait(); - thread.Join(); - - if (capturedException is not null) - ExceptionDispatchInfo.Capture(capturedException).Throw(); - } - private readonly record struct ProviderRequest(string FilePath, string Content, int Line, int Column); private sealed class FakeLuaIntellisenseProvider : ILuaIntellisenseProvider diff --git a/TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs b/TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs index 152e760e2f..723c4415fb 100644 --- a/TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs +++ b/TombLib/TombLib.Test/MarkdownToolTipRendererTests.cs @@ -1,5 +1,3 @@ -using System.Runtime.ExceptionServices; -using System.Threading; using System.Windows.Media; using ICSharpCode.AvalonEdit; using TombLib.Scripting.Rendering; @@ -12,7 +10,7 @@ public class MarkdownToolTipRendererTests [TestMethod] public void CreateCodeBlockEditor_DoesNotAcceptKeyboardFocus() { - RunInSta(() => + WpfTestHelper.RunInSta(() => { TextEditor editor = MarkdownToolTipRenderer.CreateCodeBlockEditor("lua", "local value = 1", Brushes.White); @@ -22,34 +20,4 @@ public void CreateCodeBlockEditor_DoesNotAcceptKeyboardFocus() Assert.IsFalse(editor.TextArea.IsTabStop); }); } - - private static void RunInSta(Action action) - { - Exception? capturedException = null; - using var completed = new ManualResetEventSlim(false); - - var thread = new Thread(() => - { - try - { - action(); - } - catch (Exception exception) - { - capturedException = exception; - } - finally - { - completed.Set(); - } - }); - - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - completed.Wait(); - thread.Join(); - - if (capturedException is not null) - ExceptionDispatchInfo.Capture(capturedException).Throw(); - } } \ No newline at end of file diff --git a/TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs b/TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs index 26f8a72779..20a6b1d7d6 100644 --- a/TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs +++ b/TombLib/TombLib.Test/Tomb1MainEditorToolTipTests.cs @@ -1,7 +1,4 @@ using System; -using System.Reflection; -using System.Runtime.ExceptionServices; -using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; @@ -16,23 +13,23 @@ public class Tomb1MainEditorToolTipTests [TestMethod] public void ShowMarkdownToolTip_OpensPopupAndForceCloseClearsContent() { - RunInSta(() => + WpfTestHelper.RunInSta(() => { var editor = new Tomb1MainEditor(new Version(1, 0)); - Window hostWindow = ShowInHostWindow(editor); + Window hostWindow = WpfTestHelper.ShowInHostWindow(editor); try { editor.ShowMarkdownToolTip("`Level` tooltip"); - PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); + WpfTestHelper.PumpDispatcher(editor.Dispatcher, DispatcherPriority.Background); - Popup popup = GetPrivateField(editor, "_specialToolTip"); - ContentPresenter presenter = GetPrivateField(editor, "_specialToolTipPresenter"); + Popup popup = WpfTestHelper.GetPrivateField(editor, "_specialToolTip"); + ContentPresenter presenter = WpfTestHelper.GetPrivateField(editor, "_specialToolTipPresenter"); Assert.IsTrue(popup.IsOpen); Assert.IsNotNull(presenter.Content); - InvokeInstanceMethod(editor, "CloseDefinitionToolTip", [typeof(bool)], true); + WpfTestHelper.InvokeInstanceMethod(editor, "CloseDefinitionToolTip", [typeof(bool)], true); Assert.IsFalse(popup.IsOpen); Assert.IsNull(presenter.Content); @@ -43,91 +40,4 @@ public void ShowMarkdownToolTip_OpensPopupAndForceCloseClearsContent() } }); } - - private static object? InvokeInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) - { - MethodInfo method = instance.GetType().GetMethod( - methodName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, - binder: null, - parameterTypes, - modifiers: null) - ?? throw new InvalidOperationException($"Instance method '{methodName}' was not found."); - - return method.Invoke(instance, arguments); - } - - private static T GetPrivateField(object instance, string fieldName) - { - FieldInfo field = FindInstanceField(instance.GetType(), fieldName) - ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); - - return (T)(field.GetValue(instance) - ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); - } - - private static FieldInfo? FindInstanceField(Type type, string fieldName) - { - for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) - { - FieldInfo? field = currentType.GetField( - fieldName, - BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); - - if (field is not null) - return field; - } - - return null; - } - - private static Window ShowInHostWindow(FrameworkElement content) - { - var window = new Window - { - Content = content, - Width = 800.0, - Height = 600.0, - ShowActivated = false, - ShowInTaskbar = false, - WindowStyle = WindowStyle.None - }; - - window.Show(); - PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); - return window; - } - - private static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) - => dispatcher.Invoke(priority, new Action(() => { })); - - private static void RunInSta(Action action) - { - Exception? capturedException = null; - using var completed = new ManualResetEventSlim(false); - - var thread = new Thread(() => - { - try - { - action(); - } - catch (Exception exception) - { - capturedException = exception; - } - finally - { - completed.Set(); - } - }); - - thread.SetApartmentState(ApartmentState.STA); - thread.Start(); - completed.Wait(); - thread.Join(); - - if (capturedException is not null) - ExceptionDispatchInfo.Capture(capturedException).Throw(); - } } diff --git a/TombLib/TombLib.Test/WpfTestHelper.cs b/TombLib/TombLib.Test/WpfTestHelper.cs new file mode 100644 index 0000000000..2b57a21160 --- /dev/null +++ b/TombLib/TombLib.Test/WpfTestHelper.cs @@ -0,0 +1,127 @@ +using System; +using System.Reflection; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Windows; +using System.Windows.Threading; + +namespace TombLib.Test; + +internal static class WpfTestHelper +{ + public static T GetPrivateField(object instance, string fieldName) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return (T)(field.GetValue(instance) + ?? throw new InvalidOperationException($"Private field '{fieldName}' returned null.")); + } + + public static object? GetPrivateFieldValue(object instance, string fieldName) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + return field.GetValue(instance); + } + + public static void SetPrivateField(object instance, string fieldName, object? value) + { + FieldInfo field = FindInstanceField(instance.GetType(), fieldName) + ?? throw new InvalidOperationException($"Private field '{fieldName}' was not found."); + + field.SetValue(instance, value); + } + + public static object? InvokeInstanceMethod(object instance, string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = instance.GetType().GetMethod( + methodName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Instance method '{methodName}' was not found."); + + return method.Invoke(instance, arguments); + } + + public static object? InvokeStaticMethod(Type type, string methodName, Type[] parameterTypes, params object?[] arguments) + { + MethodInfo method = type.GetMethod( + methodName, + BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + parameterTypes, + modifiers: null) + ?? throw new InvalidOperationException($"Static method '{methodName}' was not found."); + + return method.Invoke(null, arguments); + } + + public static FieldInfo? FindInstanceField(Type type, string fieldName) + { + for (Type? currentType = type; currentType is not null; currentType = currentType.BaseType) + { + FieldInfo? field = currentType.GetField( + fieldName, + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); + + if (field is not null) + return field; + } + + return null; + } + + public static Window ShowInHostWindow(FrameworkElement content) + { + var window = new Window + { + Content = content, + Width = 800.0, + Height = 600.0, + ShowActivated = false, + ShowInTaskbar = false, + WindowStyle = WindowStyle.None + }; + + window.Show(); + PumpDispatcher(window.Dispatcher, DispatcherPriority.Background); + return window; + } + + public static void PumpDispatcher(Dispatcher dispatcher, DispatcherPriority priority) + => dispatcher.Invoke(priority, new Action(() => { })); + + public static void RunInSta(Action action) + { + Exception? capturedException = null; + using var completed = new ManualResetEventSlim(false); + + var thread = new Thread(() => + { + try + { + action(); + } + catch (Exception exception) + { + capturedException = exception; + } + finally + { + completed.Set(); + } + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + completed.Wait(); + thread.Join(); + + if (capturedException is not null) + ExceptionDispatchInfo.Capture(capturedException).Throw(); + } +} \ No newline at end of file From 5ebd9020fb3e54d5df6dea43308218e129332797 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 10 May 2026 15:10:51 +0100 Subject: [PATCH 31/34] Fixes and more tests --- .../Documents/LuaIntellisenseDocumentManager.cs | 8 +++++--- .../Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs index 03fb1a4da3..bf16120f2e 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs @@ -138,15 +138,17 @@ public IReadOnlyList GetSemanticTokens(string filePath) if (!_documents.TryGetValue(oldFilePath, out DocumentState? state)) return null; + // The host blocks rename-to-existing-path in normal flows. If an external rename still + // targets a tracked document, keep both states intact instead of overwriting the destination. + if (_documents.ContainsKey(newFilePath)) + return null; + string safeContent = content ?? state.Content; bool contentChanged = !string.Equals(state.Content, safeContent, StringComparison.Ordinal); LuaDocumentSnapshot? previousDocument = state.IsOpen ? CreateSnapshot(state) : null; _documents.Remove(oldFilePath); - if (_documents.ContainsKey(newFilePath)) - ClearCachedState(state); - state.FilePath = newFilePath; state.Uri = LuaLanguageServerPathHelper.CreateFileUri(newFilePath); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs index 44cb321be7..1eaedeed3c 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs @@ -65,6 +65,8 @@ public bool Start() try { + // .API/*.lua changes are already covered by the recursive Lua watcher. + // This watcher exists so creating, deleting, or renaming the .API directory itself is also observed. _apiDirectoryWatcher = CreateWatcher(".API", includeSubdirectories: false); _luaWatcher = CreateWatcher("*.lua", includeSubdirectories: true); _configWatcher = CreateWatcher(".luarc.*", includeSubdirectories: false); From e112972e940b428f5a571dcff063fce8afff004e Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 10 May 2026 15:28:54 +0100 Subject: [PATCH 32/34] Add more tests --- .../LuaIntellisenseDocumentManagerTests.cs | 32 ++++++++++++ .../LuaTextMateSyntaxHighlightingTests.cs | 26 ++++++++++ .../TombLib.Test/TextMateHighlightingTests.cs | 52 +++++++++++++++---- 3 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs diff --git a/TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs b/TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs new file mode 100644 index 0000000000..ca2d3f14d2 --- /dev/null +++ b/TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs @@ -0,0 +1,32 @@ +using TombIDE.ScriptingStudio.Services.LuaIntellisense; + +namespace TombLib.Test; + +[TestClass] +public class LuaIntellisenseDocumentManagerTests +{ + [TestMethod] + public void Rename_ReturnsNullAndPreservesTrackedDocuments_WhenDestinationIsAlreadyTracked() + { + var manager = new LuaIntellisenseDocumentManager(); + const string oldFilePath = @"C:\Workspace\Scripts\source.lua"; + const string newFilePath = @"C:\Workspace\Scripts\target.lua"; + + manager.Synchronize(oldFilePath, "return 1", acquireOpenReference: true); + manager.Synchronize(newFilePath, "return 2", acquireOpenReference: true); + + LuaDocumentRenameRequest? renameRequest = manager.Rename(oldFilePath, newFilePath, "return 1"); + + Assert.IsNull(renameRequest); + Assert.IsNotNull(manager.GetDocumentSnapshot(oldFilePath)); + + LuaDocumentSnapshot? destinationDocument = manager.GetDocumentSnapshot(newFilePath); + + Assert.IsNotNull(destinationDocument); + Assert.AreEqual("return 2", destinationDocument.Content); + Assert.AreEqual(1, destinationDocument.Version); + Assert.IsTrue(manager.TryClose(oldFilePath, out _)); + Assert.IsTrue(manager.TryClose(newFilePath, out LuaDocumentSnapshot? closedDestinationDocument)); + Assert.AreEqual("return 2", closedDestinationDocument.Content); + } +} \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs b/TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs index cd7702fdd6..f58a86794d 100644 --- a/TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs +++ b/TombLib/TombLib.Test/LuaTextMateSyntaxHighlightingTests.cs @@ -1,3 +1,4 @@ +using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Highlighting; using TombLib.Scripting.Highlighting; @@ -14,4 +15,29 @@ public void LoadFallbackHighlighting_ReturnsLuaDefinition() Assert.IsNotNull(highlighting); Assert.AreEqual("Lua", highlighting.Name); } + + [TestMethod] + public void TryInstall_AttachesTransformerAndDisposeRemovesIt() + { + WpfTestHelper.RunInSta(() => + { + var editor = new TextEditor + { + Text = "local value = 1" + }; + + int initialTransformerCount = editor.TextArea.TextView.LineTransformers.Count; + + bool installed = LuaTextMateSyntaxHighlighting.TryInstall(editor, out LuaTextMateInstallation? installation); + + Assert.IsTrue(installed); + Assert.IsNotNull(installation); + Assert.AreEqual(initialTransformerCount + 1, editor.TextArea.TextView.LineTransformers.Count); + + installation.Dispose(); + installation.Dispose(); + + Assert.AreEqual(initialTransformerCount, editor.TextArea.TextView.LineTransformers.Count); + }); + } } \ No newline at end of file diff --git a/TombLib/TombLib.Test/TextMateHighlightingTests.cs b/TombLib/TombLib.Test/TextMateHighlightingTests.cs index e51afcf805..f297249cc4 100644 --- a/TombLib/TombLib.Test/TextMateHighlightingTests.cs +++ b/TombLib/TombLib.Test/TextMateHighlightingTests.cs @@ -1,3 +1,5 @@ +using System; +using System.Collections.Generic; using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using TombLib.Scripting.Highlighting; @@ -64,20 +66,50 @@ public void Resolve_PrefersMoreSpecificBundledSelectorsOverBroaderParents() Assert.AreEqual("#FFD7B8FF", GetForegroundColor(style)); } - private static (int StartLineIndex, int RemovedLineCount, int InsertedLineCount) ApplyChangeAndGetInfo(string originalText, Action changeAction) + [TestMethod] + public void DocumentLineList_TracksInsertedAndReplacedLines() + { + var document = new TextDocument("alpha\r\nbeta"); + var lineList = new TextMateDocumentLineList(document); + + try { - var document = new TextDocument(originalText); - DocumentChangeEventArgs? change = null; + CollectionAssert.AreEqual(new[] { "alpha\r\n", "beta" }, GetSnapshotLines(lineList)); - document.Changed += (_, args) => change = args; - changeAction(document); + document.Insert(document.TextLength, "\r\ngamma"); - return TextMateDocumentLineList.GetChangeInfo(document, change!); - } + CollectionAssert.AreEqual(new[] { "alpha\r\n", "beta\r\n", "gamma" }, GetSnapshotLines(lineList)); + Assert.AreEqual(3, lineList.GetNumberOfLines()); - private static string GetForegroundColor(TextMateHighlightingStyle style) + int replacementOffset = document.Text.IndexOf("beta\r\ngamma", StringComparison.Ordinal); + document.Replace(replacementOffset, "beta\r\ngamma".Length, "delta"); + + CollectionAssert.AreEqual(new[] { "alpha\r\n", "delta" }, GetSnapshotLines(lineList)); + Assert.AreEqual(2, lineList.GetNumberOfLines()); + } + finally { - Assert.IsNotNull(style.Foreground); - return ((SolidColorBrush)style.Foreground).Color.ToString(); + lineList.Dispose(); } + } + + private static (int StartLineIndex, int RemovedLineCount, int InsertedLineCount) ApplyChangeAndGetInfo(string originalText, Action changeAction) + { + var document = new TextDocument(originalText); + DocumentChangeEventArgs? change = null; + + document.Changed += (_, args) => change = args; + changeAction(document); + + return TextMateDocumentLineList.GetChangeInfo(document, change!); + } + + private static string[] GetSnapshotLines(TextMateDocumentLineList lineList) + => [.. WpfTestHelper.GetPrivateField>(lineList, "_lineTexts")]; + + private static string GetForegroundColor(TextMateHighlightingStyle style) + { + Assert.IsNotNull(style.Foreground); + return ((SolidColorBrush)style.Foreground).Color.ToString(); + } } \ No newline at end of file From 2385ab6c0a7eea467829d1ea46f3de7240b8975f Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Sun, 10 May 2026 20:00:43 +0100 Subject: [PATCH 33/34] More features --- LuaLS_ScriptingStudio_Features_Plan.md | 361 ++++++++++++++++++ .../Bases/StudioBase.cs | 65 +++- .../Helpers/EditorNavigationHelper.cs | 110 ++++++ .../LuaStudio.Diagnostics.cs | 67 ++++ .../LuaStudio.Formatting.cs | 74 ++++ .../LuaStudio.Intellisense.cs | 55 ++- .../LuaStudio.Navigation.cs | 114 ++++++ .../LuaStudio.References.cs | 216 +++++++++++ .../LuaStudio.Rename.cs | 190 +++++++++ .../LuaStudio.WorkspaceEditHistory.cs | 115 ++++++ TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs | 60 ++- .../Objects/EditorNavigationLocation.cs | 19 + .../Objects/LuaDiagnosticListItem.cs | 15 + .../Objects/LuaReferenceGroup.cs | 25 ++ .../Objects/LuaReferenceListItem.cs | 15 + .../EditorNavigationHistoryService.cs | 131 +++++++ ...LanguageServerResponseParser.Formatting.cs | 23 ++ .../Client/ILuaLanguageServerClient.cs | 15 + .../Client/LuaLanguageServerClient.cs | 52 +++ ...uageServerIntellisenseProvider.Requests.cs | 125 ++++++ .../LuaLanguageServerIntellisenseProvider.cs | 15 + .../Services/LuaIntellisense/README.md | 7 + ...LanguageServerResponseParser.References.cs | 89 +++++ .../LuaLanguageServerResponseParser.Rename.cs | 148 +++++++ .../Services/LuaWorkspaceEditApplier.cs | 268 +++++++++++++ .../LuaWorkspaceEditHistoryService.cs | 88 +++++ .../LuaWorkspaceEditSelectionState.cs | 38 ++ .../ToolWindows/LuaDiagnostics.cs | 47 +++ .../ToolWindows/LuaReferencesResults.cs | 48 +++ .../ToolWindows/SearchResults.cs | 57 +-- .../ContextMenus/ClassicScript.xml | 1 + .../ContextMenus/GameFlowScript.xml | 1 + .../DocumentModePresets/ContextMenus/Lua.xml | 5 + .../ContextMenus/Tomb1Main.xml | 1 + .../MenuStrips/ClassicScript.xml | 1 + .../MenuStrips/GameFlowScript.xml | 1 + .../UI/DocumentModePresets/MenuStrips/Lua.xml | 7 + .../MenuStrips/Tomb1Main.xml | 1 + .../UI/StudioModePresets/MenuStrips/Lua.xml | 4 + .../UI/StudioModePresets/ToolStrips/Lua.xml | 3 + .../TombIDE.ScriptingStudio/UI/UICommand.cs | 7 + .../TombIDE.ScriptingStudio/UI/UIElement.cs | 1 + TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs | 5 + .../ViewModels/LuaDiagnosticsViewModel.cs | 194 ++++++++++ .../LuaReferencesResultsViewModel.cs | 72 ++++ .../Views/LuaDiagnosticsView.xaml | 79 ++++ .../Views/LuaDiagnosticsView.xaml.cs | 43 +++ .../Views/LuaReferencesResultsView.xaml | 43 +++ .../Views/LuaReferencesResultsView.xaml.cs | 41 ++ TombIDE/TombIDE.Shared/DefaultLayouts.cs | 19 + .../Resources/Localization/EN/TombIDE.xml | 33 +- .../Resources/Localization/Localization.cs | 31 ++ .../Resources/Localization/PL/TombIDE.xml | 33 +- TombIDE/TombIDE/Program.cs | 35 +- .../Objects/LuaDocumentEdit.cs | 30 ++ .../Objects/LuaDocumentRange.cs | 56 +++ .../Objects/LuaFormattingOptions.cs | 28 ++ .../Objects/LuaReferenceLocation.cs | 28 ++ .../Objects/LuaTextEdit.cs | 28 ++ .../Objects/LuaWorkspaceEdit.cs | 28 ++ .../Services/ILuaIntellisenseProvider.cs | 51 +++ .../TombLib.Scripting/Bases/TextEditorBase.cs | 116 +++--- .../LuaEditorCompletionWindowTests.cs | 15 + .../LuaEditorIntellisenseStateTests.cs | 15 + .../LuaLanguageServerClientTests.cs | 20 + ...LanguageServerIntellisenseProviderTests.cs | 90 +++++ .../LuaLanguageServerResponseParserTests.cs | 123 ++++++ 67 files changed, 3797 insertions(+), 144 deletions(-) create mode 100644 LuaLS_ScriptingStudio_Features_Plan.md create mode 100644 TombIDE/TombIDE.ScriptingStudio/Helpers/EditorNavigationHelper.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/LuaStudio.Diagnostics.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/LuaStudio.Formatting.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/LuaStudio.Navigation.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/LuaStudio.References.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/LuaStudio.Rename.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/LuaStudio.WorkspaceEditHistory.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Objects/EditorNavigationLocation.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Objects/LuaDiagnosticListItem.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceGroup.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceListItem.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/EditorNavigationHistoryService.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Formatting/LuaLanguageServerResponseParser.Formatting.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditApplier.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditHistoryService.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditSelectionState.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaDiagnostics.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaReferencesResults.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaDiagnosticsViewModel.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaReferencesResultsViewModel.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml create mode 100644 TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml.cs create mode 100644 TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml create mode 100644 TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentEdit.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentRange.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaFormattingOptions.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaReferenceLocation.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaTextEdit.cs create mode 100644 TombLib/TombLib.Scripting.Lua/Objects/LuaWorkspaceEdit.cs diff --git a/LuaLS_ScriptingStudio_Features_Plan.md b/LuaLS_ScriptingStudio_Features_Plan.md new file mode 100644 index 0000000000..8f4d160dbb --- /dev/null +++ b/LuaLS_ScriptingStudio_Features_Plan.md @@ -0,0 +1,361 @@ +# LuaLS / Scripting Studio Feature Plan + +Date: 2026-05-10. + +## Goal + +Add these Lua editor features in TombIDE Scripting Studio: + +- VSCode-like back / forward navigation across document, caret, and selection state. +- A dedicated diagnostics tool window for the active Lua document, with severity toggle filters. +- LuaLS Find References. +- LuaLS Rename Symbol. +- LuaLS document reformatting, exposed through the existing document cleanup command. + +This plan is written as an implementation handoff for the next agent. It is intentionally concrete and biased toward the smallest set of architectural changes that fit the current codebase. + +## Verified Starting Point + +- [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs) already owns Lua-specific editor UX and currently wires completion, hover, signature help, and definition navigation. +- [LuaEditor.Navigation](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs) already routes `F12` and `Ctrl+Click` into the definition-navigation controller, so definition jumps already have a single owner on the editor side. +- [LuaStudio.Intellisense](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs) is the current cross-document bridge. It opens Lua documents in the provider, applies diagnostics and semantic tokens, and performs the actual open-file jump for definitions. +- [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) currently exposes only completion, hover, definition, signature help, diagnostics, semantic tokens, and document lifecycle. References, rename, and formatting are not in the contract yet. +- [StudioBase](TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs) already owns command routing, dockable tool-window visibility, and the shared document command pipeline. +- [UICommand](TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs), [UIKeys](TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs), and the Lua menu/context XML files are the existing command-registration surface. +- [SearchResults](TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs) is a docked results window already, but it is tightly coupled to `FindReplaceEventArgs` and regex-match navigation. +- [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs) already raises `StatusChanged` on caret and selection changes, and stores diagnostics locally through `SetDiagnostics(...)`. +- [TextEditorDiagnostic](TombLib/TombLib.Scripting/Objects/TextEditorDiagnostic.cs) currently carries severity plus start/end offsets only. That is enough to build a current-document diagnostics list, but line/column text will need to be derived in the host UI. +- [TombIDE.ScriptingStudio.csproj](TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj) already has `UseWPF=true`, references `DarkUI.WPF`, and uses `ElementHost` elsewhere, so new WPF panes can be hosted inside existing `DarkToolWindow` shells. +- The visible `Reindent` command is currently routed through [StudioBase.HandleDocumentCommands](TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs) to [TextEditorBase.TidyCode](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs), which only trims ending whitespace. Lua reformatting must override this path instead of reusing the current base behavior. + +## Recommended Decisions + +- Keep cross-document navigation history in the Scripting Studio host, not in `LuaEditor`. The editor knows about caret and selection, but only the studio knows about tabs, file opening, tool-window jumps, and document lifetime. +- Add new LuaLS protocol features inside `TombIDE.ScriptingStudio/Services/LuaIntellisense` using the existing feature-sliced layout. Do not collapse them into one generic parser file. +- Build new front-end panes as `DarkToolWindow` plus `ElementHost` plus a DarkUI.WPF `UserControl`. That gives a WPF front-end while preserving the existing WinForms dock host. +- Do not force `SearchResults` to become a generic results shell in the first pass. Extract only the shared jump helper if needed. A dedicated references window is lower risk than untangling the existing find/replace tree. +- Reuse the existing `InputBoxWindow` shape for rename unless the first iteration truly needs rename preview. A dedicated rename-preview dialog can wait. +- Keep the `UICommand.Reindent` identifier for now and rename only the visible localization strings to `Reformat`. That avoids broad command-churn across shared menus and settings. +- Treat diagnostics filter buttons as `Errors`, `Warnings`, and `Messages`, where `Information` and `Hint` roll up into `Messages`. Internally, keep the original severity values intact. +- Keep format-on-save out of the first Lua slice. The explicit document command should land first so edit-application, caret preservation, and latency can be validated before wiring it into save flows. + +## Phase 1. Shared Location And Navigation Infrastructure + +### Objective + +Create a reusable location model and navigation-history service that every Lua jump can use. + +### Why First + +Definition jumps already exist, and diagnostics and references both need the same open-file-and-position behavior. Landing this first avoids three separate navigation implementations. + +### Work Items + +- Add new commands and shortcuts: + - `NavigateBack` mapped to `Alt+Left`. + - `NavigateForward` mapped to `Alt+Right`. + - `FindReferences` mapped to `Shift+F12`. + - `RenameSymbol` mapped to `F2` when a text editor has focus. +- Update: + - [UICommand](TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs) + - [UIKeys](TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs) + - [Lua document menu](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml) + - [Lua context menu](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml) + - [Lua studio menu](TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml) + - [EN localization](TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml) + - [PL localization](TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml) +- Introduce a small studio-owned location model, for example: + - `EditorNavigationLocation` with file path, caret offset, selection start, selection length, and optional preferred line for scroll restoration. +- Introduce a studio-owned history service, for example: + - `EditorNavigationHistoryService` with back stack, forward stack, and a suppression scope for programmatic jumps. +- Subscribe to `IEditorControl.StatusChanged` in the studio host for Lua editors and record debounced user movement when it represents a meaningful location change. +- Add a single host-side navigation method in `LuaStudio`, for example `NavigateToLocation(EditorNavigationLocation location, NavigationOrigin origin)`, and route all Lua jumps through it. +- Change [LuaStudio.NavigateToDefinition](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs) so definition navigation pushes the current location before opening the target location. +- Extract the target-file jump logic from [SearchResults](TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs) into a shared helper or callback so later tool windows can reuse it. + +### Done When + +- `Alt+Left` and `Alt+Right` work after `F12`, `Ctrl+Click`, and existing Search Results jumps. +- Programmatic jumps do not create duplicate history entries. +- Same-file caret and selection movement can be recorded without polluting the history on every cursor tick. + +### Validation + +- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` +- Manual check: + - Jump to a definition in another file. + - Jump back. + - Jump forward. + - Select text, move caret materially, and verify history behaves predictably. + +## Phase 2. Active-Document Diagnostics Tool Window + +### Objective + +Add a dedicated diagnostics pane for the current Lua document, with three severity toggle buttons and jump-to-diagnostic behavior. + +### Recommended UI Shape + +- New `DarkToolWindow` hosted in the dock panel. +- Inside it, host a DarkUI.WPF `UserControl` through `ElementHost`. +- Use DarkUI.WPF `ToggleButton` controls for `Errors`, `Warnings`, and `Messages`. +- Use a WPF `DataGrid` or `ListBox` for rows. Prefer `DataGrid` because the row shape is tabular: severity, line, column, message. + +### Work Items + +- Add a new public tool-window field on `LuaStudio`, for example `LuaDiagnostics`, so it participates in the normal dock-layout serialization and View menu handling. +- Create new files under `TombIDE.ScriptingStudio`, for example: + - `ToolWindows/LuaDiagnostics.cs` + - `Views/LuaDiagnosticsView.xaml` + - `Views/LuaDiagnosticsView.xaml.cs` + - `ViewModels/LuaDiagnosticsViewModel.cs` + - `Objects/LuaDiagnosticListItem.cs` +- Populate the view model from the active Lua editor only. The source of truth should remain `ILuaIntellisenseProvider.GetDiagnostics(filePath)` plus the active editor document for line/column/message projection. +- Project each `TextEditorDiagnostic` into a row model with: + - severity + - line + - column + - message + - start offset + - end offset +- Refresh the pane when: + - the selected tab changes + - diagnostics update for the active file + - the current Lua editor changes locally +- On local edit, clear or mark pending diagnostics for the active file immediately instead of displaying known-stale results until the delayed provider refresh arrives. +- Double-click or press `Enter` on a row to navigate through the shared navigation service from Phase 1. +- Add a View menu entry and default bottom-dock placement near Search Results. + +### Done When + +- The pane always shows diagnostics for the active Lua document only. +- `Errors`, `Warnings`, and `Messages` toggles filter rows live. +- Jumping from the diagnostics list records history correctly. +- Switching to a non-Lua tab clears or disables the pane instead of leaving stale Lua results on screen. + +### Validation + +- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` +- Manual check: + - Open a Lua file with multiple diagnostics. + - Toggle each severity filter. + - Edit the document and verify stale rows clear quickly. + - Double-click a row and jump back with `Alt+Left`. + +## Phase 3. LuaLS Find References + +### Objective + +Add LuaLS references requests and surface the results in a dedicated docked results pane. + +### Recommended UI Shape + +- Use a dedicated references tool window instead of reusing the current Search Results tool window. +- Keep the shell pattern consistent with diagnostics: `DarkToolWindow` plus `ElementHost` plus WPF `UserControl`. +- Group results by file and show line/column plus preview text. + +### Work Items + +- Extend [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) with a new async references API. +- Add new DTOs under `TombLib.Scripting.Lua/Objects`, for example: + - `LuaReferenceLocation` + - `LuaDocumentRange` +- Add provider support inside `TombIDE.ScriptingStudio/Services/LuaIntellisense`: + - new request method in the provider partials + - new response parser under a new `References/` folder or under `Navigation/` if kept small + - capability detection during initialization +- Add a studio command handler in `LuaStudio` for `Shift+F12` and context-menu invocation. +- Create a new results pane, for example: + - `ToolWindows/LuaReferencesResults.cs` + - `Views/LuaReferencesResultsView.xaml` + - `ViewModels/LuaReferencesResultsViewModel.cs` +- Model the rows with enough information to jump directly: + - file path + - line + - column + - preview text + - start/end offsets where available +- Prefer file grouping plus count headers so the result list stays readable in multi-file workspaces. +- Route all activation through the Phase 1 navigation service. +- If LuaLS does not advertise references support, disable the command cleanly instead of failing at runtime. + +### Done When + +- `Shift+F12` from a valid symbol opens a references pane and groups matches by file. +- Double-clicking a result jumps to the location and back/forward navigation works afterward. +- Re-running references replaces the previous Lua references result set cleanly. + +### Validation + +- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` +- Targeted test pass if provider parser changes add or update testable seams under `TombLib.Test`. +- Manual check: + - local variable references in one file + - shared symbol references across multiple files + - no-result case + +## Phase 4. LuaLS Rename Symbol + +### Objective + +Add symbol rename via LuaLS and apply the returned workspace edits safely across open and unopened Lua files. + +### Recommended UI Shape + +- Start with the existing [InputBoxWindow](TombLib/TombLib.Forms/Views/InputBoxWindow.xaml) visual pattern. +- Reuse `InputBoxWindowViewModel` if the first slice only needs title, label, and new name text. +- Only create a dedicated rename dialog if a preview list or extra validation text becomes necessary. + +### Work Items + +- Extend [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) with a rename API. +- Add workspace-edit DTOs, for example: + - `LuaWorkspaceEdit` + - `LuaDocumentEdit` + - `LuaTextEdit` +- Add LuaLS rename request handling under `TombIDE.ScriptingStudio/Services/LuaIntellisense`: + - request method + - parser for `WorkspaceEdit` + - capability detection +- Add a studio-owned edit applier, for example `LuaWorkspaceEditApplier`, that: + - applies edits in descending offset order per file + - uses open editors when available + - opens files through `EditorTabControl` when needed + - leaves affected files dirty instead of silently saving them + - preserves the previously selected tab when practical +- Add a host-side command handler for `F2` when a Lua editor is focused. +- Seed the rename box from the current selection or the identifier at the caret. +- If the server returns no edits, show a non-blocking message and leave the editor untouched. +- If the server refuses the rename, surface the error cleanly through DarkUI message UI. +- After edits apply, refresh provider-tracked document state so diagnostics, semantic tokens, references, and future rename requests remain aligned. +- Keep file-explorer `F2` rename behavior intact when the editor does not have focus. + +### Done When + +- `F2` on a renameable Lua symbol opens a DarkUI.WPF-style prompt and applies changes across the workspace. +- Open tabs update in place and unopened files are updated safely. +- Back/forward history still works after the rename operation. +- Rename failures and unsupported cases are visible and non-destructive. + +### Validation + +- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` +- Manual check: + - rename a local variable in one file + - rename a shared symbol across files + - cancel rename + - invalid or unsupported rename + +## Phase 5. LuaLS Reformat Command + +### Objective + +Replace the current Lua `Reindent` behavior with provider-backed Lua formatting while keeping the existing shared command slot. + +### Work Items + +- Extend [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) with a document-formatting API. +- Add formatting request support under `TombIDE.ScriptingStudio/Services/LuaIntellisense`: + - request method + - parser for returned text edits + - capability detection +- Reuse the workspace-edit application machinery from Phase 4 for single-document formatting edits. +- Override the Lua document-command path in `LuaStudio` so `UICommand.Reindent` does this instead: + - when the current editor is `LuaEditor` and the provider supports formatting, request formatting edits and apply them + - when the provider is unavailable, disable the command or show a warning instead of silently falling back to trim-only behavior +- Change visible menu text from `Reindent` to `Reformat` in localization files. Keep the existing command and configuration identifiers for now. +- Decide explicitly whether the existing visible `ReindentOnSave` option should also be renamed to `Reformat on Save`. Recommended first slice: rename the visible text only if the save path is still intentionally trim-only across non-Lua editors; otherwise defer the label change to avoid implying Lua format-on-save before it exists. +- Keep range formatting out of scope for the first pass. + +### Done When + +- The Lua document menu command reformats a Lua document through LuaLS. +- Caret and selection are preserved well enough for normal editing. +- The visible UI says `Reformat` instead of `Reindent`. +- Non-Lua editors keep their current behavior. + +### Validation + +- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` +- Manual check: + - reformat a messy Lua file + - verify edits are applied once + - verify the editor state remains usable afterward + +## Phase 6. Polish, Layout, And Regression Pass + +### Work Items + +- Add default layout entries for the new diagnostics and references panes if they should participate in restored layouts from first launch. +- Verify View menu checked states and serialization keys for every new tool window. +- Add or update documentation notes in the LuaLS service README if ownership shifts or new folders are introduced. +- Update tests in `TombLib.Test` for any provider/parser contracts that change. +- Re-run a full manual regression pass over: + - completion + - hover + - signature help + - definition navigation + - diagnostics refresh + - semantic token stability after rename and reformat + +### Validation + +- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` +- Broader test pass: `dotnet test .\TombLib\TombLib.Test\TombLib.Test.csproj` + +## Suggested File Touch Map + +### Command And Menu Surface + +- [TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs](TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs) +- [TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs](TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs) +- [TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml) +- [TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml) +- [TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml](TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml) +- [TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml](TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml) +- [TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml](TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml) + +### Host / Studio Side + +- [TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs](TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs) +- [TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs) +- [TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs](TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs) +- [TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs) +- [TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs](TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs) + +### New Host Files Likely Needed + +- `TombIDE/TombIDE.ScriptingStudio/Objects/EditorNavigationLocation.cs` +- `TombIDE/TombIDE.ScriptingStudio/Services/EditorNavigationHistoryService.cs` +- `TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditApplier.cs` +- `TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaDiagnostics.cs` +- `TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaReferencesResults.cs` +- `TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml` +- `TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml` +- `TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaDiagnosticsViewModel.cs` +- `TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaReferencesResultsViewModel.cs` + +### Provider / Contract Side + +- [TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) +- `TombLib/TombLib.Scripting.Lua/Objects/LuaReferenceLocation.cs` +- `TombLib/TombLib.Scripting.Lua/Objects/LuaWorkspaceEdit.cs` +- `TombLib/TombLib.Scripting.Lua/Objects/LuaTextEdit.cs` +- [TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs) +- New service folders under [TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense) + +## Not In Scope For The First Slice + +- Code actions and quick fixes. +- Rename preview with per-file accept/reject UI. +- Range formatting. +- Workspace-wide diagnostics across every Lua file. +- Generalizing every existing results surface into a single mega-control. + +## Agent Execution Notes + +- Implement one phase at a time and validate it before widening scope. +- Do not start rename-edit application before the shared navigation and location model exist. +- Do not change non-Lua editor behavior unless a shared command surface absolutely requires it. +- Prefer small, reversible refactors in the studio host over broad shell rewrites. +- If a WPF result pane adds too much friction inside the dock host, keep the `DarkToolWindow` shell and debug the `ElementHost` bridge first instead of falling back immediately to a second WinForms tree/grid implementation. diff --git a/TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs b/TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs index c4bf0fe0a2..05b3ddc76f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs @@ -108,6 +108,8 @@ public string ScriptRootDirectoryPath protected ToolStripMenuItem ReferenceBrowserViewItem; protected ToolStripMenuItem CompilerLogsViewItem; protected ToolStripMenuItem SearchResultsViewItem; + protected ToolStripMenuItem LuaDiagnosticsViewItem; + protected ToolStripMenuItem LuaReferencesResultsViewItem; protected ToolStripMenuItem StatusStripViewItem; #endregion Fields @@ -125,7 +127,7 @@ public StudioBase(string scriptRootDirectoryPath, string engineDirectoryPath) InitializeFindReplaceForm(); CompilerLogs = new CompilerLogs(); - SearchResults = new SearchResults(EditorTabControl); + SearchResults = new SearchResults(NavigateToSearchResult); IDE.Instance.IDEEventRaised += OnIDEEventRaised; @@ -218,6 +220,7 @@ private void InitializeDockPanel() // Apply the current layout DockPanel.RestoreDockPanelState(DockPanelState, FindDockContentByKey); + OnDockPanelLayoutRestored(); ApplyMessageFilters(); } @@ -236,6 +239,8 @@ private void InitializeFrequentlyAccessedMenuStripItems() ReferenceBrowserViewItem = MenuStrip.FindItem(UICommand.ReferenceBrowser) as ToolStripMenuItem; CompilerLogsViewItem = MenuStrip.FindItem(UICommand.CompilerLogs) as ToolStripMenuItem; SearchResultsViewItem = MenuStrip.FindItem(UICommand.SearchResults) as ToolStripMenuItem; + LuaDiagnosticsViewItem = MenuStrip.FindItem(UICommand.LuaDiagnostics) as ToolStripMenuItem; + LuaReferencesResultsViewItem = MenuStrip.FindItem(UICommand.LuaReferencesResults) as ToolStripMenuItem; StatusStripViewItem = MenuStrip.FindItem(UICommand.StatusStrip) as ToolStripMenuItem; } @@ -295,6 +300,21 @@ protected virtual void OnToolStripItemClicked(UICommand e) HandleDocumentCommands(e); } + protected virtual void OnDockPanelLayoutRestored() + { } + + protected virtual bool CanExecuteUndo() + => CurrentEditor is not null && CurrentEditor.CanUndo; + + protected virtual bool CanExecuteRedo() + => CurrentEditor is not null && CurrentEditor.CanRedo; + + protected virtual void ExecuteUndo() + => CurrentEditor?.Undo(); + + protected virtual void ExecuteRedo() + => CurrentEditor?.Redo(); + #endregion Virtual region #region Abstract region @@ -354,6 +374,23 @@ private void Editor_ContentChangedWorkerRunCompleted(object sender, EventArgs e) private void TextEditor_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) { + if (System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Alt) + { + if (e.Key == System.Windows.Input.Key.Left) + { + OnToolStripItemClicked(UICommand.NavigateBack); + e.Handled = true; + return; + } + + if (e.Key == System.Windows.Input.Key.Right) + { + OnToolStripItemClicked(UICommand.NavigateForward); + e.Handled = true; + return; + } + } + if ((System.Windows.Input.Keyboard.Modifiers == System.Windows.Input.ModifierKeys.Control) && (e.Key == System.Windows.Input.Key.F || e.Key == System.Windows.Input.Key.H)) FindReplaceForm.Show(this, (CurrentEditor as TextEditorBase).SelectedText); @@ -424,14 +461,14 @@ protected void UpdateUI() protected void UpdateUndoRedoSaveStates() { // Undo buttons - UndoMenuItem.Enabled = CurrentEditor != null && CurrentEditor.CanUndo; + UndoMenuItem.Enabled = CanExecuteUndo(); UndoMenuItem.Text = UndoMenuItem.Enabled ? Strings.Default.Undo : Strings.Default.CantUndo; UndoToolStripButton.Enabled = UndoMenuItem.Enabled; UndoToolStripButton.ToolTipText = UndoMenuItem.Text; // Redo buttons - RedoMenuItem.Enabled = CurrentEditor != null && CurrentEditor.CanRedo; + RedoMenuItem.Enabled = CanExecuteRedo(); RedoMenuItem.Text = RedoMenuItem.Enabled ? Strings.Default.Redo : Strings.Default.CantRedo; RedoToolStripButton.Enabled = RedoMenuItem.Enabled; @@ -467,8 +504,8 @@ private void HandleGlobalCommands(UICommand command) case UICommand.Exit: IDE.Instance.RequestProgramClose(); break; // Edit - case UICommand.Undo: CurrentEditor?.Undo(); break; - case UICommand.Redo: CurrentEditor?.Redo(); break; + case UICommand.Undo: ExecuteUndo(); break; + case UICommand.Redo: ExecuteRedo(); break; case UICommand.Cut: CurrentEditor?.Cut(); break; case UICommand.Copy: CurrentEditor?.Copy(); break; case UICommand.Paste: CurrentEditor?.Paste(); break; @@ -506,6 +543,7 @@ protected virtual void HandleDocumentCommands(UICommand command) case UICommand.SpacesToTabs: textEditor.ConvertSpacesToTabs(); break; case UICommand.Reindent: textEditor.TidyCode(); break; case UICommand.TrimWhiteSpace: textEditor.TidyCode(true); break; + case UICommand.ToggleComment: textEditor.ToggleCommentLines(); break; case UICommand.CommentOut: textEditor.CommentOutLines(); break; case UICommand.Uncomment: textEditor.UncommentLines(); break; case UICommand.ToggleBookmark: textEditor.ToggleBookmark(); break; @@ -532,6 +570,23 @@ protected virtual void HandleDocumentCommands(UICommand command) } } + protected virtual void NavigateToSearchResult(string filePath, FindReplaceItem item) + { + if (string.IsNullOrWhiteSpace(filePath)) + return; + + EditorTabControl.OpenFile(filePath); + + if (CurrentEditor is not TextEditorBase textEditor) + return; + + if (!EditorNavigationHelper.TryCreateSearchResultLocation(textEditor, filePath, item, out EditorNavigationLocation? location) + || location is null) + return; + + EditorNavigationHelper.ApplyLocation(textEditor, location.Value); + } + protected void ToggleItemVisibility(UICommand command) { Control control = GetControlByKey(command.ToString()); diff --git a/TombIDE/TombIDE.ScriptingStudio/Helpers/EditorNavigationHelper.cs b/TombIDE/TombIDE.ScriptingStudio/Helpers/EditorNavigationHelper.cs new file mode 100644 index 0000000000..fd18a9b735 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Helpers/EditorNavigationHelper.cs @@ -0,0 +1,110 @@ +#nullable enable + +using System; +using System.Text.RegularExpressions; +using ICSharpCode.AvalonEdit.Document; +using TombIDE.ScriptingStudio.Objects; +using TombLib.Scripting.Bases; +using TombLib.Scripting.Lua.Objects; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.Helpers; + +internal static class EditorNavigationHelper +{ + public static EditorNavigationLocation CreateLocation(TextEditorBase textEditor) + => new( + textEditor.FilePath, + textEditor.CaretOffset, + textEditor.SelectionStart, + textEditor.SelectionLength, + textEditor.CurrentRow); + + public static EditorNavigationLocation CreateDefinitionLocation( + TextEditorBase textEditor, + string filePath, + int lineNumber, + int columnNumber) + { + int offset = GetOffset(textEditor, lineNumber, columnNumber); + + return new EditorNavigationLocation(filePath, offset, offset, 0, lineNumber); + } + + public static EditorNavigationLocation CreateRangeLocation( + TextEditorBase textEditor, + string filePath, + LuaDocumentRange range) + { + int startOffset = GetOffset(textEditor, range.StartLineNumber, range.StartColumnNumber); + int endOffset = GetOffset(textEditor, range.EndLineNumber, range.EndColumnNumber); + int selectionLength = Math.Max(0, endOffset - startOffset); + + return new EditorNavigationLocation(filePath, startOffset, startOffset, selectionLength, range.StartLineNumber); + } + + public static void ApplyLocation(TextEditorBase textEditor, EditorNavigationLocation location) + { + int documentLength = textEditor.Document.TextLength; + int selectionStart = Math.Max(0, Math.Min(location.SelectionStart, documentLength)); + int selectionLength = Math.Max(0, Math.Min(location.SelectionLength, documentLength - selectionStart)); + int caretOffset = Math.Max(0, Math.Min(location.CaretOffset, documentLength)); + + textEditor.Focus(); + textEditor.CaretOffset = caretOffset; + textEditor.Select(selectionStart, selectionLength); + textEditor.ScrollToLine(GetPreferredLine(textEditor, location, selectionStart, caretOffset)); + } + + public static bool TryCreateSearchResultLocation( + TextEditorBase textEditor, + string filePath, + FindReplaceItem item, + out EditorNavigationLocation? location) + { + location = null; + + if (item.LineNumber < 1 || item.LineNumber > textEditor.Document.LineCount) + return false; + + DocumentLine line = textEditor.Document.GetLineByNumber(item.LineNumber); + string lineText = textEditor.Document.GetText(line.Offset, line.Length); + MatchCollection matches = Regex.Matches(lineText, item.MatchSegmentText); + + if (item.MatchSegmentIndex < 0 || item.MatchSegmentIndex >= matches.Count) + { + location = new EditorNavigationLocation(filePath, line.Offset, line.Offset, 0, line.LineNumber); + return true; + } + + Match match = matches[item.MatchSegmentIndex]; + int selectionStart = line.Offset + match.Index; + + location = new EditorNavigationLocation(filePath, selectionStart, selectionStart, match.Length, line.LineNumber); + return true; + } + + private static int GetPreferredLine( + TextEditorBase textEditor, + EditorNavigationLocation location, + int selectionStart, + int caretOffset) + { + if (location.PreferredLine is int preferredLine) + return Math.Max(1, Math.Min(preferredLine, textEditor.Document.LineCount)); + + int offset = selectionStart > 0 || location.SelectionLength > 0 + ? selectionStart + : caretOffset; + + return textEditor.Document.GetLineByOffset(offset).LineNumber; + } + + private static int GetOffset(TextEditorBase textEditor, int lineNumber, int columnNumber) + { + int safeLineNumber = Math.Max(1, Math.Min(lineNumber, textEditor.Document.LineCount)); + DocumentLine documentLine = textEditor.Document.GetLineByNumber(safeLineNumber); + int safeColumnNumber = Math.Max(1, Math.Min(columnNumber, documentLine.Length + 1)); + return documentLine.Offset + safeColumnNumber - 1; + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Diagnostics.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Diagnostics.cs new file mode 100644 index 0000000000..d0e4400f55 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Diagnostics.cs @@ -0,0 +1,67 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.ScriptingStudio.ToolWindows; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio; + +public sealed partial class LuaStudio +{ + public LuaDiagnostics LuaDiagnostics = null!; + + private void InitializeLuaDiagnostics() + { + LuaDiagnostics = new LuaDiagnostics(NavigateToDiagnostic); + } + + private void EditorTabControl_LuaSelectedIndexChanged(object? sender, EventArgs e) + { + RefreshLuaDiagnosticsView(); + UpdateLuaFeatureCommandAvailability(); + } + + private void LuaEditor_TextChanged(object? sender, EventArgs e) + { + InvalidateWorkspaceEditHistory(); + + if (!ReferenceEquals(sender, CurrentEditor)) + return; + + RefreshLuaDiagnosticsView(isPending: true); + } + + private void RefreshLuaDiagnosticsView(bool isPending = false, IReadOnlyList? diagnostics = null) + { + if (CurrentEditor is not LuaEditor editor) + { + LuaDiagnostics.ShowNoActiveDocument(); + return; + } + + if (isPending) + { + LuaDiagnostics.ShowPending(); + return; + } + + LuaDiagnostics.ShowDiagnostics( + editor.FilePath, + editor.Document, + diagnostics ?? _intellisenseProvider.GetDiagnostics(editor.FilePath)); + } + + private void NavigateToDiagnostic(LuaDiagnosticListItem diagnostic) + => NavigateToLocation( + diagnostic.FilePath, + NavigationOrigin.Diagnostics, + _ => new EditorNavigationLocation( + diagnostic.FilePath, + diagnostic.StartOffset, + diagnostic.StartOffset, + Math.Max(0, diagnostic.EndOffset - diagnostic.StartOffset), + diagnostic.LineNumber)); +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Formatting.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Formatting.cs new file mode 100644 index 0000000000..50eee0d4a3 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Formatting.cs @@ -0,0 +1,74 @@ +#nullable enable + +using DarkUI.Forms; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using TombIDE.ScriptingStudio.Services; +using TombIDE.Shared; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio; + +public sealed partial class LuaStudio +{ + private async Task ReformatDocumentAsync() + { + if (CurrentEditor is not LuaEditor editor) + return; + + if (!_intellisenseProvider.SupportsFormatting) + { + DarkMessageBox.Show(this, + Strings.Default.LuaReformatUnsupported, + Strings.Default.Reindent, + MessageBoxButtons.OK, + MessageBoxIcon.Information); + return; + } + + try + { + LuaFormattingOptions formattingOptions = CreateFormattingOptions(editor); + IReadOnlyList textEdits = await _intellisenseProvider + .FormatDocumentAsync(editor.FilePath, editor.Text, formattingOptions) + .ConfigureAwait(true); + + if (textEdits.Count == 0) + return; + + LuaWorkspaceEdit workspaceEdit = new([ + new LuaDocumentEdit(editor.FilePath, textEdits) + ]); + + LuaWorkspaceEditSelectionState selectionState = LuaWorkspaceEditSelectionState.Capture(editor); + LuaWorkspaceEditTransaction transaction = _workspaceEditApplier.Apply(workspaceEdit, selectionState); + + if (!transaction.HasChanges) + return; + + PushWorkspaceEditTransaction(transaction); + HandleWorkspaceDocumentsChanged(transaction.DocumentChanges.Select(documentChange => documentChange.FilePath)); + } + catch (OperationCanceledException) + { + // Ignore canceled formatting requests. + } + catch (Exception ex) + { + DarkMessageBox.Show(this, ex.Message, Strings.Default.Reindent, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private static LuaFormattingOptions CreateFormattingOptions(LuaEditor editor) + { + int tabSize = editor.Options.IndentationSize > 0 + ? editor.Options.IndentationSize + : 4; + + return new LuaFormattingOptions(tabSize, editor.Options.ConvertTabsToSpaces); + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 53ea336d23..090468ad9c 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.IO; using System.Windows.Forms; +using TombIDE.ScriptingStudio.Helpers; using TombIDE.ScriptingStudio.Objects; using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombLib.Scripting.Bases; @@ -26,6 +27,8 @@ private void HookLuaIntellisense() { EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; EditorTabControl.FileOpened += EditorTabControl_LuaFileOpened; + EditorTabControl.SelectedIndexChanged -= EditorTabControl_LuaSelectedIndexChanged; + EditorTabControl.SelectedIndexChanged += EditorTabControl_LuaSelectedIndexChanged; EditorTabControl.DocumentRenamed -= EditorTabControl_DocumentRenamed; EditorTabControl.DocumentRenamed += EditorTabControl_DocumentRenamed; @@ -41,11 +44,16 @@ private void HookLuaIntellisense() languageServerProvider.WorkspaceWatcherFailed -= IntellisenseProvider_WorkspaceWatcherFailed; languageServerProvider.WorkspaceWatcherFailed += IntellisenseProvider_WorkspaceWatcherFailed; } + + UpdateLuaFeatureCommandAvailability(); } private void DisposeLuaIntellisense() { + CancelPendingReferenceRequest(); + EditorTabControl.FileOpened -= EditorTabControl_LuaFileOpened; + EditorTabControl.SelectedIndexChanged -= EditorTabControl_LuaSelectedIndexChanged; EditorTabControl.DocumentRenamed -= EditorTabControl_DocumentRenamed; _intellisenseProvider.DiagnosticsUpdated -= IntellisenseProvider_DiagnosticsUpdated; _intellisenseProvider.SemanticTokensUpdated -= IntellisenseProvider_SemanticTokensUpdated; @@ -66,13 +74,13 @@ private ILuaIntellisenseProvider CreateLuaIntellisenseProvider() if (string.IsNullOrWhiteSpace(executablePath)) { // LuaLS is shipped with TombIDE; if the bundled binary is missing the user has no way - // of knowing why diagnostics, completion and definition lookups silently stop working. + // of knowing why diagnostics, completion, definition and references silently stop working. // Log a warning and surface a single non-blocking notification so the failure is visible. - Log.Warn("Bundled Lua language server was not found; Lua IntelliSense (diagnostics, completion, hover, go-to-definition) will be unavailable for this session."); + Log.Warn("Bundled Lua language server was not found; Lua IntelliSense (diagnostics, completion, hover, go-to-definition and find references) will be unavailable for this session."); MessageBox.Show(this, "The bundled Lua language server (LuaLS) could not be located.\n\n" + - "Lua IntelliSense - including diagnostics, completion, hover and go-to-definition - will be unavailable for this session.\n\n" + + "Lua IntelliSense - including diagnostics, completion, hover, go-to-definition and find references - will be unavailable for this session.\n\n" + "Reinstall TombIDE to restore the bundled language server.", "Lua IntelliSense unavailable", MessageBoxButtons.OK, @@ -90,12 +98,18 @@ private void EditorTabControl_LuaFileOpened(object? sender, EventArgs e) editor.IntellisenseProvider = _intellisenseProvider; editor.DefinitionNavigationRequested -= NavigateToDefinition; editor.DefinitionNavigationRequested += NavigateToDefinition; + editor.StatusChanged -= LuaEditor_StatusChanged; + editor.StatusChanged += LuaEditor_StatusChanged; + editor.TextChanged -= LuaEditor_TextChanged; + editor.TextChanged += LuaEditor_TextChanged; editor.TextChangedDelayed -= LuaEditor_TextChangedDelayed; editor.TextChangedDelayed += LuaEditor_TextChangedDelayed; _intellisenseProvider.OpenDocument(editor.FilePath, editor.Text); ApplyDiagnosticsToEditor(editor, _intellisenseProvider.GetDiagnostics(editor.FilePath)); ApplySemanticTokensToEditor(editor, _intellisenseProvider.GetSemanticTokens(editor.FilePath)); + RefreshLuaDiagnosticsView(); + UpdateLuaFeatureCommandAvailability(); } private void LuaEditor_TextChangedDelayed(object? sender, EventArgs e) @@ -121,6 +135,9 @@ private void EditorTabControl_DocumentRenamed(object? sender, DocumentRenamedEve return; _intellisenseProvider.RenameDocument(e.OldFilePath, e.NewFilePath, editor.Text); + + if (ReferenceEquals(CurrentEditor, editor)) + RefreshLuaDiagnosticsView(); } private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyList diagnostics) @@ -136,6 +153,14 @@ private void IntellisenseProvider_DiagnosticsUpdated(string filePath, IReadOnlyL if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) ApplyDiagnosticsToEditor(editor, diagnostics); } + + if (CurrentEditor is LuaEditor currentEditor + && string.Equals(currentEditor.FilePath, filePath, StringComparison.OrdinalIgnoreCase)) + { + RefreshLuaDiagnosticsView(diagnostics: diagnostics); + } + + UpdateLuaFeatureCommandAvailability(); } private void IntellisenseProvider_SemanticTokensUpdated(string filePath, IReadOnlyList semanticTokens) @@ -151,6 +176,8 @@ private void IntellisenseProvider_SemanticTokensUpdated(string filePath, IReadOn if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor editor) ApplySemanticTokensToEditor(editor, semanticTokens); } + + UpdateLuaFeatureCommandAvailability(); } private void IntellisenseProvider_StartupFailed(LuaLanguageServerStartupFailure failure) @@ -194,20 +221,14 @@ private void NavigateToDefinition(LuaDefinitionLocation definitionLocation) if (definitionLocation is null || string.IsNullOrWhiteSpace(definitionLocation.FilePath) || !File.Exists(definitionLocation.FilePath)) return; - EditorTabControl.OpenFile(definitionLocation.FilePath); - - if (CurrentEditor is not TextEditorBase editor || editor.Document.LineCount == 0) - return; - - int lineNumber = Math.Max(1, Math.Min(definitionLocation.LineNumber, editor.Document.LineCount)); - DocumentLine documentLine = editor.Document.GetLineByNumber(lineNumber); - int columnNumber = Math.Max(1, Math.Min(definitionLocation.ColumnNumber, documentLine.Length + 1)); - int offset = documentLine.Offset + columnNumber - 1; - - editor.Focus(); - editor.CaretOffset = offset; - editor.Select(offset, 0); - editor.ScrollToLine(lineNumber); + NavigateToLocation( + definitionLocation.FilePath, + NavigationOrigin.Definition, + editor => EditorNavigationHelper.CreateDefinitionLocation( + editor, + definitionLocation.FilePath, + definitionLocation.LineNumber, + definitionLocation.ColumnNumber)); } private static void ApplyDiagnosticsToEditor(LuaEditor editor, IReadOnlyList diagnostics) diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Navigation.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Navigation.cs new file mode 100644 index 0000000000..c2950235f7 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Navigation.cs @@ -0,0 +1,114 @@ +#nullable enable + +using System; +using System.IO; +using TombIDE.ScriptingStudio.Helpers; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.ScriptingStudio.Services; +using TombLib.Scripting.Bases; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio; + +public sealed partial class LuaStudio +{ + private readonly EditorNavigationHistoryService _navigationHistory = new(); + + private enum NavigationOrigin + { + Definition, + Diagnostics, + References, + SearchResults, + HistoryBack, + HistoryForward + } + + private void LuaEditor_StatusChanged(object? sender, EventArgs e) + { + if (sender is not LuaEditor editor) + return; + + _navigationHistory.Observe(EditorNavigationHelper.CreateLocation(editor)); + } + + private void NavigateBack() + { + if (TryGetCurrentNavigationLocation() is not EditorNavigationLocation currentLocation) + return; + + if (!_navigationHistory.TryNavigateBack(currentLocation, out EditorNavigationLocation? targetLocation) + || targetLocation is null) + return; + + NavigateToLocation( + targetLocation.Value.FilePath, + NavigationOrigin.HistoryBack, + _ => targetLocation.Value); + } + + private void NavigateForward() + { + if (TryGetCurrentNavigationLocation() is not EditorNavigationLocation currentLocation) + return; + + if (!_navigationHistory.TryNavigateForward(currentLocation, out EditorNavigationLocation? targetLocation) + || targetLocation is null) + return; + + NavigateToLocation( + targetLocation.Value.FilePath, + NavigationOrigin.HistoryForward, + _ => targetLocation.Value); + } + + private EditorNavigationLocation? TryGetCurrentNavigationLocation() + { + if (CurrentEditor is not TextEditorBase textEditor || string.IsNullOrWhiteSpace(textEditor.FilePath)) + return null; + + return EditorNavigationHelper.CreateLocation(textEditor); + } + + private void NavigateToLocation( + string filePath, + NavigationOrigin origin, + Func locationFactory, + EditorNavigationLocation? sourceLocation = null) + { + if (string.IsNullOrWhiteSpace(filePath) || !File.Exists(filePath)) + return; + + EditorNavigationLocation? currentLocation = sourceLocation ?? TryGetCurrentNavigationLocation(); + + using IDisposable suppression = _navigationHistory.SuppressRecording(); + + EditorTabControl.OpenFile(filePath); + + if (CurrentEditor is not TextEditorBase textEditor) + return; + + EditorNavigationLocation? targetLocation = locationFactory(textEditor); + if (targetLocation is null) + return; + + if (origin is NavigationOrigin.Definition or NavigationOrigin.Diagnostics or NavigationOrigin.References or NavigationOrigin.SearchResults + && currentLocation is EditorNavigationLocation source + && !source.IsEquivalentTo(targetLocation.Value)) + { + _navigationHistory.RecordProgrammaticJump(source, targetLocation.Value); + } + + EditorNavigationHelper.ApplyLocation(textEditor, targetLocation.Value); + _navigationHistory.SetCurrentLocation(EditorNavigationHelper.CreateLocation(textEditor)); + } + + protected override void NavigateToSearchResult(string filePath, FindReplaceItem item) + => NavigateToLocation( + filePath, + NavigationOrigin.SearchResults, + textEditor => EditorNavigationHelper.TryCreateSearchResultLocation(textEditor, filePath, item, out EditorNavigationLocation? location) + ? location + : null); +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.References.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.References.cs new file mode 100644 index 0000000000..1b414205b2 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.References.cs @@ -0,0 +1,216 @@ +#nullable enable + +using DarkUI.Docking; +using ICSharpCode.AvalonEdit.Document; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using TombIDE.ScriptingStudio.Helpers; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.ScriptingStudio.ToolStrips; +using TombIDE.ScriptingStudio.ToolWindows; +using TombIDE.ScriptingStudio.UI; +using TombLib.Scripting.Bases; +using TombLib.Scripting.Enums; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio; + +public sealed partial class LuaStudio +{ + public LuaReferencesResults LuaReferencesResults = null!; + + private CancellationTokenSource? _referencesCancellationTokenSource; + private int _referencesRequestToken; + + private void InitializeLuaReferencesResults() + { + LuaReferencesResults = new LuaReferencesResults(NavigateToReference); + } + + private async Task FindReferencesAsync() + { + ShowLuaReferencesResults(); + + if (CurrentEditor is not LuaEditor editor) + { + LuaReferencesResults.ShowNoActiveDocument(); + return; + } + + if (!_intellisenseProvider.SupportsReferences) + { + LuaReferencesResults.ShowUnsupported(); + return; + } + + CancellationToken cancellationToken = ResetReferenceRequestCancellation(); + int requestToken = ++_referencesRequestToken; + LuaReferencesResults.ShowLoading(); + + try + { + IReadOnlyList references = await _intellisenseProvider + .GetReferencesAsync( + editor.FilePath, + editor.Text, + Math.Max(0, editor.CurrentRow - 1), + Math.Max(0, editor.CurrentColumn - 1), + cancellationToken) + .ConfigureAwait(true); + + if (cancellationToken.IsCancellationRequested || requestToken != _referencesRequestToken) + return; + + if (references.Count == 0 && !_intellisenseProvider.SupportsReferences) + { + LuaReferencesResults.ShowUnsupported(); + UpdateLuaFeatureCommandAvailability(); + return; + } + + LuaReferencesResults.ShowReferences(BuildReferenceGroups(references)); + } + catch (OperationCanceledException) + { + // Ignore stale reference requests. + } + } + + private void CancelPendingReferenceRequest() + { + _referencesCancellationTokenSource?.Cancel(); + _referencesCancellationTokenSource?.Dispose(); + _referencesCancellationTokenSource = null; + } + + private void UpdateLuaFeatureCommandAvailability() + { + bool hasActiveTextEditor = CurrentEditor is TextEditorBase; + bool hasActiveLuaEditor = CurrentEditor is LuaEditor; + + SetCommandEnabled(UICommand.FindReferences, hasActiveLuaEditor && _intellisenseProvider.SupportsReferences); + SetCommandEnabled(UICommand.RenameSymbol, hasActiveLuaEditor && _intellisenseProvider.SupportsRename); + SetCommandEnabled(UICommand.Reindent, hasActiveLuaEditor ? _intellisenseProvider.SupportsFormatting : hasActiveTextEditor); + } + + private void SetCommandEnabled(UICommand command, bool isEnabled) + { + if (MenuStrip.FindItem(command) is ToolStripItem menuItem) + menuItem.Enabled = isEnabled; + + if (EditorContextMenu.FindItem(command) is ToolStripItem contextMenuItem) + contextMenuItem.Enabled = isEnabled; + } + + private void ShowLuaReferencesResults() + { + if (!DockPanel.ContainsContent(LuaReferencesResults)) + { + LuaReferencesResults.DockArea = DarkDockArea.Bottom; + DockPanel.AddContent(LuaReferencesResults); + } + + LuaReferencesResults.DockGroup.SetVisibleContent(LuaReferencesResults); + } + + private void NavigateToReference(LuaReferenceListItem reference) + => NavigateToLocation( + reference.FilePath, + NavigationOrigin.References, + textEditor => EditorNavigationHelper.CreateRangeLocation(textEditor, reference.FilePath, reference.Range)); + + private IReadOnlyList BuildReferenceGroups(IReadOnlyList references) + { + if (references.Count == 0) + return []; + + var lineCache = new Dictionary(StringComparer.OrdinalIgnoreCase); + var groups = new List(); + + foreach (IGrouping fileGroup in references + .Where(reference => !string.IsNullOrWhiteSpace(reference.FilePath)) + .GroupBy(reference => reference.FilePath, StringComparer.OrdinalIgnoreCase) + .OrderBy(group => GetDisplayPath(group.Key), StringComparer.OrdinalIgnoreCase)) + { + var items = fileGroup + .OrderBy(reference => reference.Range.StartLineNumber) + .ThenBy(reference => reference.Range.StartColumnNumber) + .Select(reference => new LuaReferenceListItem( + reference.FilePath, + reference.Range, + reference.Range.StartLineNumber, + reference.Range.StartColumnNumber, + GetPreviewText(reference.FilePath, reference.Range.StartLineNumber, lineCache))) + .ToArray(); + + groups.Add(new LuaReferenceGroup(fileGroup.Key, GetDisplayPath(fileGroup.Key), items)); + } + + return groups; + } + + private string GetDisplayPath(string filePath) + { + string fullFilePath = Path.GetFullPath(filePath); + string fullScriptRootPath = Path.GetFullPath(ScriptRootDirectoryPath); + + if (!fullScriptRootPath.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) + fullScriptRootPath += Path.DirectorySeparatorChar; + + if (fullFilePath.StartsWith(fullScriptRootPath, StringComparison.OrdinalIgnoreCase)) + return Path.GetRelativePath(fullScriptRootPath, fullFilePath); + + return fullFilePath; + } + + private string GetPreviewText(string filePath, int lineNumber, Dictionary lineCache) + { + string? previewText = TryGetOpenEditorLineText(filePath, lineNumber); + + if (previewText is null) + { + if (!lineCache.TryGetValue(filePath, out string[]? lines)) + { + lines = File.Exists(filePath) ? File.ReadAllLines(filePath) : null; + lineCache[filePath] = lines; + } + + if (lines is not null && lineNumber >= 1 && lineNumber <= lines.Length) + previewText = lines[lineNumber - 1]; + } + + return previewText?.Trim() ?? string.Empty; + } + + private string? TryGetOpenEditorLineText(string filePath, int lineNumber) + { + TabPage? tabPage = EditorTabControl.FindTabPage(filePath, EditorType.Text); + + if (tabPage is null || EditorTabControl.GetEditorOfTab(tabPage) is not TextEditorBase textEditor) + return null; + + return TryGetDocumentLineText(textEditor.Document, lineNumber); + } + + private static string? TryGetDocumentLineText(TextDocument document, int lineNumber) + { + if (lineNumber < 1 || lineNumber > document.LineCount) + return null; + + DocumentLine line = document.GetLineByNumber(lineNumber); + return document.GetText(line.Offset, line.Length); + } + + private CancellationToken ResetReferenceRequestCancellation() + { + CancelPendingReferenceRequest(); + _referencesCancellationTokenSource = new CancellationTokenSource(); + return _referencesCancellationTokenSource.Token; + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Rename.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Rename.cs new file mode 100644 index 0000000000..cde3c53dba --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Rename.cs @@ -0,0 +1,190 @@ +#nullable enable + +using DarkUI.Forms; +using ICSharpCode.AvalonEdit.Document; +using System; +using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Windows.Interop; +using TombIDE.ScriptingStudio.Services; +using TombIDE.Shared; +using TombLib.Forms.ViewModels; +using TombLib.Forms.Views; +using TombLib.Scripting.Lua; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio; + +public sealed partial class LuaStudio +{ + private readonly Services.LuaWorkspaceEditApplier _workspaceEditApplier; + + private async Task RenameSymbolAsync() + { + if (CurrentEditor is not LuaEditor editor) + { + ShowRenameInfo(Strings.Default.LuaRenameNoDocument, MessageBoxIcon.Information); + return; + } + + if (!_intellisenseProvider.SupportsRename) + { + ShowRenameInfo(Strings.Default.LuaRenameUnsupported, MessageBoxIcon.Information); + return; + } + + if (!TryGetRenameTarget(editor, out int renameOffset, out string currentName)) + { + ShowRenameInfo(Strings.Default.LuaRenameNoSymbol, MessageBoxIcon.Information); + return; + } + + if (!TryPromptRenameSymbol(currentName, out string? newName) + || string.IsNullOrWhiteSpace(newName) + || string.Equals(currentName, newName, StringComparison.Ordinal)) + { + return; + } + + TextLocation location = editor.Document.GetLocation(renameOffset); + + try + { + LuaWorkspaceEdit? workspaceEdit = await _intellisenseProvider + .RenameSymbolAsync( + editor.FilePath, + editor.Text, + Math.Max(0, location.Line - 1), + Math.Max(0, location.Column - 1), + newName) + .ConfigureAwait(true); + + if (workspaceEdit is null || !workspaceEdit.HasEdits) + { + ShowRenameInfo(Strings.Default.LuaRenameNoChanges, MessageBoxIcon.Information); + return; + } + + LuaWorkspaceEditTransaction transaction = _workspaceEditApplier.Apply(workspaceEdit); + + if (!transaction.HasChanges) + { + ShowRenameInfo(Strings.Default.LuaRenameNoChanges, MessageBoxIcon.Information); + return; + } + + PushWorkspaceEditTransaction(transaction); + HandleWorkspaceDocumentsChanged(transaction.DocumentChanges.Select(documentChange => documentChange.FilePath)); + } + catch (OperationCanceledException) + { + // Ignore canceled rename requests. + } + catch (Exception ex) + { + DarkMessageBox.Show(this, ex.Message, Strings.Default.RenameSymbol, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + private void ShowRenameInfo(string message, MessageBoxIcon icon) + => DarkMessageBox.Show(this, message, Strings.Default.RenameSymbol, MessageBoxButtons.OK, icon); + + private static bool TryGetRenameTarget(LuaEditor editor, out int renameOffset, out string currentName) + { + renameOffset = 0; + currentName = string.Empty; + + if (editor.SelectionLength > 0) + { + renameOffset = editor.SelectionStart; + currentName = editor.SelectedText?.Trim() ?? string.Empty; + return !string.IsNullOrWhiteSpace(currentName); + } + + if (!TryGetIdentifierStartOffset(editor.Document, editor.CaretOffset, out renameOffset)) + return false; + + currentName = editor.GetWordFromOffset(renameOffset)?.Trim() ?? string.Empty; + return !string.IsNullOrWhiteSpace(currentName); + } + + private bool TryPromptRenameSymbol(string currentName, out string? newName) + { + var viewModel = new InputBoxWindowViewModel(Strings.Default.RenameSymbol, Strings.Default.LuaRenamePromptLabel, currentName); + var window = new InputBoxWindow { DataContext = viewModel }; + PropertyChangedEventHandler? propertyChangedHandler = null; + + propertyChangedHandler = (_, e) => + { + if (e.PropertyName == nameof(InputBoxWindowViewModel.DialogResult) && viewModel.DialogResult.HasValue) + window.DialogResult = viewModel.DialogResult; + }; + + viewModel.PropertyChanged += propertyChangedHandler; + + try + { + if (FindForm() is Form ownerForm) + new WindowInteropHelper(window).Owner = ownerForm.Handle; + + bool? dialogResult = window.ShowDialog(); + newName = dialogResult == true ? viewModel.Value.Trim() : null; + return dialogResult == true; + } + finally + { + viewModel.PropertyChanged -= propertyChangedHandler; + } + } + + private bool TryGetOpenLuaEditor(string filePath, [NotNullWhen(true)] out LuaEditor? editor) + { + foreach (TabPage tabPage in EditorTabControl.FindTabPagesOfFile(filePath)) + { + if (EditorTabControl.GetEditorOfTab(tabPage) is LuaEditor luaEditor) + { + editor = luaEditor; + return true; + } + } + + editor = null; + return false; + } + + private static bool TryGetIdentifierStartOffset(TextDocument document, int offset, out int identifierStartOffset) + { + identifierStartOffset = 0; + + if (document.TextLength == 0) + return false; + + int probeOffset = Math.Clamp(offset, 0, document.TextLength); + + if (probeOffset >= document.TextLength) + probeOffset = document.TextLength - 1; + + if (probeOffset > 0 + && !IsLuaIdentifierCharacter(document.GetCharAt(probeOffset)) + && IsLuaIdentifierCharacter(document.GetCharAt(probeOffset - 1))) + { + probeOffset--; + } + + if (!IsLuaIdentifierCharacter(document.GetCharAt(probeOffset))) + return false; + + identifierStartOffset = probeOffset; + + while (identifierStartOffset > 0 && IsLuaIdentifierCharacter(document.GetCharAt(identifierStartOffset - 1))) + identifierStartOffset--; + + return true; + } + + private static bool IsLuaIdentifierCharacter(char character) + => char.IsLetterOrDigit(character) || character == '_'; +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.WorkspaceEditHistory.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.WorkspaceEditHistory.cs new file mode 100644 index 0000000000..f864de1382 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.WorkspaceEditHistory.cs @@ -0,0 +1,115 @@ +#nullable enable + +using DarkUI.Forms; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; +using TombIDE.ScriptingStudio.Services; +using TombIDE.Shared; +using TombLib.Scripting.Lua; + +namespace TombIDE.ScriptingStudio; + +public sealed partial class LuaStudio +{ + private readonly LuaWorkspaceEditHistoryService _workspaceEditHistory; + private int _workspaceEditHistoryApplyDepth; + + protected override bool CanExecuteUndo() + => _workspaceEditHistory.CanUndo || base.CanExecuteUndo(); + + protected override bool CanExecuteRedo() + => _workspaceEditHistory.CanRedo || base.CanExecuteRedo(); + + protected override void ExecuteUndo() + { + if (TryExecuteWorkspaceUndo()) + return; + + base.ExecuteUndo(); + } + + protected override void ExecuteRedo() + { + if (TryExecuteWorkspaceRedo()) + return; + + base.ExecuteRedo(); + } + + private bool IsApplyingWorkspaceEditHistory => _workspaceEditHistoryApplyDepth > 0; + + private void PushWorkspaceEditTransaction(LuaWorkspaceEditTransaction transaction) + { + if (!transaction.HasChanges) + return; + + _workspaceEditHistory.Push(transaction); + UpdateUndoRedoSaveStates(); + } + + private void InvalidateWorkspaceEditHistory() + { + if (IsApplyingWorkspaceEditHistory || !_workspaceEditHistory.HasEntries) + return; + + _workspaceEditHistory.Clear(); + UpdateUndoRedoSaveStates(); + } + + private bool TryExecuteWorkspaceUndo() + { + if (!_workspaceEditHistory.CanUndo) + return false; + + ApplyWorkspaceEditHistoryOperation(_workspaceEditHistory.Undo, Strings.Default.Undo); + return true; + } + + private bool TryExecuteWorkspaceRedo() + { + if (!_workspaceEditHistory.CanRedo) + return false; + + ApplyWorkspaceEditHistoryOperation(_workspaceEditHistory.Redo, Strings.Default.Redo); + return true; + } + + private void ApplyWorkspaceEditHistoryOperation(Func> operation, string caption) + { + try + { + _workspaceEditHistoryApplyDepth++; + HandleWorkspaceDocumentsChanged(operation()); + } + catch (Exception ex) + { + DarkMessageBox.Show(this, ex.Message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error); + } + finally + { + _workspaceEditHistoryApplyDepth--; + UpdateUndoRedoSaveStates(); + } + } + + private void HandleWorkspaceDocumentsChanged(IEnumerable filePaths) + { + string[] changedFiles = [.. filePaths + .Where(filePath => !string.IsNullOrWhiteSpace(filePath)) + .Distinct(StringComparer.OrdinalIgnoreCase)]; + + foreach (string filePath in changedFiles) + { + if (TryGetOpenLuaEditor(filePath, out LuaEditor? updatedEditor) && updatedEditor is not null) + _intellisenseProvider.UpdateDocument(filePath, updatedEditor.Text); + } + + if (CurrentEditor is LuaEditor currentEditor + && changedFiles.Any(filePath => string.Equals(filePath, currentEditor.FilePath, StringComparison.OrdinalIgnoreCase))) + { + RefreshLuaDiagnosticsView(isPending: true); + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs index e2f2cea762..3a26fe15fa 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs @@ -1,4 +1,5 @@ -using System; +using DarkUI.Docking; +using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -8,6 +9,7 @@ using ICSharpCode.AvalonEdit.Document; using TombIDE.ScriptingStudio.Bases; using TombIDE.ScriptingStudio.Controls; +using TombIDE.ScriptingStudio.Services; using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombIDE.ScriptingStudio.ToolWindows; using TombIDE.ScriptingStudio.UI; @@ -42,8 +44,12 @@ public LuaStudio() : base(IDE.Instance.Project.GetScriptRootDirectory(), IDE.Ins FileExplorer.ExcludedDirectoryFilter = "Scripts\\Engine"; FileExplorer.Filter = "*.lua"; FileExplorer.CommentPrefix = "--"; + InitializeLuaDiagnostics(); + InitializeLuaReferencesResults(); _intellisenseProvider = CreateLuaIntellisenseProvider(); + _workspaceEditApplier = new LuaWorkspaceEditApplier(EditorTabControl); + _workspaceEditHistory = new LuaWorkspaceEditHistoryService(_workspaceEditApplier); HookLuaIntellisense(); EditorTabControl.CheckPreviousSession(); @@ -245,8 +251,12 @@ protected override void RestoreDefaultLayout() DockPanel.RemoveContent(); DockPanel.RestoreDockPanelState(DockPanelState, FindDockContentByKey); + EnsureLuaToolWindowsInDockPanel(); } + protected override void OnDockPanelLayoutRestored() + => EnsureLuaToolWindowsInDockPanel(); + private void EndSilentScriptAction(TabPage previousTab, bool indicateChange, bool saveAffectedFile, bool closeAffectedTab) { if (indicateChange) @@ -271,6 +281,32 @@ private void EndSilentScriptAction(TabPage previousTab, bool indicateChange, boo #region Other methods + private void EnsureLuaToolWindowsInDockPanel() + { + if (DockPanel is null) + return; + + DarkDockGroup bottomGroup = SearchResults?.DockGroup ?? CompilerLogs?.DockGroup; + + bottomGroup = EnsureLuaToolWindowInDockPanel(LuaDiagnostics, bottomGroup); + EnsureLuaToolWindowInDockPanel(LuaReferencesResults, bottomGroup); + } + + private DarkDockGroup EnsureLuaToolWindowInDockPanel(DarkToolWindow toolWindow, DarkDockGroup bottomGroup) + { + if (DockPanel.ContainsContent(toolWindow)) + return bottomGroup ?? toolWindow.DockGroup; + + toolWindow.DockArea = DarkDockArea.Bottom; + + if (bottomGroup is not null) + DockPanel.AddContent(toolWindow, bottomGroup); + else + DockPanel.AddContent(toolWindow); + + return bottomGroup ?? toolWindow.DockGroup; + } + protected override void ApplyUserSettings(IEditorControl editor) => editor.UpdateSettings(Configs.Lua); @@ -298,13 +334,35 @@ protected override void Build() protected override void HandleDocumentCommands(UICommand command) { + if (command == UICommand.Reindent && CurrentEditor is LuaEditor) + { + _ = ReformatDocumentAsync(); + return; + } + switch (command) { + case UICommand.NavigateBack: + NavigateBack(); + break; + + case UICommand.NavigateForward: + NavigateForward(); + break; + case UICommand.GoToDefinition: if (CurrentEditor is LuaEditor luaEditor) _ = luaEditor.NavigateToDefinitionAtCaretAsync(); break; + case UICommand.FindReferences: + _ = FindReferencesAsync(); + break; + + case UICommand.RenameSymbol: + _ = RenameSymbolAsync(); + break; + case UICommand.LuaBasics: const string url = "https://github.com/MontyTRC89/TombEngine/wiki/Basics-of-Lua-Programming"; diff --git a/TombIDE/TombIDE.ScriptingStudio/Objects/EditorNavigationLocation.cs b/TombIDE/TombIDE.ScriptingStudio/Objects/EditorNavigationLocation.cs new file mode 100644 index 0000000000..baa30976ff --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Objects/EditorNavigationLocation.cs @@ -0,0 +1,19 @@ +#nullable enable + +using System; + +namespace TombIDE.ScriptingStudio.Objects; + +internal readonly record struct EditorNavigationLocation( + string FilePath, + int CaretOffset, + int SelectionStart, + int SelectionLength, + int? PreferredLine) +{ + public bool IsEquivalentTo(EditorNavigationLocation other) + => string.Equals(FilePath, other.FilePath, StringComparison.OrdinalIgnoreCase) + && CaretOffset == other.CaretOffset + && SelectionStart == other.SelectionStart + && SelectionLength == other.SelectionLength; +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Objects/LuaDiagnosticListItem.cs b/TombIDE/TombIDE.ScriptingStudio/Objects/LuaDiagnosticListItem.cs new file mode 100644 index 0000000000..abe620047b --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Objects/LuaDiagnosticListItem.cs @@ -0,0 +1,15 @@ +#nullable enable + +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.Objects; + +internal sealed record class LuaDiagnosticListItem( + string FilePath, + TextEditorDiagnosticSeverity Severity, + string SeverityLabel, + int LineNumber, + int ColumnNumber, + string Message, + int StartOffset, + int EndOffset); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceGroup.cs b/TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceGroup.cs new file mode 100644 index 0000000000..7b3c38afb4 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceGroup.cs @@ -0,0 +1,25 @@ +#nullable enable + +using System.Collections.Generic; + +namespace TombIDE.ScriptingStudio.Objects; + +internal sealed class LuaReferenceGroup +{ + public LuaReferenceGroup(string filePath, string displayPath, IReadOnlyList items) + { + FilePath = filePath; + DisplayPath = displayPath; + Items = items; + } + + public string FilePath { get; } + + public string DisplayPath { get; } + + public IReadOnlyList Items { get; } + + public int Count => Items.Count; + + public string Header => $"{DisplayPath} ({Count})"; +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceListItem.cs b/TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceListItem.cs new file mode 100644 index 0000000000..313c05256d --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Objects/LuaReferenceListItem.cs @@ -0,0 +1,15 @@ +#nullable enable + +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Objects; + +internal sealed record class LuaReferenceListItem( + string FilePath, + LuaDocumentRange Range, + int LineNumber, + int ColumnNumber, + string PreviewText) +{ + public string DisplayText => $"{LineNumber}:{ColumnNumber} {PreviewText}"; +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/EditorNavigationHistoryService.cs b/TombIDE/TombIDE.ScriptingStudio/Services/EditorNavigationHistoryService.cs new file mode 100644 index 0000000000..6ca3d0a9f3 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/EditorNavigationHistoryService.cs @@ -0,0 +1,131 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using TombIDE.ScriptingStudio.Objects; + +namespace TombIDE.ScriptingStudio.Services; + +internal sealed class EditorNavigationHistoryService +{ + private const int MinimumCaretMoveDistance = 32; + private const int MinimumSelectionMoveDistance = 8; + + private readonly Stack _backStack = new(); + private readonly Stack _forwardStack = new(); + + private EditorNavigationLocation? _currentLocation; + private int _suppressionDepth; + + public bool CanNavigateBack => _backStack.Count > 0; + + public bool CanNavigateForward => _forwardStack.Count > 0; + + public void Observe(EditorNavigationLocation location) + { + if (_suppressionDepth > 0) + { + _currentLocation = location; + return; + } + + if (_currentLocation is not EditorNavigationLocation currentLocation) + { + _currentLocation = location; + return; + } + + if (!IsMeaningfulChange(currentLocation, location)) + { + _currentLocation = location; + return; + } + + PushDistinct(_backStack, currentLocation); + _forwardStack.Clear(); + _currentLocation = location; + } + + public void RecordProgrammaticJump(EditorNavigationLocation currentLocation, EditorNavigationLocation targetLocation) + { + _currentLocation = currentLocation; + + if (currentLocation.IsEquivalentTo(targetLocation)) + return; + + PushDistinct(_backStack, currentLocation); + _forwardStack.Clear(); + } + + public void SetCurrentLocation(EditorNavigationLocation location) + => _currentLocation = location; + + public bool TryNavigateBack(EditorNavigationLocation currentLocation, out EditorNavigationLocation? targetLocation) + { + targetLocation = null; + + if (_backStack.Count == 0) + return false; + + PushDistinct(_forwardStack, currentLocation); + targetLocation = _backStack.Pop(); + _currentLocation = targetLocation; + return true; + } + + public bool TryNavigateForward(EditorNavigationLocation currentLocation, out EditorNavigationLocation? targetLocation) + { + targetLocation = null; + + if (_forwardStack.Count == 0) + return false; + + PushDistinct(_backStack, currentLocation); + targetLocation = _forwardStack.Pop(); + _currentLocation = targetLocation; + return true; + } + + public IDisposable SuppressRecording() + { + _suppressionDepth++; + return new RecordingScope(this); + } + + private static bool IsMeaningfulChange(EditorNavigationLocation previous, EditorNavigationLocation current) + { + if (!string.Equals(previous.FilePath, current.FilePath, StringComparison.OrdinalIgnoreCase)) + return true; + + if (previous.SelectionLength != current.SelectionLength) + return true; + + if (previous.SelectionLength > 0 || current.SelectionLength > 0) + return Math.Abs(previous.SelectionStart - current.SelectionStart) >= MinimumSelectionMoveDistance; + + return Math.Abs(previous.CaretOffset - current.CaretOffset) >= MinimumCaretMoveDistance; + } + + private static void PushDistinct(Stack stack, EditorNavigationLocation location) + { + if (stack.Count == 0 || !stack.Peek().IsEquivalentTo(location)) + stack.Push(location); + } + + private sealed class RecordingScope : IDisposable + { + private EditorNavigationHistoryService? _owner; + + public RecordingScope(EditorNavigationHistoryService owner) + => _owner = owner; + + public void Dispose() + { + if (_owner is null) + return; + + _owner._suppressionDepth = Math.Max(0, _owner._suppressionDepth - 1); + _owner = null; + } + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Formatting/LuaLanguageServerResponseParser.Formatting.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Formatting/LuaLanguageServerResponseParser.Formatting.cs new file mode 100644 index 0000000000..d14501734b --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Formatting/LuaLanguageServerResponseParser.Formatting.cs @@ -0,0 +1,23 @@ +#nullable enable + +using System.Collections.Generic; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses document-formatting edits from a LuaLS formatting response. + /// + public static IReadOnlyList ParseDocumentFormattingEdits(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Array) + return []; + + var textEdits = new List(); + AppendTextEdits(response, textEdits); + return textEdits; + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs index 73ecb00f40..7bf4144f45 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs @@ -43,6 +43,21 @@ internal interface ILuaLanguageServerClient : IDisposable /// bool SupportsCompletionResolve { get; } + /// + /// Gets a value indicating whether the server supports textDocument/references. + /// + bool SupportsReferences { get; } + + /// + /// Gets a value indicating whether the server supports textDocument/rename. + /// + bool SupportsRename { get; } + + /// + /// Gets a value indicating whether the server supports textDocument/formatting. + /// + bool SupportsFormatting { get; } + /// /// Gets a value indicating whether the server supports semantic-token delta responses. /// diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs index cfefa1b60d..866ea7b074 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs @@ -74,6 +74,9 @@ internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient private string[] _semanticTokenTypes = []; private string[] _semanticTokenModifiers = []; private bool _supportsCompletionResolve; + private bool? _supportsReferences; + private bool? _supportsRename; + private bool? _supportsFormatting; private bool _supportsSemanticTokensDelta; /// @@ -110,6 +113,21 @@ public bool IsReady /// public bool SupportsCompletionResolve => _supportsCompletionResolve; + /// + /// Gets a value indicating whether the server supports reference requests. + /// + public bool SupportsReferences => _supportsReferences ?? true; + + /// + /// Gets a value indicating whether the server supports rename requests. + /// + public bool SupportsRename => _supportsRename ?? true; + + /// + /// Gets a value indicating whether the server supports document formatting requests. + /// + public bool SupportsFormatting => _supportsFormatting ?? true; + /// /// Gets a value indicating whether the server supports semantic-token delta responses. /// @@ -313,6 +331,19 @@ public void MarkTransportUnhealthy() { linkSupport = true }, + references = new + { + dynamicRegistration = false + }, + rename = new + { + dynamicRegistration = false, + prepareSupport = false + }, + formatting = new + { + dynamicRegistration = false + }, publishDiagnostics = new { versionSupport = true @@ -350,6 +381,9 @@ public void MarkTransportUnhealthy() private void CaptureServerCapabilities(JsonElement initializeResponse) { _supportsCompletionResolve = false; + _supportsReferences = false; + _supportsRename = false; + _supportsFormatting = false; _supportsSemanticTokensDelta = false; _textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; _semanticTokenTypes = []; @@ -375,6 +409,24 @@ private void CaptureServerCapabilities(JsonElement initializeResponse) _supportsCompletionResolve = resolveProvider.ValueKind == JsonValueKind.True; } + if (capabilities.TryGetProperty("referencesProvider", out JsonElement referencesProvider)) + { + _supportsReferences = referencesProvider.ValueKind == JsonValueKind.True + || referencesProvider.ValueKind == JsonValueKind.Object; + } + + if (capabilities.TryGetProperty("renameProvider", out JsonElement renameProvider)) + { + _supportsRename = renameProvider.ValueKind == JsonValueKind.True + || renameProvider.ValueKind == JsonValueKind.Object; + } + + if (capabilities.TryGetProperty("documentFormattingProvider", out JsonElement formattingProvider)) + { + _supportsFormatting = formattingProvider.ValueKind == JsonValueKind.True + || formattingProvider.ValueKind == JsonValueKind.Object; + } + if (!capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider)) return; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs index f93f109315..c0b37ca5f5 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs @@ -84,6 +84,131 @@ public async Task> GetCompletionItemsAsync(stri cancellationToken); } + /// + /// Requests all known references for the specified document position. + /// + /// The local file path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The reference locations returned by LuaLS. + public async Task> GetReferencesAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + { + ILuaLanguageServerClient? client = _client; + + if (client is null + || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || !await SynchronizeDocumentAsync(normalizedFilePath, content, + acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false) + || !client.SupportsReferences) + { + return []; + } + + object textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }; + object position = new { line, character = column }; + + JsonElement response = await SendBoundedRequestAsync(client, "textDocument/references", + new + { + textDocument, + position, + context = new + { + includeDeclaration = true + } + }, + cancellationToken).ConfigureAwait(false); + + return LuaLanguageServerResponseParser.ParseReferenceLocations(response); + } + + /// + /// Requests workspace edits to rename the symbol at the specified document position. + /// + /// The local file path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// The requested replacement symbol name. + /// A token that can cancel the request. + /// The workspace edit returned by LuaLS, or when unavailable. + public async Task RenameSymbolAsync(string filePath, string content, + int line, int column, string newName, CancellationToken cancellationToken = default) + { + if (string.IsNullOrWhiteSpace(newName)) + return null; + + ILuaLanguageServerClient? client = _client; + + if (client is null + || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || !await SynchronizeDocumentAsync(normalizedFilePath, content, + acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false) + || !client.SupportsRename) + { + return null; + } + + object textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }; + object position = new { line, character = column }; + + JsonElement response = await SendBoundedRequestAsync(client, "textDocument/rename", + new + { + textDocument, + position, + newName + }, + cancellationToken).ConfigureAwait(false); + + return LuaLanguageServerResponseParser.ParseWorkspaceEdit(response); + } + + /// + /// Requests formatting edits for the specified Lua document. + /// + /// The local file path. + /// The current document content. + /// The editor formatting preferences to pass to LuaLS. + /// A token that can cancel the request. + /// The text edits returned by LuaLS. + public async Task> FormatDocumentAsync(string filePath, string content, + LuaFormattingOptions options, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(options); + + ILuaLanguageServerClient? client = _client; + + if (client is null + || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + || !await SynchronizeDocumentAsync(normalizedFilePath, content, + acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false) + || !client.SupportsFormatting) + { + return []; + } + + JsonElement response = await SendBoundedRequestAsync(client, "textDocument/formatting", + new + { + textDocument = new + { + uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) + }, + options = new + { + tabSize = options.TabSize, + insertSpaces = options.InsertSpaces + } + }, + cancellationToken).ConfigureAwait(false); + + return LuaLanguageServerResponseParser.ParseDocumentFormattingEdits(response); + } + /// /// Requests signature-help information for the specified document position. /// diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs index 7dc300ba18..975e8acdfc 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs @@ -53,6 +53,21 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntell public bool IsAvailable => !_isDisposed && _client is not null && _consecutiveStartupFailures < HardStartupFailureThreshold; + /// + /// Gets a value indicating whether reference requests are supported by the active Lua language server. + /// + public bool SupportsReferences => !_isDisposed && _client is not null && _client.SupportsReferences; + + /// + /// Gets a value indicating whether rename requests are supported by the active Lua language server. + /// + public bool SupportsRename => !_isDisposed && _client is not null && _client.SupportsRename; + + /// + /// Gets a value indicating whether formatting requests are supported by the active Lua language server. + /// + public bool SupportsFormatting => !_isDisposed && _client is not null && _client.SupportsFormatting; + /// /// Occurs when diagnostics for a tracked document change. /// diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md index 05a18b2d37..a357ac3118 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md @@ -13,10 +13,14 @@ This note is a maintainer map for the current LuaLS integration layout after the - `Completion/`: completion response parsing and snippet-placeholder result shaping. - `Hover/`: hover response parsing. - `Navigation/`: definition-location response parsing. +- `References/`: reference-location response parsing for `textDocument/references`. +- `Rename/`: workspace-edit parsing for `textDocument/rename` results. +- `Formatting/`: document-formatting edit parsing for `textDocument/formatting` results. - `SignatureHelp/`: signature-help response parsing. - `Diagnostics/`: diagnostics payload mapping and published diagnostics snapshots. - `SemanticTokens/`: semantic-tokens delta parsing plus cached delta and decode result carriers. - `LuaLanguageServerResponseParser.Shared.cs`: shared markup parsing helpers used by the response-parser partials. +- `LuaStudio.Formatting.cs` plus `LuaWorkspaceEditApplier`: host-side reformat command ownership, including selection preservation when formatting edits are applied back into the editor. ## Extraction naming @@ -37,6 +41,9 @@ This note is a maintainer map for the current LuaLS integration layout after the - Hover: verify symbol hover still shows hover content, and that hover falls back to diagnostics when no hover payload is available. - Signature help: verify `(` and `,` open or refresh the popup, `)` dismisses it, and editor deactivation clears transient UI. - Definition navigation: verify `F12` and `Ctrl+Click` navigate for valid identifiers and stay inert for comments, strings, or unresolved symbols. +- References: verify Find References opens or refreshes the references results pane, groups locations by file, and keeps activation navigation aligned with the selected result. +- Rename: verify Rename Symbol applies workspace edits across open and unopened files, preserves diagnostics ownership after the rename, and keeps the global undo action working for the full rename batch. +- Formatting: verify the existing cleanup command routes Lua documents through LuaLS formatting, preserves caret or selection state in the active editor, and falls back cleanly when formatting is unavailable. - Document lifecycle: verify open, update, rename, close, and restart replay keep document versions, URIs, and open references synchronized with LuaLS. - Diagnostics: verify published diagnostics replace stale results, clear when documents change or close, and stay attached to the correct file after rename and restart flows. - Semantic tokens: verify full refresh, delta apply, and delta fallback all keep coloring stable after edits, file changes, and server restart. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs new file mode 100644 index 0000000000..8640555c43 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs @@ -0,0 +1,89 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses reference locations from a LuaLS references response. + /// + public static IReadOnlyList ParseReferenceLocations(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Array) + return []; + + var locations = new List(); + + foreach (JsonElement referenceElement in response.EnumerateArray()) + { + if (referenceElement.ValueKind != JsonValueKind.Object) + continue; + + if (!TryGetReferenceUri(referenceElement, out Uri? parsedUri) + || !TryGetReferenceRange(referenceElement, out LuaDocumentRange? range)) + { + continue; + } + + locations.Add(new LuaReferenceLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), range)); + } + + return locations; + } + + private static bool TryGetReferenceUri(JsonElement referenceElement, [NotNullWhen(true)] out Uri? parsedUri) + { + parsedUri = null; + + if (!referenceElement.TryGetProperty("uri", out JsonElement uriElement)) + return false; + + string? uri = uriElement.GetString(); + return !string.IsNullOrWhiteSpace(uri) && Uri.TryCreate(uri, UriKind.Absolute, out parsedUri) && parsedUri.IsFile; + } + + private static bool TryGetReferenceRange(JsonElement referenceElement, [NotNullWhen(true)] out LuaDocumentRange? range) + { + range = null; + + if (!referenceElement.TryGetProperty("range", out JsonElement rangeElement) + || !rangeElement.TryGetProperty("start", out JsonElement startElement) + || !rangeElement.TryGetProperty("end", out JsonElement endElement)) + { + return false; + } + + if (!TryGetLineAndColumn(startElement, out int startLineNumber, out int startColumnNumber) + || !TryGetLineAndColumn(endElement, out int endLineNumber, out int endColumnNumber)) + { + return false; + } + + range = new LuaDocumentRange(startLineNumber, startColumnNumber, endLineNumber, endColumnNumber); + return true; + } + + private static bool TryGetLineAndColumn(JsonElement positionElement, out int lineNumber, out int columnNumber) + { + lineNumber = 1; + columnNumber = 1; + + if (!positionElement.TryGetProperty("line", out JsonElement lineElement) + || !lineElement.TryGetInt32(out int parsedLine) + || !positionElement.TryGetProperty("character", out JsonElement characterElement) + || !characterElement.TryGetInt32(out int parsedCharacter)) + { + return false; + } + + lineNumber = parsedLine + 1; + columnNumber = parsedCharacter + 1; + return true; + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs new file mode 100644 index 0000000000..d1b35918f4 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs @@ -0,0 +1,148 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; + +internal static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses a workspace edit from a LuaLS rename response. + /// + public static LuaWorkspaceEdit? ParseWorkspaceEdit(JsonElement response) + { + if (response.ValueKind != JsonValueKind.Object) + return null; + + var editsByFile = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + ParseChangeMap(response, editsByFile); + ParseDocumentChanges(response, editsByFile); + + if (editsByFile.Count == 0) + return null; + + var documentEdits = new List(editsByFile.Count); + + foreach ((string filePath, List textEdits) in editsByFile) + { + if (textEdits.Count == 0) + continue; + + documentEdits.Add(new LuaDocumentEdit(filePath, textEdits)); + } + + return documentEdits.Count == 0 + ? null + : new LuaWorkspaceEdit(documentEdits); + } + + private static void ParseChangeMap(JsonElement response, Dictionary> editsByFile) + { + if (!response.TryGetProperty("changes", out JsonElement changesElement) + || changesElement.ValueKind != JsonValueKind.Object) + { + return; + } + + foreach (JsonProperty changeProperty in changesElement.EnumerateObject()) + { + if (!Uri.TryCreate(changeProperty.Name, UriKind.Absolute, out Uri? parsedUri) || !parsedUri.IsFile) + continue; + + string filePath = LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri); + List textEdits = GetOrCreateTextEditBucket(editsByFile, filePath); + AppendTextEdits(changeProperty.Value, textEdits); + } + } + + private static void ParseDocumentChanges(JsonElement response, Dictionary> editsByFile) + { + if (!response.TryGetProperty("documentChanges", out JsonElement documentChangesElement) + || documentChangesElement.ValueKind != JsonValueKind.Array) + { + return; + } + + foreach (JsonElement documentChangeElement in documentChangesElement.EnumerateArray()) + { + if (documentChangeElement.ValueKind != JsonValueKind.Object + || !documentChangeElement.TryGetProperty("textDocument", out JsonElement textDocumentElement) + || !textDocumentElement.TryGetProperty("uri", out JsonElement uriElement)) + { + continue; + } + + string? uri = uriElement.GetString(); + + if (string.IsNullOrWhiteSpace(uri) || !Uri.TryCreate(uri, UriKind.Absolute, out Uri? parsedUri) || !parsedUri.IsFile) + continue; + + if (!documentChangeElement.TryGetProperty("edits", out JsonElement editsElement)) + continue; + + string filePath = LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri); + List textEdits = GetOrCreateTextEditBucket(editsByFile, filePath); + AppendTextEdits(editsElement, textEdits); + } + } + + private static void AppendTextEdits(JsonElement editsElement, List textEdits) + { + if (editsElement.ValueKind != JsonValueKind.Array) + return; + + foreach (JsonElement editElement in editsElement.EnumerateArray()) + { + if (TryParseTextEdit(editElement, out LuaTextEdit? textEdit)) + textEdits.Add(textEdit); + } + } + + private static bool TryParseTextEdit(JsonElement editElement, [NotNullWhen(true)] out LuaTextEdit? textEdit) + { + textEdit = null; + + if (editElement.ValueKind != JsonValueKind.Object + || !editElement.TryGetProperty("range", out JsonElement rangeElement) + || !TryParseRange(rangeElement, out LuaDocumentRange? range) + || !editElement.TryGetProperty("newText", out JsonElement newTextElement)) + { + return false; + } + + textEdit = new LuaTextEdit(range, newTextElement.GetString() ?? string.Empty); + return true; + } + + private static bool TryParseRange(JsonElement rangeElement, [NotNullWhen(true)] out LuaDocumentRange? range) + { + range = null; + + if (!rangeElement.TryGetProperty("start", out JsonElement startElement) + || !rangeElement.TryGetProperty("end", out JsonElement endElement) + || !TryGetLineAndColumn(startElement, out int startLineNumber, out int startColumnNumber) + || !TryGetLineAndColumn(endElement, out int endLineNumber, out int endColumnNumber)) + { + return false; + } + + range = new LuaDocumentRange(startLineNumber, startColumnNumber, endLineNumber, endColumnNumber); + return true; + } + + private static List GetOrCreateTextEditBucket(Dictionary> editsByFile, string filePath) + { + if (!editsByFile.TryGetValue(filePath, out List? textEdits)) + { + textEdits = []; + editsByFile[filePath] = textEdits; + } + + return textEdits; + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditApplier.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditApplier.cs new file mode 100644 index 0000000000..224c6af958 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditApplier.cs @@ -0,0 +1,268 @@ +#nullable enable + +using ICSharpCode.AvalonEdit.Document; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Windows.Forms; +using TombIDE.ScriptingStudio.Controls; +using TombLib.Scripting.Bases; +using TombLib.Scripting.Interfaces; +using TombLib.Scripting.Lua.Objects; + +namespace TombIDE.ScriptingStudio.Services; + +internal sealed class LuaWorkspaceEditApplier(EditorTabControl editorTabControl) +{ + private readonly EditorTabControl _editorTabControl = editorTabControl ?? throw new ArgumentNullException(nameof(editorTabControl)); + + public LuaWorkspaceEditTransaction Apply(LuaWorkspaceEdit workspaceEdit, LuaWorkspaceEditSelectionState? selectionState = null) + { + ArgumentNullException.ThrowIfNull(workspaceEdit); + + if (!workspaceEdit.HasEdits) + return new LuaWorkspaceEditTransaction([]); + + TabPage? previouslySelectedTab = _editorTabControl.SelectedTab; + var documentChanges = new List(); + + try + { + foreach (IGrouping fileGroup in workspaceEdit.DocumentEdits + .Where(documentEdit => !string.IsNullOrWhiteSpace(documentEdit.FilePath)) + .GroupBy(documentEdit => documentEdit.FilePath, StringComparer.OrdinalIgnoreCase)) + { + string filePath = fileGroup.Key; + TextEditorBase textEditor = GetOrOpenTextEditor(filePath); + LuaWorkspaceEditSelectionState? selectionStateForFile = selectionState is not null + && string.Equals(selectionState.FilePath, filePath, StringComparison.OrdinalIgnoreCase) + ? selectionState + : null; + string beforeContent = textEditor.Text; + List preparedTextEdits = PrepareTextEdits(textEditor.Document, + fileGroup.SelectMany(documentEdit => documentEdit.TextEdits)); + RestoredSelectionState? restoredSelectionState = selectionStateForFile is null + ? null + : MapSelectionState(selectionStateForFile, preparedTextEdits); + + ApplyPreparedTextEdits(textEditor, preparedTextEdits); + SynchronizeOpenTabs(filePath, textEditor); + + if (selectionStateForFile is not null && restoredSelectionState is not null) + RestoreSelectionState(selectionStateForFile.Editor, restoredSelectionState.Value); + + if (!string.Equals(beforeContent, textEditor.Text, StringComparison.Ordinal)) + documentChanges.Add(new LuaWorkspaceDocumentChange(filePath, beforeContent, textEditor.Text)); + } + } + finally + { + if (previouslySelectedTab is not null && _editorTabControl.TabPages.Contains(previouslySelectedTab)) + _editorTabControl.SelectTab(previouslySelectedTab); + } + + return new LuaWorkspaceEditTransaction(documentChanges); + } + + public IReadOnlyList ApplyBeforeSnapshot(LuaWorkspaceEditTransaction transaction) + => ApplyContentSnapshots(transaction, static documentChange => documentChange.BeforeContent); + + public IReadOnlyList ApplyAfterSnapshot(LuaWorkspaceEditTransaction transaction) + => ApplyContentSnapshots(transaction, static documentChange => documentChange.AfterContent); + + private TextEditorBase GetOrOpenTextEditor(string filePath) + { + if (!_editorTabControl.FindTabPagesOfFile(filePath).Any() && !File.Exists(filePath)) + throw new FileNotFoundException("Unable to apply a Lua workspace edit because the target file could not be found.", filePath); + + _editorTabControl.OpenFile(filePath); + + if (_editorTabControl.CurrentEditor is not TextEditorBase textEditor) + throw new InvalidOperationException($"Unable to apply Lua workspace edits to '{filePath}'."); + + return textEditor; + } + + private static void ApplyPreparedTextEdits(TextEditorBase textEditor, IReadOnlyList preparedTextEdits) + { + if (preparedTextEdits.Count == 0) + return; + + textEditor.Document.UndoStack.StartUndoGroup(); + textEditor.Document.BeginUpdate(); + + try + { + foreach (PreparedTextEdit preparedTextEdit in preparedTextEdits) + textEditor.Document.Replace(preparedTextEdit.StartOffset, preparedTextEdit.Length, preparedTextEdit.NewText); + } + finally + { + textEditor.Document.EndUpdate(); + textEditor.Document.UndoStack.EndUndoGroup(); + } + + textEditor.TryRunContentChangedWorker(); + } + + private IReadOnlyList ApplyContentSnapshots(LuaWorkspaceEditTransaction transaction, Func selectContent) + { + ArgumentNullException.ThrowIfNull(transaction); + ArgumentNullException.ThrowIfNull(selectContent); + + if (!transaction.HasChanges) + return []; + + TabPage? previouslySelectedTab = _editorTabControl.SelectedTab; + var updatedFiles = new List(transaction.DocumentChanges.Count); + + try + { + foreach (LuaWorkspaceDocumentChange documentChange in transaction.DocumentChanges) + { + TextEditorBase textEditor = GetOrOpenTextEditor(documentChange.FilePath); + ApplyDocumentContent(textEditor, selectContent(documentChange)); + SynchronizeOpenTabs(documentChange.FilePath, textEditor); + updatedFiles.Add(documentChange.FilePath); + } + } + finally + { + if (previouslySelectedTab is not null && _editorTabControl.TabPages.Contains(previouslySelectedTab)) + _editorTabControl.SelectTab(previouslySelectedTab); + } + + return updatedFiles; + } + + private static RestoredSelectionState MapSelectionState(LuaWorkspaceEditSelectionState selectionState, IReadOnlyList preparedTextEdits) + { + PreparedTextEdit[] editsAscending = [.. preparedTextEdits]; + + Array.Sort(editsAscending, static (left, right) => + { + int startComparison = left.StartOffset.CompareTo(right.StartOffset); + return startComparison != 0 + ? startComparison + : left.Length.CompareTo(right.Length); + }); + + int selectionStart = MapOffset(selectionState.SelectionStart, editsAscending); + int selectionEnd = MapOffset(selectionState.SelectionEnd, editsAscending); + int caretOffset = MapOffset(selectionState.CaretOffset, editsAscending); + + if (selectionEnd < selectionStart) + (selectionStart, selectionEnd) = (selectionEnd, selectionStart); + + return new RestoredSelectionState(selectionStart, selectionEnd, caretOffset); + } + + private static int MapOffset(int offset, IReadOnlyList preparedTextEdits) + { + int cumulativeDelta = 0; + + foreach (PreparedTextEdit preparedTextEdit in preparedTextEdits) + { + if (offset < preparedTextEdit.StartOffset) + break; + + if (offset <= preparedTextEdit.EndOffset) + { + int relativeOffset = offset - preparedTextEdit.StartOffset; + int normalizedRelativeOffset = Math.Min(relativeOffset, preparedTextEdit.NewText.Length); + return preparedTextEdit.StartOffset + cumulativeDelta + normalizedRelativeOffset; + } + + cumulativeDelta += preparedTextEdit.NewText.Length - preparedTextEdit.Length; + } + + return offset + cumulativeDelta; + } + + private static void RestoreSelectionState(TextEditorBase textEditor, RestoredSelectionState restoredSelectionState) + { + int documentLength = textEditor.Document.TextLength; + int selectionStart = Math.Clamp(restoredSelectionState.SelectionStart, 0, documentLength); + int selectionEnd = Math.Clamp(restoredSelectionState.SelectionEnd, 0, documentLength); + int caretOffset = Math.Clamp(restoredSelectionState.CaretOffset, 0, documentLength); + + if (selectionEnd < selectionStart) + (selectionStart, selectionEnd) = (selectionEnd, selectionStart); + + textEditor.Select(selectionStart, selectionEnd - selectionStart); + textEditor.CaretOffset = caretOffset; + } + + private static void ApplyDocumentContent(TextEditorBase textEditor, string content) + { + if (string.Equals(textEditor.Text, content, StringComparison.Ordinal)) + return; + + textEditor.Content = content; + } + + private static List PrepareTextEdits(TextDocument document, IEnumerable textEdits) + { + var preparedTextEdits = new List(); + + foreach (LuaTextEdit textEdit in textEdits) + { + if (!TryGetOffset(document, textEdit.Range.StartLineNumber, textEdit.Range.StartColumnNumber, out int startOffset) + || !TryGetOffset(document, textEdit.Range.EndLineNumber, textEdit.Range.EndColumnNumber, out int endOffset) + || endOffset < startOffset) + { + throw new InvalidOperationException("LuaLS returned an invalid workspace-edit range."); + } + + preparedTextEdits.Add(new PreparedTextEdit(startOffset, endOffset - startOffset, textEdit.NewText)); + } + + preparedTextEdits.Sort(static (left, right) => + { + int startComparison = right.StartOffset.CompareTo(left.StartOffset); + + return startComparison != 0 + ? startComparison + : right.Length.CompareTo(left.Length); + }); + + return preparedTextEdits; + } + + private void SynchronizeOpenTabs(string filePath, TextEditorBase sourceEditor) + { + foreach (TabPage tabPage in _editorTabControl.FindTabPagesOfFile(filePath)) + { + IEditorControl? editor = _editorTabControl.GetEditorOfTab(tabPage); + + if (ReferenceEquals(editor, sourceEditor) || editor is null) + continue; + + if (!string.Equals(editor.Content, sourceEditor.Content, StringComparison.Ordinal)) + editor.Content = sourceEditor.Content; + + editor.TryRunContentChangedWorker(); + } + } + + private static bool TryGetOffset(TextDocument document, int lineNumber, int columnNumber, out int offset) + { + offset = 0; + + if (lineNumber < 1 || lineNumber > document.LineCount) + return false; + + DocumentLine line = document.GetLineByNumber(lineNumber); + int characterOffset = Math.Clamp(columnNumber - 1, 0, line.Length); + offset = line.Offset + characterOffset; + return true; + } + + private readonly record struct PreparedTextEdit(int StartOffset, int Length, string NewText) + { + public int EndOffset => StartOffset + Length; + } + + private readonly record struct RestoredSelectionState(int SelectionStart, int SelectionEnd, int CaretOffset); +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditHistoryService.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditHistoryService.cs new file mode 100644 index 0000000000..e057ee49c8 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditHistoryService.cs @@ -0,0 +1,88 @@ +#nullable enable + +using System; +using System.Collections.Generic; + +namespace TombIDE.ScriptingStudio.Services; + +internal sealed class LuaWorkspaceEditHistoryService(LuaWorkspaceEditApplier workspaceEditApplier) +{ + private readonly LuaWorkspaceEditApplier _workspaceEditApplier = workspaceEditApplier ?? throw new ArgumentNullException(nameof(workspaceEditApplier)); + private readonly Stack _undoStack = []; + private readonly Stack _redoStack = []; + + public bool CanUndo => _undoStack.Count > 0; + public bool CanRedo => _redoStack.Count > 0; + public bool HasEntries => CanUndo || CanRedo; + + public void Push(LuaWorkspaceEditTransaction transaction) + { + ArgumentNullException.ThrowIfNull(transaction); + + if (!transaction.HasChanges) + return; + + _undoStack.Push(transaction); + _redoStack.Clear(); + } + + public void Clear() + { + _undoStack.Clear(); + _redoStack.Clear(); + } + + public IReadOnlyList Undo() + { + if (_undoStack.Count == 0) + return []; + + LuaWorkspaceEditTransaction transaction = _undoStack.Pop(); + + try + { + IReadOnlyList changedFiles = _workspaceEditApplier.ApplyBeforeSnapshot(transaction); + _redoStack.Push(transaction); + return changedFiles; + } + catch + { + _undoStack.Push(transaction); + throw; + } + } + + public IReadOnlyList Redo() + { + if (_redoStack.Count == 0) + return []; + + LuaWorkspaceEditTransaction transaction = _redoStack.Pop(); + + try + { + IReadOnlyList changedFiles = _workspaceEditApplier.ApplyAfterSnapshot(transaction); + _undoStack.Push(transaction); + return changedFiles; + } + catch + { + _redoStack.Push(transaction); + throw; + } + } +} + +internal sealed class LuaWorkspaceEditTransaction(IReadOnlyList documentChanges) +{ + public IReadOnlyList DocumentChanges { get; } = documentChanges ?? []; + + public bool HasChanges => DocumentChanges.Count > 0; +} + +internal sealed class LuaWorkspaceDocumentChange(string filePath, string beforeContent, string afterContent) +{ + public string FilePath { get; } = filePath ?? string.Empty; + public string BeforeContent { get; } = beforeContent ?? string.Empty; + public string AfterContent { get; } = afterContent ?? string.Empty; +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditSelectionState.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditSelectionState.cs new file mode 100644 index 0000000000..460d4d3853 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditSelectionState.cs @@ -0,0 +1,38 @@ +#nullable enable + +using System; +using TombLib.Scripting.Bases; + +namespace TombIDE.ScriptingStudio.Services; + +internal sealed class LuaWorkspaceEditSelectionState +{ + private LuaWorkspaceEditSelectionState(string filePath, TextEditorBase editor, int selectionStart, int selectionEnd, int caretOffset) + { + FilePath = filePath; + Editor = editor; + SelectionStart = selectionStart; + SelectionEnd = selectionEnd; + CaretOffset = caretOffset; + } + + public string FilePath { get; } + + public TextEditorBase Editor { get; } + + public int SelectionStart { get; } + + public int SelectionEnd { get; } + + public int CaretOffset { get; } + + public static LuaWorkspaceEditSelectionState Capture(TextEditorBase editor) + { + ArgumentNullException.ThrowIfNull(editor); + + int selectionStart = editor.SelectionStart; + int selectionEnd = selectionStart + editor.SelectionLength; + + return new LuaWorkspaceEditSelectionState(editor.FilePath, editor, selectionStart, selectionEnd, editor.CaretOffset); + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaDiagnostics.cs b/TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaDiagnostics.cs new file mode 100644 index 0000000000..0126fb48fd --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaDiagnostics.cs @@ -0,0 +1,47 @@ +#nullable enable + +using DarkUI.Docking; +using ICSharpCode.AvalonEdit.Document; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using System.Windows.Forms.Integration; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.ScriptingStudio.ViewModels; +using TombIDE.ScriptingStudio.Views; +using TombIDE.Shared; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.ToolWindows; + +public sealed class LuaDiagnostics : DarkToolWindow +{ + private readonly LuaDiagnosticsViewModel _viewModel = new(); + + internal LuaDiagnostics(Action? activateDiagnostic) + { + ElementHost elementHost = new() + { + Dock = DockStyle.Fill, + Child = new LuaDiagnosticsView(_viewModel, activateDiagnostic) + }; + + Controls.Add(elementHost); + + DefaultDockArea = DarkDockArea.Bottom; + DockText = Strings.Default.LuaDiagnostics; + Name = nameof(LuaDiagnostics); + SerializationKey = nameof(LuaDiagnostics); + Size = new Size(420, 220); + } + + public void ShowNoActiveDocument() + => _viewModel.ShowNoActiveDocument(); + + public void ShowPending() + => _viewModel.ShowPending(); + + public void ShowDiagnostics(string filePath, TextDocument document, IReadOnlyList diagnostics) + => _viewModel.ShowDiagnostics(filePath, document, diagnostics); +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaReferencesResults.cs b/TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaReferencesResults.cs new file mode 100644 index 0000000000..a49bbbd07d --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaReferencesResults.cs @@ -0,0 +1,48 @@ +#nullable enable + +using DarkUI.Docking; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using System.Windows.Forms.Integration; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.ScriptingStudio.ViewModels; +using TombIDE.ScriptingStudio.Views; +using TombIDE.Shared; + +namespace TombIDE.ScriptingStudio.ToolWindows; + +public sealed class LuaReferencesResults : DarkToolWindow +{ + private readonly LuaReferencesResultsViewModel _viewModel = new(); + + internal LuaReferencesResults(Action? activateReference) + { + ElementHost elementHost = new() + { + Dock = DockStyle.Fill, + Child = new LuaReferencesResultsView(_viewModel, activateReference) + }; + + Controls.Add(elementHost); + + DefaultDockArea = DarkDockArea.Bottom; + DockText = Strings.Default.LuaReferencesResults; + Name = nameof(LuaReferencesResults); + SerializationKey = nameof(LuaReferencesResults); + Size = new Size(420, 220); + } + + public void ShowNoActiveDocument() + => _viewModel.ShowNoActiveDocument(); + + public void ShowUnsupported() + => _viewModel.ShowUnsupported(); + + public void ShowLoading() + => _viewModel.ShowLoading(); + + internal void ShowReferences(IReadOnlyList groups) + => _viewModel.ShowReferences(groups); +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs b/TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs index b91e6789ff..d8e9d7cca1 100644 --- a/TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs +++ b/TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs @@ -1,26 +1,24 @@ -using DarkUI.Controls; +#nullable enable + +using DarkUI.Controls; using DarkUI.Docking; -using ICSharpCode.AvalonEdit.Document; -using System.Text.RegularExpressions; +using System; using System.Windows.Forms; -using TombIDE.ScriptingStudio.Controls; using TombIDE.Shared; -using TombLib.Scripting.Bases; -using TombLib.Scripting.Enums; using TombLib.Scripting.Objects; namespace TombIDE.ScriptingStudio.ToolWindows { public partial class SearchResults : DarkToolWindow { - private EditorTabControl _targetTabControl; + private readonly Action? _navigateToSearchResult; - public SearchResults(EditorTabControl targetTabControl) + public SearchResults(Action? navigateToSearchResult) { InitializeComponent(); DockText = Strings.Default.SearchResults; - _targetTabControl = targetTabControl; + _navigateToSearchResult = navigateToSearchResult; } public void UpdateResults(FindReplaceEventArgs e) @@ -56,43 +54,14 @@ private void treeView_MouseDoubleClick(object sender, MouseEventArgs e) return; var item = treeView.SelectedNodes[0].Tag as FindReplaceItem; + if (item is null) + return; - if (_targetTabControl != null) - { - string sourceFilePath = treeView.SelectedNodes[0].ParentNode.Tag.ToString(); - TabPage tab = _targetTabControl.FindTabPage(sourceFilePath, EditorType.Text); - - if (tab != null) - { - _targetTabControl.SelectTab(tab); - HandleJump(_targetTabControl.CurrentEditor as TextEditorBase, item); - } - } - } - - private void HandleJump(TextEditorBase textEditor, FindReplaceItem item) - { - try - { - DocumentLine line = textEditor.Document.GetLineByNumber(item.LineNumber); - string lineText = textEditor.Document.GetText(line.Offset, line.Length); - - MatchCollection matches = Regex.Matches(lineText, item.MatchSegmentText); - - if (item.MatchSegmentIndex > matches.Count) - { - textEditor.Select(line.Offset, 0); - textEditor.ScrollToLine(line.LineNumber); - } - else - { - Match match = matches[item.MatchSegmentIndex]; + string? sourceFilePath = treeView.SelectedNodes[0].ParentNode?.Tag?.ToString(); + if (string.IsNullOrWhiteSpace(sourceFilePath)) + return; - textEditor.Select(line.Offset + match.Index, match.Length); - textEditor.ScrollToLine(line.LineNumber); - } - } - catch { } + _navigateToSearchResult?.Invoke(sourceFilePath, item); } private bool IsRootNode() diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/ClassicScript.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/ClassicScript.xml index c9faf03b61..4901fe163e 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/ClassicScript.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/ClassicScript.xml @@ -4,6 +4,7 @@ + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/GameFlowScript.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/GameFlowScript.xml index 8d3bb645af..0c8e8a714f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/GameFlowScript.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/GameFlowScript.xml @@ -4,6 +4,7 @@ + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml index 5689996749..84089e5d6b 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml @@ -5,7 +5,12 @@ + + + + + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Tomb1Main.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Tomb1Main.xml index 8d3bb645af..0c8e8a714f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Tomb1Main.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Tomb1Main.xml @@ -4,6 +4,7 @@ + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/ClassicScript.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/ClassicScript.xml index 6faacb4c90..901604d340 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/ClassicScript.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/ClassicScript.xml @@ -9,6 +9,7 @@ + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/GameFlowScript.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/GameFlowScript.xml index bcb42987ca..f5eee0bd3f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/GameFlowScript.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/GameFlowScript.xml @@ -8,6 +8,7 @@ + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml index 6faacb4c90..eb32884e92 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml @@ -9,6 +9,13 @@ + + + + + + + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Tomb1Main.xml b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Tomb1Main.xml index bcb42987ca..f5eee0bd3f 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Tomb1Main.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Tomb1Main.xml @@ -8,6 +8,7 @@ + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml b/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml index 3a488ea59d..07a333b1a7 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml @@ -20,6 +20,8 @@ + + @@ -33,6 +35,8 @@ + + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/ToolStrips/Lua.xml b/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/ToolStrips/Lua.xml index 2a19e5e69e..343558ce4c 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/ToolStrips/Lua.xml +++ b/TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/ToolStrips/Lua.xml @@ -1,5 +1,8 @@  + + + diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs b/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs index ce4ed0fc23..84cfa64443 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs +++ b/TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs @@ -30,6 +30,7 @@ public enum UICommand Reindent, TrimWhiteSpace, + ToggleComment, CommentOut, Uncomment, ToggleBookmark, @@ -60,6 +61,8 @@ public enum UICommand ReferenceBrowser, CompilerLogs, SearchResults, + LuaDiagnostics, + LuaReferencesResults, StatusStrip, // View end @@ -72,7 +75,11 @@ public enum UICommand // Other: + NavigateBack, + NavigateForward, GoToDefinition, + FindReferences, + RenameSymbol, TypeFirstAvailableId, NewFileAtCaret } diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/UIElement.cs b/TombIDE/TombIDE.ScriptingStudio/UI/UIElement.cs index 200b0a4be3..2062415080 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/UIElement.cs +++ b/TombIDE/TombIDE.ScriptingStudio/UI/UIElement.cs @@ -24,6 +24,7 @@ public enum UIElement Reindent, TrimWhiteSpace, + ToggleComment, CommentOut, Uncomment, ToggleBookmark, diff --git a/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs b/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs index 73af7d14ac..da0a2bd870 100644 --- a/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs +++ b/TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs @@ -21,10 +21,15 @@ internal struct UIKeys public const Keys Reindent = Keys.Control | Keys.R; public const Keys TrimWhitespace = Keys.Control | Keys.Shift | Keys.R; + public const Keys ToggleComment = Keys.Control | Keys.OemQuestion; public const Keys CommentOut = Keys.Control | Keys.Shift | Keys.C; public const Keys Uncomment = Keys.Control | Keys.Shift | Keys.U; public const Keys ToggleBookmark = Keys.Control | Keys.B; + public const Keys NavigateBack = Keys.Alt | Keys.Left; + public const Keys NavigateForward = Keys.Alt | Keys.Right; public const Keys GoToDefinition = Keys.F12; + public const Keys FindReferences = Keys.Shift | Keys.F12; + public const Keys RenameSymbol = Keys.F2; public const Keys PrevBookmark = Keys.Control | Keys.Oemcomma; public const Keys NextBookmark = Keys.Control | Keys.OemPeriod; public const Keys ClearBookmarks = Keys.Control | Keys.Shift | Keys.B; diff --git a/TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaDiagnosticsViewModel.cs b/TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaDiagnosticsViewModel.cs new file mode 100644 index 0000000000..c73be11bbf --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaDiagnosticsViewModel.cs @@ -0,0 +1,194 @@ +#nullable enable + +using ICSharpCode.AvalonEdit.Document; +using System; +using System.Collections.ObjectModel; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Windows.Data; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.Shared; +using TombLib.Scripting.Objects; + +namespace TombIDE.ScriptingStudio.ViewModels; + +internal sealed class LuaDiagnosticsViewModel : INotifyPropertyChanged +{ + private readonly ObservableCollection _diagnostics = []; + + private LuaDiagnosticListItem? _selectedItem; + private bool _showErrors = true; + private bool _showWarnings = true; + private bool _showMessages = true; + private string _statusText = string.Empty; + + public LuaDiagnosticsViewModel() + { + Diagnostics = CollectionViewSource.GetDefaultView(_diagnostics); + Diagnostics.Filter = FilterDiagnostic; + + ShowNoActiveDocument(); + } + + public event PropertyChangedEventHandler? PropertyChanged; + + public ICollectionView Diagnostics { get; } + + public LuaDiagnosticListItem? SelectedItem + { + get => _selectedItem; + set => SetField(ref _selectedItem, value); + } + + public bool ShowErrors + { + get => _showErrors; + set + { + if (!SetField(ref _showErrors, value)) + return; + + Diagnostics.Refresh(); + } + } + + public bool ShowWarnings + { + get => _showWarnings; + set + { + if (!SetField(ref _showWarnings, value)) + return; + + Diagnostics.Refresh(); + } + } + + public bool ShowMessages + { + get => _showMessages; + set + { + if (!SetField(ref _showMessages, value)) + return; + + Diagnostics.Refresh(); + } + } + + public string StatusText + { + get => _statusText; + private set + { + if (!SetField(ref _statusText, value)) + return; + + OnPropertyChanged(nameof(HasStatusText)); + } + } + + public bool HasStatusText => !string.IsNullOrWhiteSpace(StatusText); + + public string ErrorsLabel => Strings.Default.Errors; + + public string WarningsLabel => Strings.Default.Warnings; + + public string MessagesLabel => Strings.Default.Messages; + + public string SeverityHeader => Strings.Default.Severity; + + public string LineHeader => Strings.Default.LineHeader; + + public string ColumnHeader => Strings.Default.ColumnHeader; + + public string MessageHeader => Strings.Default.Message; + + public void ShowNoActiveDocument() + => ReplaceDiagnostics([], Strings.Default.LuaDiagnosticsNoDocument); + + public void ShowPending() + => ReplaceDiagnostics([], Strings.Default.LuaDiagnosticsUpdating); + + public void ShowDiagnostics(string filePath, TextDocument document, IReadOnlyList diagnostics) + { + ArgumentNullException.ThrowIfNull(document); + ArgumentNullException.ThrowIfNull(diagnostics); + + LuaDiagnosticListItem[] items = new LuaDiagnosticListItem[diagnostics.Count]; + + for (int i = 0; i < diagnostics.Count; i++) + items[i] = CreateItem(filePath, document, diagnostics[i]); + + ReplaceDiagnostics(items, items.Length == 0 ? Strings.Default.NoDiagnostics : string.Empty); + } + + private void ReplaceDiagnostics(IReadOnlyList diagnostics, string statusText) + { + _diagnostics.Clear(); + + foreach (LuaDiagnosticListItem diagnostic in diagnostics) + _diagnostics.Add(diagnostic); + + SelectedItem = _diagnostics.Count > 0 ? _diagnostics[0] : null; + StatusText = statusText; + Diagnostics.Refresh(); + } + + private bool FilterDiagnostic(object item) + { + if (item is not LuaDiagnosticListItem diagnostic) + return false; + + return diagnostic.Severity switch + { + TextEditorDiagnosticSeverity.Error => ShowErrors, + TextEditorDiagnosticSeverity.Warning => ShowWarnings, + _ => ShowMessages + }; + } + + private static LuaDiagnosticListItem CreateItem(string filePath, TextDocument document, TextEditorDiagnostic diagnostic) + { + int documentLength = document.TextLength; + int startOffset = Math.Max(0, Math.Min(diagnostic.StartOffset, documentLength)); + int endOffset = Math.Max(startOffset, Math.Min(diagnostic.EndOffset, documentLength)); + + DocumentLine line = document.GetLineByOffset(startOffset); + int columnNumber = startOffset - line.Offset + 1; + + return new LuaDiagnosticListItem( + filePath, + diagnostic.Severity, + GetSeverityLabel(diagnostic.Severity), + line.LineNumber, + columnNumber, + diagnostic.Message, + startOffset, + endOffset); + } + + private static string GetSeverityLabel(TextEditorDiagnosticSeverity severity) + => severity switch + { + TextEditorDiagnosticSeverity.Error => Strings.Default.Error, + TextEditorDiagnosticSeverity.Warning => Strings.Default.Warning, + TextEditorDiagnosticSeverity.Information => Strings.Default.Information, + TextEditorDiagnosticSeverity.Hint => Strings.Default.Hint, + _ => Strings.Default.Message + }; + + private bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null) + { + if (Equals(field, value)) + return false; + + field = value; + OnPropertyChanged(propertyName); + return true; + } + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaReferencesResultsViewModel.cs b/TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaReferencesResultsViewModel.cs new file mode 100644 index 0000000000..5cbe148299 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaReferencesResultsViewModel.cs @@ -0,0 +1,72 @@ +#nullable enable + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.Shared; + +namespace TombIDE.ScriptingStudio.ViewModels; + +internal sealed class LuaReferencesResultsViewModel : INotifyPropertyChanged +{ + private readonly ObservableCollection _groups = []; + private string _statusText = string.Empty; + + public event PropertyChangedEventHandler? PropertyChanged; + + public ObservableCollection Groups => _groups; + + public string StatusText + { + get => _statusText; + private set + { + if (!SetField(ref _statusText, value)) + return; + + OnPropertyChanged(nameof(HasStatusText)); + } + } + + public bool HasStatusText => !string.IsNullOrWhiteSpace(StatusText); + + public bool HasResults => _groups.Count > 0; + + public void ShowNoActiveDocument() + => ReplaceGroups([], Strings.Default.LuaReferencesNoDocument); + + public void ShowUnsupported() + => ReplaceGroups([], Strings.Default.LuaReferencesUnsupported); + + public void ShowLoading() + => ReplaceGroups([], Strings.Default.LuaReferencesLoading); + + public void ShowReferences(IReadOnlyList groups) + => ReplaceGroups(groups, groups.Count == 0 ? Strings.Default.NoReferencesFound : string.Empty); + + private void ReplaceGroups(IReadOnlyList groups, string statusText) + { + _groups.Clear(); + + foreach (LuaReferenceGroup group in groups) + _groups.Add(group); + + StatusText = statusText; + OnPropertyChanged(nameof(HasResults)); + } + + private bool SetField(ref T field, T value, [CallerMemberName] string? propertyName = null) + { + if (EqualityComparer.Default.Equals(field, value)) + return false; + + field = value; + OnPropertyChanged(propertyName); + return true; + } + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml b/TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml new file mode 100644 index 0000000000..798bce96d5 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml.cs b/TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml.cs new file mode 100644 index 0000000000..8f8d8adaf6 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml.cs @@ -0,0 +1,43 @@ +#nullable enable + +using System; +using System.Windows.Controls; +using System.Windows.Input; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.ScriptingStudio.ViewModels; + +namespace TombIDE.ScriptingStudio.Views; + +public partial class LuaDiagnosticsView : UserControl +{ + private readonly Action? _activateDiagnostic; + + internal LuaDiagnosticsView(LuaDiagnosticsViewModel viewModel, Action? activateDiagnostic) + { + InitializeComponent(); + DataContext = viewModel; + _activateDiagnostic = activateDiagnostic; + } + + private LuaDiagnosticsViewModel ViewModel => (LuaDiagnosticsViewModel)DataContext; + + private void DiagnosticsGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) + => ActivateSelectedDiagnostic(); + + private void DiagnosticsGrid_PreviewKeyDown(object sender, KeyEventArgs e) + { + if (e.Key != Key.Enter) + return; + + ActivateSelectedDiagnostic(); + e.Handled = true; + } + + private void ActivateSelectedDiagnostic() + { + if (ViewModel.SelectedItem is not LuaDiagnosticListItem selectedDiagnostic) + return; + + _activateDiagnostic?.Invoke(selectedDiagnostic); + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml b/TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml new file mode 100644 index 0000000000..ec668bdb59 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml.cs b/TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml.cs new file mode 100644 index 0000000000..e40583e784 --- /dev/null +++ b/TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml.cs @@ -0,0 +1,41 @@ +#nullable enable + +using System; +using System.Windows.Controls; +using System.Windows.Input; +using TombIDE.ScriptingStudio.Objects; +using TombIDE.ScriptingStudio.ViewModels; + +namespace TombIDE.ScriptingStudio.Views; + +public partial class LuaReferencesResultsView : UserControl +{ + private readonly Action? _activateReference; + + internal LuaReferencesResultsView(LuaReferencesResultsViewModel viewModel, Action? activateReference) + { + InitializeComponent(); + DataContext = viewModel; + _activateReference = activateReference; + } + + private void ReferencesTree_MouseDoubleClick(object sender, MouseButtonEventArgs e) + => ActivateSelectedReference(); + + private void ReferencesTree_PreviewKeyDown(object sender, KeyEventArgs e) + { + if (e.Key != Key.Enter) + return; + + ActivateSelectedReference(); + e.Handled = true; + } + + private void ActivateSelectedReference() + { + if (ReferencesTree.SelectedItem is not LuaReferenceListItem selectedReference) + return; + + _activateReference?.Invoke(selectedReference); + } +} \ No newline at end of file diff --git a/TombIDE/TombIDE.Shared/DefaultLayouts.cs b/TombIDE/TombIDE.Shared/DefaultLayouts.cs index 02252d9196..2d939bd6f2 100644 --- a/TombIDE/TombIDE.Shared/DefaultLayouts.cs +++ b/TombIDE/TombIDE.Shared/DefaultLayouts.cs @@ -122,6 +122,25 @@ public static class DefaultLayouts VisibleContent = "ReferenceBrowser" } } + }, + new DockRegionState + { + Area = DarkDockArea.Bottom, + Size = new Size(320, 220), + Groups = new List + { + new DockGroupState + { + Contents = new List + { + "SearchResults", + "LuaDiagnostics", + "LuaReferencesResults" + }, + + VisibleContent = "LuaDiagnostics" + } + } } } }; diff --git a/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml b/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml index 9d472b237f..128b699afd 100644 --- a/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml +++ b/TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml @@ -59,12 +59,17 @@ Tabs to Spaces Spaces to Tabs - Reindent Code + Reformat Trim Ending Whitespace + Toggle Comment Comment out Selected Lines Uncomment Selected Lines Toggle Bookmark + Navigate Back + Navigate Forward Go to Definition + Find References + Rename Symbol Go to Previous Bookmark Go to Next Bookmark Clear All Bookmarks... @@ -86,6 +91,8 @@ Reference Browser Compiler Logs Search Results + Lua Diagnostics + Lua References Tool Strip Status Strip @@ -115,10 +122,34 @@ Row: {0} Column: {0} Line: {0} + Line + Column Selected: {0} Zoom: {0}% Reset Zoom + Severity + Message + Errors + Warning + Warnings + Information + Hint + Messages + No diagnostics in the active Lua document. + Select an active Lua document to view diagnostics. + Diagnostics are updating... + No references found. + Select an active Lua document to view references. + The active Lua language server does not support Find References. + Searching for references... + Select an active Lua document to rename a symbol. + The active Lua language server does not support Rename Symbol. + Select a Lua identifier or place the caret on one first. + New name: + No rename changes were returned. + The active Lua language server does not support document formatting. + Decimal Value Hexadecimal Value Macro diff --git a/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs b/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs index c1e0fff52d..ae4f6d23ac 100644 --- a/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs +++ b/TombIDE/TombIDE.Shared/Resources/Localization/Localization.cs @@ -50,10 +50,15 @@ public class Localization public string Reindent { get; set; } public string TrimWhitespace { get; set; } + public string ToggleComment { get; set; } public string CommentOut { get; set; } public string Uncomment { get; set; } public string ToggleBookmark { get; set; } + public string NavigateBack { get; set; } + public string NavigateForward { get; set; } public string GoToDefinition { get; set; } + public string FindReferences { get; set; } + public string RenameSymbol { get; set; } public string PrevBookmark { get; set; } public string NextBookmark { get; set; } public string ClearBookmarks { get; set; } @@ -74,6 +79,8 @@ public class Localization public string ReferenceBrowser { get; set; } public string CompilerLogs { get; set; } public string SearchResults { get; set; } + public string LuaDiagnostics { get; set; } + public string LuaReferencesResults { get; set; } public string ToolStrip { get; set; } public string StatusStrip { get; set; } @@ -103,10 +110,34 @@ public class Localization public string Row { get; set; } public string Column { get; set; } public string Line { get; set; } + public string LineHeader { get; set; } + public string ColumnHeader { get; set; } public string Selected { get; set; } public string Zoom { get; set; } public string ResetZoom { get; set; } + public string Severity { get; set; } + public string Message { get; set; } + public string Errors { get; set; } + public string Warning { get; set; } + public string Warnings { get; set; } + public string Information { get; set; } + public string Hint { get; set; } + public string Messages { get; set; } + public string NoDiagnostics { get; set; } + public string LuaDiagnosticsNoDocument { get; set; } + public string LuaDiagnosticsUpdating { get; set; } + public string NoReferencesFound { get; set; } + public string LuaReferencesNoDocument { get; set; } + public string LuaReferencesUnsupported { get; set; } + public string LuaReferencesLoading { get; set; } + public string LuaRenameNoDocument { get; set; } + public string LuaRenameUnsupported { get; set; } + public string LuaRenameNoSymbol { get; set; } + public string LuaRenamePromptLabel { get; set; } + public string LuaRenameNoChanges { get; set; } + public string LuaReformatUnsupported { get; set; } + public string DecimalValue { get; set; } public string HexadecimalValue { get; set; } public string Macro { get; set; } diff --git a/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml b/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml index 64c95a2b34..49f04b40a1 100644 --- a/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml +++ b/TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml @@ -59,12 +59,17 @@ Tabulatory na spacje Spacje na tabulatory - Uporządkuj białe znaki + Przeformatuj Usuń białe znaki na końcach linii + Przelacz komentarz Wstaw zakomentowanie Usuń zakomentowanie Przełącz zakładkę + Przejdź wstecz + Przejdź dalej Przejdź do definicji + Znajdź odwołania + Zmień nazwę symbolu Idź do poprzedniej zakładki Idź do następnej zakładki Wyczyść wszystkie zakładki... @@ -86,6 +91,8 @@ Wyszukiwarka referencji Raport kompilatora Wyniki wyszukiwania + Diagnostyka Lua + Referencje Lua Pasek narzędzi Pasek stanu @@ -115,10 +122,34 @@ Wiersz: {0} Kolumna: {0} Linia: {0} + Linia + Kolumna Zaznaczone: {0} Powiększenie: {0}% Resetuj powiększenie + Poziom + Wiadomość + Błędy + Ostrzeżenie + Ostrzeżenia + Informacja + Wskazówka + Komunikaty + Brak diagnostyki dla aktywnego dokumentu Lua. + Wybierz aktywny dokument Lua, aby wyświetlić diagnostykę. + Diagnostyka jest aktualizowana... + Nie znaleziono referencji. + Wybierz aktywny dokument Lua, aby wyswietlic referencje. + Aktywny serwer jezyka Lua nie obsluguje funkcji Znajdz odwolania. + Trwa wyszukiwanie referencji... + Wybierz aktywny dokument Lua, aby zmienic nazwe symbolu. + Aktywny serwer jezyka Lua nie obsluguje funkcji Zmien nazwe symbolu. + Wybierz identyfikator Lua lub ustaw na nim kursor. + Nowa nazwa: + Nie zwrocono zadnych zmian nazwy. + Aktywny serwer jezyka Lua nie obsluguje formatowania dokumentu. + Wartość dziesiętna Wartość szesnastkowa Makro diff --git a/TombIDE/TombIDE/Program.cs b/TombIDE/TombIDE/Program.cs index e75a2ae99a..d6475ae911 100644 --- a/TombIDE/TombIDE/Program.cs +++ b/TombIDE/TombIDE/Program.cs @@ -1,4 +1,4 @@ -using CustomMessageBox.WPF; +using Microsoft.Extensions.DependencyInjection; using System; using System.IO; using System.Linq; @@ -6,7 +6,8 @@ using System.Windows.Forms; using TombIDE.Shared; using TombIDE.Shared.SharedClasses; -using WPF = System.Windows; +using TombLib.WPF; +using TombLib.WPF.Services; namespace TombIDE { @@ -18,7 +19,8 @@ internal static class Program [STAThread] private static void Main(string[] args) { - InitializeWPF(); + var services = WPFInitializer.InitializeWPF(); + ServiceLocator.Configure(services.BuildServiceProvider()); Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); @@ -63,33 +65,6 @@ private static void Main(string[] args) Application.Run(form); } - private static void InitializeWPF() - { - // Initialize WPF resources - var wpfApp = new WPF.Application - { - ShutdownMode = WPF.ShutdownMode.OnExplicitShutdown - }; - - // Add the DarkUI theme to the WPF application - wpfApp.Resources.MergedDictionaries.Add(new WPF.ResourceDictionary - { - Source = new Uri("pack://application:,,,/DarkUI.WPF;component/Generic.xaml") - }); - - // Use DarkColors theme (default DarkUI look) - wpfApp.Resources.MergedDictionaries.Add(new WPF.ResourceDictionary - { - Source = new Uri("pack://application:,,,/DarkUI.WPF;component/Dictionaries/DarkColors.xaml") - }); - - CMessageBox.WindowStyleOverride = (WPF.Style)wpfApp.Resources["CustomWindowStyle"]; - CMessageBox.UsePathIconsByDefault = true; - - if (wpfApp.TryFindResource("Brush_Background_Alternative") is WPF.Media.SolidColorBrush brush) - CMessageBox.DefaultButtonsPanelBackground = brush; - } - private static void UpdateNGCompilerPaths() { try diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentEdit.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentEdit.cs new file mode 100644 index 0000000000..58c322b80f --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentEdit.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace TombLib.Scripting.Lua.Objects; + +/// +/// Represents the text edits that should be applied to a single Lua document. +/// +public sealed class LuaDocumentEdit +{ + /// + /// Initializes a new instance of the class. + /// + /// The file to update. + /// The edits to apply. + public LuaDocumentEdit(string filePath, IReadOnlyList textEdits) + { + FilePath = filePath; + TextEdits = textEdits ?? []; + } + + /// + /// Gets the file to update. + /// + public string FilePath { get; } + + /// + /// Gets the edits to apply to the file. + /// + public IReadOnlyList TextEdits { get; } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentRange.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentRange.cs new file mode 100644 index 0000000000..153b7bf3f7 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaDocumentRange.cs @@ -0,0 +1,56 @@ +using System; + +namespace TombLib.Scripting.Lua.Objects; + +/// +/// Identifies a one-based document range inside a Lua source file. +/// +public sealed class LuaDocumentRange +{ + /// + /// Initializes a new instance of the class. + /// + /// The one-based start line number. + /// The one-based start column number. + /// The one-based end line number. + /// The one-based end column number. + public LuaDocumentRange(int startLineNumber, int startColumnNumber, int endLineNumber, int endColumnNumber) + { + int safeStartLineNumber = Math.Max(1, startLineNumber); + int safeStartColumnNumber = Math.Max(1, startColumnNumber); + int safeEndLineNumber = Math.Max(1, endLineNumber); + int safeEndColumnNumber = Math.Max(1, endColumnNumber); + + if (safeEndLineNumber < safeStartLineNumber + || (safeEndLineNumber == safeStartLineNumber && safeEndColumnNumber < safeStartColumnNumber)) + { + safeEndLineNumber = safeStartLineNumber; + safeEndColumnNumber = safeStartColumnNumber; + } + + StartLineNumber = safeStartLineNumber; + StartColumnNumber = safeStartColumnNumber; + EndLineNumber = safeEndLineNumber; + EndColumnNumber = safeEndColumnNumber; + } + + /// + /// Gets the one-based start line number. + /// + public int StartLineNumber { get; } + + /// + /// Gets the one-based start column number. + /// + public int StartColumnNumber { get; } + + /// + /// Gets the one-based end line number. + /// + public int EndLineNumber { get; } + + /// + /// Gets the one-based end column number. + /// + public int EndColumnNumber { get; } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaFormattingOptions.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaFormattingOptions.cs new file mode 100644 index 0000000000..9f1eaa8c88 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaFormattingOptions.cs @@ -0,0 +1,28 @@ +namespace TombLib.Scripting.Lua.Objects; + +/// +/// Represents the editor formatting preferences used for a Lua document formatting request. +/// +public sealed class LuaFormattingOptions +{ + /// + /// Initializes a new instance of the class. + /// + /// The preferred indentation width. + /// to indent with spaces; otherwise, tabs. + public LuaFormattingOptions(int tabSize, bool insertSpaces) + { + TabSize = tabSize > 0 ? tabSize : 4; + InsertSpaces = insertSpaces; + } + + /// + /// Gets the preferred indentation width. + /// + public int TabSize { get; } + + /// + /// Gets a value indicating whether indentation should use spaces. + /// + public bool InsertSpaces { get; } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaReferenceLocation.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaReferenceLocation.cs new file mode 100644 index 0000000000..906f2110cf --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaReferenceLocation.cs @@ -0,0 +1,28 @@ +namespace TombLib.Scripting.Lua.Objects; + +/// +/// Identifies a source location for a Lua symbol reference. +/// +public sealed class LuaReferenceLocation +{ + /// + /// Initializes a new instance of the class. + /// + /// The file containing the reference. + /// The referenced range within the file. + public LuaReferenceLocation(string filePath, LuaDocumentRange range) + { + FilePath = filePath; + Range = range; + } + + /// + /// Gets the file containing the reference. + /// + public string FilePath { get; } + + /// + /// Gets the referenced range within the file. + /// + public LuaDocumentRange Range { get; } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaTextEdit.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaTextEdit.cs new file mode 100644 index 0000000000..7363c068e9 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaTextEdit.cs @@ -0,0 +1,28 @@ +namespace TombLib.Scripting.Lua.Objects; + +/// +/// Represents a single text replacement inside a Lua document. +/// +public sealed class LuaTextEdit +{ + /// + /// Initializes a new instance of the class. + /// + /// The range to replace. + /// The replacement text. + public LuaTextEdit(LuaDocumentRange range, string newText) + { + Range = range; + NewText = newText ?? string.Empty; + } + + /// + /// Gets the range to replace. + /// + public LuaDocumentRange Range { get; } + + /// + /// Gets the replacement text. + /// + public string NewText { get; } +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Objects/LuaWorkspaceEdit.cs b/TombLib/TombLib.Scripting.Lua/Objects/LuaWorkspaceEdit.cs new file mode 100644 index 0000000000..c3e98c050d --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua/Objects/LuaWorkspaceEdit.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace TombLib.Scripting.Lua.Objects; + +/// +/// Represents a workspace-wide set of Lua document edits. +/// +public sealed class LuaWorkspaceEdit +{ + /// + /// Initializes a new instance of the class. + /// + /// The per-document edits in the workspace change set. + public LuaWorkspaceEdit(IReadOnlyList documentEdits) + { + DocumentEdits = documentEdits ?? []; + } + + /// + /// Gets the per-document edits in the workspace change set. + /// + public IReadOnlyList DocumentEdits { get; } + + /// + /// Gets a value indicating whether the workspace edit contains any text edits. + /// + public bool HasEdits => DocumentEdits.Count > 0; +} \ No newline at end of file diff --git a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs index 49bb2eb55c..4785901f70 100644 --- a/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs +++ b/TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs @@ -17,6 +17,21 @@ public interface ILuaIntellisenseProvider : IDisposable /// bool IsAvailable { get; } + /// + /// Gets a value indicating whether the provider supports Lua symbol reference requests. + /// + bool SupportsReferences { get; } + + /// + /// Gets a value indicating whether the provider supports Lua symbol rename requests. + /// + bool SupportsRename { get; } + + /// + /// Gets a value indicating whether the provider supports Lua document formatting requests. + /// + bool SupportsFormatting { get; } + /// /// Occurs when diagnostics for a document have changed. /// @@ -106,6 +121,42 @@ Task> GetCompletionItemsAsync(string filePath, Task GetDefinitionAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default); + /// + /// Requests all known reference locations for a symbol at a position within a Lua document. + /// + /// The document path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// A token that can cancel the request. + /// The resolved reference locations, or an empty list when none are available. + Task> GetReferencesAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default); + + /// + /// Requests workspace edits to rename the symbol at a position within a Lua document. + /// + /// The document path. + /// The current document content. + /// The zero-based line index. + /// The zero-based column index. + /// The requested replacement symbol name. + /// A token that can cancel the request. + /// The workspace edit returned by the language server, or when none is available. + Task RenameSymbolAsync(string filePath, string content, + int line, int column, string newName, CancellationToken cancellationToken = default); + + /// + /// Requests formatting edits for a Lua document. + /// + /// The document path. + /// The current document content. + /// The editor formatting preferences to pass to the language server. + /// A token that can cancel the request. + /// The text edits returned by the language server, or an empty list when none are available. + Task> FormatDocumentAsync(string filePath, string content, + LuaFormattingOptions options, CancellationToken cancellationToken = default); + /// /// Requests signature help for a function call at a position within a Lua document. /// diff --git a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs index e3956a4581..eb69d7377d 100644 --- a/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs +++ b/TombLib/TombLib.Scripting/Bases/TextEditorBase.cs @@ -589,36 +589,43 @@ protected virtual void OnAutoClosingElementSkipped(string element) // TODO: Refactor public void CommentOutLines() + { + if (string.IsNullOrWhiteSpace(CommentPrefix)) + return; + + ApplyLineCommentTransformation(CommentLine); + } + + public void UncommentLines() + { + if (string.IsNullOrWhiteSpace(CommentPrefix)) + return; + + ApplyLineCommentTransformation(UncommentLine); + } + + public void ToggleCommentLines() + { + if (string.IsNullOrWhiteSpace(CommentPrefix)) + return; + + ApplyLineCommentTransformation(ShouldUncommentSelectedLines() ? UncommentLine : CommentLine); + } + + private void ApplyLineCommentTransformation(Func transformLine) { DocumentLine startLine = Document.GetLineByOffset(SelectionStart); DocumentLine endLine = Document.GetLineByOffset(SelectionStart + SelectionLength); int totalLineLength = 0; - var builder = new StringBuilder(); - for (int i = startLine.LineNumber; i <= endLine.LineNumber; i++) + for (int lineNumber = startLine.LineNumber; lineNumber <= endLine.LineNumber; lineNumber++) { - DocumentLine currentLine = Document.GetLineByNumber(i); + DocumentLine currentLine = Document.GetLineByNumber(lineNumber); string currentLineText = Document.GetText(currentLine.Offset, currentLine.Length); - var whitespaceBuilder = new StringBuilder(); - - for (int j = 0; j < currentLineText.Length; j++) - { - char c = currentLineText[j]; - - if (char.IsWhiteSpace(c)) - whitespaceBuilder.Append(c); - else - break; - } - - if (!string.IsNullOrWhiteSpace(currentLineText)) - builder.AppendLine(whitespaceBuilder.ToString() + CommentPrefix + currentLineText.TrimStart()); - else - builder.AppendLine(whitespaceBuilder.ToString()); - + builder.AppendLine(transformLine(currentLineText, CommentPrefix)); totalLineLength += currentLine.TotalLength; } @@ -628,44 +635,63 @@ public void CommentOutLines() Select(startLine.Offset, SelectionLength - 1); } - public void UncommentLines() + private bool ShouldUncommentSelectedLines() { DocumentLine startLine = Document.GetLineByOffset(SelectionStart); DocumentLine endLine = Document.GetLineByOffset(SelectionStart + SelectionLength); + bool foundCommentableLine = false; - int totalLineLength = 0; - - var builder = new StringBuilder(); - - for (int i = startLine.LineNumber; i <= endLine.LineNumber; i++) + for (int lineNumber = startLine.LineNumber; lineNumber <= endLine.LineNumber; lineNumber++) { - DocumentLine currentLine = Document.GetLineByNumber(i); + DocumentLine currentLine = Document.GetLineByNumber(lineNumber); string currentLineText = Document.GetText(currentLine.Offset, currentLine.Length); + string trimmedLineText = currentLineText.TrimStart(); - var whitespaceBuilder = new StringBuilder(); + if (string.IsNullOrWhiteSpace(trimmedLineText)) + continue; - for (int j = 0; j < currentLineText.Length; j++) - { - char c = currentLineText[j]; + foundCommentableLine = true; - if (char.IsWhiteSpace(c)) - whitespaceBuilder.Append(c); - else - break; - } + if (!trimmedLineText.StartsWith(CommentPrefix, StringComparison.Ordinal)) + return false; + } - if (currentLineText.TrimStart().StartsWith(CommentPrefix)) - builder.AppendLine(whitespaceBuilder.ToString() + currentLineText.TrimStart().Remove(0, CommentPrefix.Length)); - else - builder.AppendLine(currentLineText); + return foundCommentableLine; + } - totalLineLength += currentLine.TotalLength; - } + private static string CommentLine(string currentLineText, string commentPrefix) + { + string leadingWhitespace = GetLeadingWhitespace(currentLineText); + return !string.IsNullOrWhiteSpace(currentLineText) + ? leadingWhitespace + commentPrefix + currentLineText.TrimStart() + : leadingWhitespace; + } - Select(startLine.Offset, totalLineLength); - SelectedText = builder.ToString(); + private static string UncommentLine(string currentLineText, string commentPrefix) + { + string leadingWhitespace = GetLeadingWhitespace(currentLineText); + string trimmedLineText = currentLineText.TrimStart(); - Select(startLine.Offset, SelectionLength - 1); + return trimmedLineText.StartsWith(commentPrefix, StringComparison.Ordinal) + ? leadingWhitespace + trimmedLineText.Remove(0, commentPrefix.Length) + : currentLineText; + } + + private static string GetLeadingWhitespace(string currentLineText) + { + var whitespaceBuilder = new StringBuilder(); + + for (int index = 0; index < currentLineText.Length; index++) + { + char character = currentLineText[index]; + + if (char.IsWhiteSpace(character)) + whitespaceBuilder.Append(character); + else + break; + } + + return whitespaceBuilder.ToString(); } #endregion Multiline commenting diff --git a/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs b/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs index 17dd8318d7..5ed548f227 100644 --- a/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs +++ b/TombLib/TombLib.Test/LuaEditorCompletionWindowTests.cs @@ -310,6 +310,9 @@ private sealed class FakeLuaCompletionProvider : ILuaIntellisenseProvider private readonly Queue> _completionResponses = []; public bool IsAvailable { get; set; } = true; + public bool SupportsReferences => false; + public bool SupportsRename => false; + public bool SupportsFormatting => false; public List CompletionRequests { get; } = []; @@ -366,6 +369,18 @@ public Task> GetCompletionItemsAsync(string fil int line, int column, CancellationToken cancellationToken = default) => Task.FromResult(null); + public Task> GetReferencesAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + => Task.FromResult>([]); + + public Task RenameSymbolAsync(string filePath, string content, + int line, int column, string newName, CancellationToken cancellationToken = default) + => Task.FromResult(null); + + public Task> FormatDocumentAsync(string filePath, string content, + LuaFormattingOptions options, CancellationToken cancellationToken = default) + => Task.FromResult>([]); + public Task GetSignatureHelpAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) => Task.FromResult(null); diff --git a/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs index f0e7e80a38..9792a83b62 100644 --- a/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs +++ b/TombLib/TombLib.Test/LuaEditorIntellisenseStateTests.cs @@ -867,6 +867,9 @@ private static void SetSignatureHelpField(LuaEditor editor, string fieldName, ob private sealed class FakeLuaIntellisenseProvider : ILuaIntellisenseProvider { public bool IsAvailable { get; set; } = true; + public bool SupportsReferences => false; + public bool SupportsRename => false; + public bool SupportsFormatting => false; public LuaHoverInfo? HoverResponse { get; set; } @@ -927,6 +930,18 @@ public Task> GetCompletionItemsAsync(string fil return Task.FromResult(DefinitionResponse); } + public Task> GetReferencesAsync(string filePath, string content, + int line, int column, CancellationToken cancellationToken = default) + => Task.FromResult>([]); + + public Task RenameSymbolAsync(string filePath, string content, + int line, int column, string newName, CancellationToken cancellationToken = default) + => Task.FromResult(null); + + public Task> FormatDocumentAsync(string filePath, string content, + LuaFormattingOptions options, CancellationToken cancellationToken = default) + => Task.FromResult>([]); + public Task GetSignatureHelpAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { diff --git a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs index 7d4def92ce..c997787e21 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs @@ -48,6 +48,26 @@ public void CaptureServerCapabilities_RejectsMissingDocumentChangeSupport() Assert.IsInstanceOfType(exception.InnerException, typeof(NotSupportedException)); } + [TestMethod] + public void CaptureServerCapabilities_RecognizesReferenceRenameAndFormattingProviders() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + + InvokePrivateMethod(client, "CaptureServerCapabilities", JsonSerializer.SerializeToElement(new + { + capabilities = new + { + referencesProvider = new { }, + renameProvider = new { prepareProvider = true }, + documentFormattingProvider = true + } + })); + + Assert.IsTrue(client.SupportsReferences); + Assert.IsTrue(client.SupportsRename); + Assert.IsTrue(client.SupportsFormatting); + } + [TestMethod] public void Dispose_WritesGracefulShutdownMessages() { diff --git a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs index 61f62abc3e..8c4e90cf18 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs @@ -105,6 +105,71 @@ public async Task GetCompletionItemsAsync_ResolvePreservesOriginalInsertionMetad Assert.AreEqual("Spawn docs.", resolvedItem.Description); } + [TestMethod] + public async Task FormatDocumentAsync_ReturnsFormattingEditsAndPassesEditorOptions() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value=1"; + + using var client = new FakeLuaLanguageServerClient + { + SupportsFormatting = true, + FormattingResponse = JsonSerializer.SerializeToElement(new object[] + { + new + { + range = new + { + start = new { line = 0, character = 0 }, + end = new { line = 0, character = 0 } + }, + newText = "local value = 1\r\n" + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + IReadOnlyList edits = await provider.FormatDocumentAsync(filePath, content, + new LuaFormattingOptions(tabSize: 3, insertSpaces: false)); + + Assert.AreEqual(1, edits.Count); + Assert.AreEqual("local value = 1\r\n", edits[0].NewText); + + JsonElement parameters = client.GetLastRequestParameters("textDocument/formatting"); + + Assert.AreEqual(new Uri(filePath).AbsoluteUri, parameters.GetProperty("textDocument").GetProperty("uri").GetString()); + Assert.AreEqual(3, parameters.GetProperty("options").GetProperty("tabSize").GetInt32()); + Assert.IsFalse(parameters.GetProperty("options").GetProperty("insertSpaces").GetBoolean()); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/formatting" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task FormatDocumentAsync_ReturnsEmptyWhenFormattingIsUnsupported() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + SupportsFormatting = false + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + IReadOnlyList edits = await provider.FormatDocumentAsync(filePath, "local value=1", + new LuaFormattingOptions(tabSize: 4, insertSpaces: true)); + + Assert.AreEqual(0, edits.Count); + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen" }, + client.GetSentMethodNames()); + } + [TestMethod] public async Task DispatchWorkspaceFileChangesAsync_RefreshesConfigurationWhenApiLibraryChanges() { @@ -835,6 +900,7 @@ private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient { private readonly object _syncRoot = new(); private readonly List<(string Method, JsonElement Parameters)> _sentNotifications = []; + private readonly List<(string Method, JsonElement Parameters)> _sentRequests = []; private readonly List _sentMethodNames = []; private readonly Queue _semanticTokensDeltaResponses = []; private readonly Queue _semanticTokensFullResponses = []; @@ -847,11 +913,15 @@ private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient public bool StartResult { get; set; } = true; public JsonElement CompletionResponse { get; set; } public JsonElement CompletionResolveResponse { get; set; } + public JsonElement FormattingResponse { get; set; } public JsonElement HoverResponse { get; set; } public LuaTextDocumentSyncKind TextDocumentSyncKind { get; set; } = LuaTextDocumentSyncKind.Incremental; public IReadOnlyList SemanticTokenTypes { get; set; } = []; public IReadOnlyList SemanticTokenModifiers { get; set; } = []; public bool SupportsCompletionResolve { get; set; } + public bool SupportsReferences { get; set; } = true; + public bool SupportsRename { get; set; } = true; + public bool SupportsFormatting { get; set; } = true; public bool SupportsSemanticTokensDelta { get; set; } public bool FailStartWhenCancellationRequested { get; set; } public int StartCallCount { get; private set; } @@ -917,7 +987,10 @@ public Task SendNotificationAsync(string method, object parameters, Cancellation public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) { lock (_syncRoot) + { _sentMethodNames.Add(method); + _sentRequests.Add((method, JsonSerializer.SerializeToElement(parameters))); + } if (method == "textDocument/hover") { @@ -937,6 +1010,9 @@ public Task SendRequestAsync(string method, object parameters, Canc if (method == "completionItem/resolve" && CompletionResolveResponse.ValueKind != JsonValueKind.Undefined) return Task.FromResult(CompletionResolveResponse); + if (method == "textDocument/formatting" && FormattingResponse.ValueKind != JsonValueKind.Undefined) + return Task.FromResult(FormattingResponse); + if (method == "textDocument/semanticTokens/full/delta") { if (_semanticTokensDeltaResponses.Count > 0) @@ -984,6 +1060,20 @@ public JsonElement GetLastNotificationParameters(string method) throw new InvalidOperationException($"Notification '{method}' was not observed."); } + public JsonElement GetLastRequestParameters(string method) + { + lock (_syncRoot) + { + for (int i = _sentRequests.Count - 1; i >= 0; i--) + { + if (string.Equals(_sentRequests[i].Method, method, StringComparison.Ordinal)) + return _sentRequests[i].Parameters; + } + } + + throw new InvalidOperationException($"Request '{method}' was not observed."); + } + public void BlockNextOpenNotification() => _openNotificationGate = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); diff --git a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs index aeabfe443b..166d733dc3 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs @@ -204,6 +204,129 @@ public void ParseDefinitionLocation_UsesTargetSelectionRangeFromLocationLink() Assert.AreEqual(3, location.ColumnNumber); } + [TestMethod] + public void ParseReferenceLocations_ParsesFileReferenceRanges() + { + string targetPath = Path.GetFullPath(@"C:\Workspace\Scripts\references.lua"); + + IReadOnlyList locations = LuaLanguageServerResponseParser.ParseReferenceLocations( + JsonSerializer.SerializeToElement(new object[] + { + new + { + uri = new Uri(targetPath).AbsoluteUri, + range = new + { + start = new { line = 2, character = 4 }, + end = new { line = 2, character = 9 } + } + }, + new + { + uri = "https://example.com/not-a-file.lua", + range = new + { + start = new { line = 0, character = 0 }, + end = new { line = 0, character = 1 } + } + } + })); + + Assert.AreEqual(1, locations.Count); + Assert.AreEqual(targetPath, locations[0].FilePath); + Assert.AreEqual(3, locations[0].Range.StartLineNumber); + Assert.AreEqual(5, locations[0].Range.StartColumnNumber); + Assert.AreEqual(3, locations[0].Range.EndLineNumber); + Assert.AreEqual(10, locations[0].Range.EndColumnNumber); + } + + [TestMethod] + public void ParseWorkspaceEdit_MergesChangeMapAndDocumentChanges() + { + string firstPath = Path.GetFullPath(@"C:\Workspace\Scripts\first.lua"); + string secondPath = Path.GetFullPath(@"C:\Workspace\Scripts\second.lua"); + + LuaWorkspaceEdit? workspaceEdit = LuaLanguageServerResponseParser.ParseWorkspaceEdit( + JsonSerializer.SerializeToElement(new + { + changes = new Dictionary + { + [new Uri(firstPath).AbsoluteUri] = + [ + new + { + range = new + { + start = new { line = 0, character = 0 }, + end = new { line = 0, character = 5 } + }, + newText = "local" + } + ] + }, + documentChanges = new object[] + { + new + { + textDocument = new { uri = new Uri(secondPath).AbsoluteUri }, + edits = new object[] + { + new + { + range = new + { + start = new { line = 3, character = 1 }, + end = new { line = 3, character = 4 } + }, + newText = "name" + } + } + } + } + })); + + Assert.IsNotNull(workspaceEdit); + Assert.AreEqual(2, workspaceEdit.DocumentEdits.Count); + Assert.AreEqual(firstPath, workspaceEdit.DocumentEdits[0].FilePath); + Assert.AreEqual("local", workspaceEdit.DocumentEdits[0].TextEdits[0].NewText); + Assert.AreEqual(secondPath, workspaceEdit.DocumentEdits[1].FilePath); + Assert.AreEqual("name", workspaceEdit.DocumentEdits[1].TextEdits[0].NewText); + } + + [TestMethod] + public void ParseDocumentFormattingEdits_ParsesFormattingTextEdits() + { + IReadOnlyList textEdits = LuaLanguageServerResponseParser.ParseDocumentFormattingEdits( + JsonSerializer.SerializeToElement(new object[] + { + new + { + range = new + { + start = new { line = 0, character = 0 }, + end = new { line = 0, character = 0 } + }, + newText = "local value = 1\r\n" + }, + new + { + range = new + { + start = new { line = 1, character = 0 }, + end = new { line = 1, character = 4 } + }, + newText = " " + } + })); + + Assert.AreEqual(2, textEdits.Count); + Assert.AreEqual("local value = 1\r\n", textEdits[0].NewText); + Assert.AreEqual(1, textEdits[0].Range.StartLineNumber); + Assert.AreEqual(1, textEdits[0].Range.StartColumnNumber); + Assert.AreEqual(2, textEdits[1].Range.StartLineNumber); + Assert.AreEqual(5, textEdits[1].Range.EndColumnNumber); + } + [TestMethod] public void ParseSignatureHelp_UsesParameterLabelOffsetsAndActiveParameter() { From 0475702fbef2639fb6723957b7f8d2f5cd138e18 Mon Sep 17 00:00:00 2001 From: Kewin Kupilas Date: Mon, 11 May 2026 00:12:01 +0100 Subject: [PATCH 34/34] Cleanups --- LuaLS_Production_Readiness_Plan.md | 478 ----------------- LuaLS_ScriptingStudio_Features_Plan.md | 361 ------------- ...ntellisense_And_AvalonEdit_Cleanup_Plan.md | 344 ------------ Tomb Editor.sln | 11 + .../LuaStudio.Intellisense.cs | 3 +- TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs | 1 - .../Completion/LuaSnippetPlaceholderResult.cs | 6 - .../LuaDocumentSynchronizationResult.cs | 10 - .../LuaLanguageServerResponseParser.Hover.cs | 24 - .../LuaLanguageServerClient.Protocol.cs | 224 -------- .../LuaLanguageServerClient.Transport.cs | 372 ------------- .../Pathing => }/LuaLanguageServerLocator.cs | 0 ...LanguageServerResponseParser.Navigation.cs | 80 --- .../Services/LuaIntellisense/README.md | 49 -- ...LanguageServerResponseParser.References.cs | 89 ---- .../LuaLanguageServerResponseParser.Rename.cs | 148 ------ .../LuaSemanticTokensDeltaState.cs | 8 - ...guageServerResponseParser.SignatureHelp.cs | 125 ----- .../TombIDE.ScriptingStudio.csproj | 1 + .../Completion/LuaCompletionPayloads.cs | 106 ++++ ...LanguageServerResponseParser.Completion.cs | 162 ++---- .../Completion/LuaSnippetPlaceholderResult.cs | 6 + .../LuaLanguageServerDiagnosticsParser.cs | 82 +-- .../Diagnostics/LuaPublishedDiagnostics.cs | 7 +- .../Documents/LuaDocumentLineOffsets.cs | 9 +- .../Documents/LuaDocumentRenameRequest.cs | 8 +- .../Documents/LuaDocumentSnapshot.cs | 6 +- .../LuaDocumentSynchronizationKind.cs | 6 +- .../LuaDocumentSynchronizationRequest.cs | 10 +- .../LuaDocumentSynchronizationResult.cs | 6 + .../Documents/LuaIncrementalEditCalculator.cs | 9 +- .../LuaIntellisenseDocumentManager.cs | 39 +- .../Documents/LuaTextDocumentSyncKind.cs | 6 +- ...LanguageServerResponseParser.Formatting.cs | 14 +- .../Hover/LuaHoverPayloads.cs | 13 + .../LuaLanguageServerResponseParser.Hover.cs | 22 + .../Client/ILuaLanguageServerClient.cs | 21 +- .../LuaLanguageServerCallbackPayloads.cs | 46 ++ .../LuaLanguageServerCapabilityPayloads.cs | 195 +++++++ .../LuaLanguageServerClient.Diagnostics.cs | 86 +++ .../LuaLanguageServerClient.Protocol.cs | 146 +++++ .../Client/LuaLanguageServerClient.cs | 346 ++++++------ .../Pathing/LuaLanguageServerPathHelper.cs | 29 +- .../LuaLanguageServerSettingsFactory.cs | 8 +- .../LuaLanguageServerStartupFailure.cs | 8 +- .../Startup/LuaProcessJobObject.cs | 15 +- .../Workspace/LuaWorkspaceFileWatcher.cs | 27 +- .../Workspace/LuaWorkspaceWatcherFailure.cs | 6 +- .../LuaLanguageServerResponseParser.Shared.cs | 40 +- .../LuaTextEditPayloads.cs | 24 + .../Navigation/LuaDefinitionPayloads.cs | 82 +++ ...LanguageServerResponseParser.Navigation.cs | 24 + .../Properties/AssemblyInfo.cs | 3 + .../Properties/InternalsVisibleTo.cs | 3 + ...ageServerIntellisenseProvider.Documents.cs | 143 ++--- ...uageServerIntellisenseProvider.Requests.cs | 217 ++++---- ...rverIntellisenseProvider.SemanticTokens.cs | 41 +- .../LuaLanguageServerIntellisenseProvider.cs | 59 ++- .../LuaLanguageServerNotificationPayloads.cs | 42 ++ .../LuaLanguageServerRequestPayloads.cs | 55 ++ ...LanguageServerResponseParser.References.cs | 36 ++ .../References/LuaReferencePayloads.cs | 15 + .../LuaLanguageServerResponseParser.Rename.cs | 106 ++++ ...LanguageServerSemanticTokensDeltaParser.cs | 65 +-- .../LuaSemanticTokensDecodeResult.cs | 9 +- .../LuaSemanticTokensDeltaState.cs | 6 + .../LuaSemanticTokensPayloads.cs | 16 + ...guageServerResponseParser.SignatureHelp.cs | 95 ++++ .../SignatureHelp/LuaSignatureHelpPayloads.cs | 43 ++ ...ombLib.Scripting.Lua.LanguageServer.csproj | 19 + TombLib/TombLib.Scripting.Lua/README.md | 28 - .../GlobalUsings.LuaLanguageServer.cs | 1 + .../LuaIntellisenseDocumentManagerTests.cs | 16 + .../LuaLanguageServerClientTests.cs | 401 +++++++------- ...LuaLanguageServerDiagnosticsParserTests.cs | 34 +- ...LanguageServerIntellisenseProviderTests.cs | 499 ++++++++++++++++-- .../LuaLanguageServerResponseParserTests.cs | 51 +- TombLib/TombLib.Test/TombLib.Test.csproj | 1 + 78 files changed, 2544 insertions(+), 3408 deletions(-) delete mode 100644 LuaLS_Production_Readiness_Plan.md delete mode 100644 LuaLS_ScriptingStudio_Features_Plan.md delete mode 100644 Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Transport.cs rename TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/{Infrastructure/Pathing => }/LuaLanguageServerLocator.cs (100%) delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Navigation/LuaLanguageServerResponseParser.Navigation.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs delete mode 100644 TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaCompletionPayloads.cs rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Completion/LuaLanguageServerResponseParser.Completion.cs (68%) create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaSnippetPlaceholderResult.cs rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Diagnostics/LuaLanguageServerDiagnosticsParser.cs (71%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Diagnostics/LuaPublishedDiagnostics.cs (87%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaDocumentLineOffsets.cs (95%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaDocumentRenameRequest.cs (56%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaDocumentSnapshot.cs (90%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaDocumentSynchronizationKind.cs (72%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaDocumentSynchronizationRequest.cs (66%) create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationResult.cs rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaIncrementalEditCalculator.cs (94%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaIntellisenseDocumentManager.cs (90%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Documents/LuaTextDocumentSyncKind.cs (77%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Formatting/LuaLanguageServerResponseParser.Formatting.cs (54%) create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaHoverPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaLanguageServerResponseParser.Hover.cs rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Client/ILuaLanguageServerClient.cs (86%) create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCallbackPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCapabilityPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Diagnostics.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Client/LuaLanguageServerClient.cs (69%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs (78%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs (86%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs (54%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Startup/LuaProcessJobObject.cs (92%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs (92%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs (53%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/LuaLanguageServerResponseParser.Shared.cs (70%) create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/LuaTextEditPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaDefinitionPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaLanguageServerResponseParser.Navigation.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/AssemblyInfo.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/InternalsVisibleTo.cs rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs (72%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs (63%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs (84%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/Provider/LuaLanguageServerIntellisenseProvider.cs (89%) create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerNotificationPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerRequestPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaLanguageServerResponseParser.References.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaReferencePayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/Rename/LuaLanguageServerResponseParser.Rename.cs rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs (71%) rename {TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense => TombLib/TombLib.Scripting.Lua.LanguageServer}/SemanticTokens/LuaSemanticTokensDecodeResult.cs (55%) create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensDeltaState.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaSignatureHelpPayloads.cs create mode 100644 TombLib/TombLib.Scripting.Lua.LanguageServer/TombLib.Scripting.Lua.LanguageServer.csproj delete mode 100644 TombLib/TombLib.Scripting.Lua/README.md create mode 100644 TombLib/TombLib.Test/GlobalUsings.LuaLanguageServer.cs diff --git a/LuaLS_Production_Readiness_Plan.md b/LuaLS_Production_Readiness_Plan.md deleted file mode 100644 index e99913b3b4..0000000000 --- a/LuaLS_Production_Readiness_Plan.md +++ /dev/null @@ -1,478 +0,0 @@ -# Lua IntelliSense Production Readiness Plan - -## Scope -This document is a clean-room handoff for the next agent. It re-verifies the current Lua IntelliSense concerns against the codebase as it exists now and turns them into a phased implementation plan. - -Date: 2026-05-09. - -## Executive Summary -The current blocker set is narrower than the original checklist, but a few items are real production-readiness problems and should be treated as the first slice: - -- LuaLS request timeouts do not trigger recovery, so a hung server can leave IntelliSense dead until restart. -- Old transport loops can still interact with the shared pending-request map after restart. -- Save As / external rename do not rebind tracked IntelliSense documents to the new path. -- Completion insertion does not honor LSP `textEdit` replacement semantics. -- Signature help dismissal and refresh are incomplete enough to produce visible UX failures. -- Stale diagnostics and semantic tokens survive normal edits until the delayed sync fires, which explains the shifted underline / stale color complaints better than a pure TextMate failure. - -The Lua indentation complaints are also real, but they belong in the completion / Enter-handling phase rather than the transport phase. - -## Re-Verification Matrix - -### 1. LuaLS Startup, Transport, And Recovery - -#### Concern: repeated request timeouts leave IntelliSense permanently dead. -Verdict: verified blocker. - -Evidence: - -- [SendBoundedRequestAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs#L185) times out after 10 seconds, logs, and returns `default`. -- That path does not mark the client unhealthy, invalidate startup state, or trigger restart. -- Restart today depends on `_client.IsReady` becoming false, which a hung but still-running process will not do. - -#### Concern: a restarted LuaLS receives all currently open documents again. -Verdict: already implemented and worth preserving. - -Evidence: - -- [EnsureStartedAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs#L159) calls `_documents.PrepareForRestart()` and then [ReopenTrackedDocumentsAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs#L102). -- Existing coverage: [GetHoverAsync_ReplaysTrackedDocumentsAfterLanguageServerRestart](TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs#L153). - -#### Concern: stale / old process read loops cannot fail requests belonging to a newer process. -Verdict: verified blocker. - -Evidence: - -- The client keeps one shared `_pendingRequests` map in [LuaLanguageServerClient](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L35). -- Requests are added in [SendRequestCoreAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Protocol.cs#L17). -- Old read loops can still call [FailPendingRequests](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L480) from [ReadLoopAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs#L18) after restart. -- `ResetProcessState()` clears streams and task references, but it does not replace the pending-request store or scope failures to a transport generation. - -#### Concern: disposal of LuaLS hangs on stderr / diagnostic pumps / background loops. -Verdict: not a blocker, but keep an eye on it. - -Evidence: - -- [Dispose](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L559) cancels lifetime, fails pending requests, and waits with [DisposeWaitTimeout](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L21). -- [WaitForBackgroundLoopsAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L506) is timeout-bounded and logs rather than hanging indefinitely. - -### 2. Document Lifetime And Tab Ownership - -#### Concern: Save As / rename must move diagnostics, semantic tokens, hover, completion, and definition to the new path. -Verdict: verified blocker. - -Evidence: - -- [SaveFileAs(TabPage)](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L363) directly changes `editor.FilePath` and saves, but it does not tell IntelliSense to close the old URI and open the new one. -- [RenameDocumentTabPage](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L691) also rewrites `editor.FilePath` only. -- Lua editors are wired through [LuaStudio.Intellisense.cs](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L76), but there is no rename/rekey hook. - -#### Concern: request-only hover / definition / signature documents are closed afterward. -Verdict: not a current UI blocker. - -Evidence: - -- Request paths use `acquireOpenReference: false` in [SendPositionRequestAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs#L145). -- In the actual UI flow, Lua editors are opened through [EditorTabControl_LuaFileOpened](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L76), which already calls `OpenDocument`. -- A non-UI caller could still create a request-only tracked document, but that is not the dominant production path. - -#### Concern: closing a tab while requests are in flight must not update a disposed editor. -Verdict: mixed. - -Evidence: - -- Completion and hover cancel tokens on unload in [LuaEditor_Unloaded](TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs#L60). -- Signature help and definition navigation still lack the same level of stale-result guarding. - -### 3. Stale Async Editor Requests - -#### Concern: stale completion / hover / signature / definition responses should be discarded after edits. -Verdict: partially verified, still missing in important paths. - -Evidence: - -- Completion uses `_completionRequestToken` in [RequestCompletionAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.Completion.cs#L92). -- Hover uses `_hoverRequestToken` in [HandleMouseHover](TombLib/TombLib.Scripting.Lua/LuaEditor.Hover.cs#L27). -- Signature help in [RequestSignatureHelpAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs#L146) has cancellation only, no request-generation token. -- Definition navigation in [TryNavigateToDefinitionAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs#L55) has no generation/version guard at all. - -### 4. Completion Insertion - -#### Concern: `textEdit.range`, `textEdit.insert`, and `textEdit.replace` must be honored. -Verdict: verified blocker. - -Evidence: - -- [ParseCompletionItem](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs#L145) reads `textEdit.newText` only. -- It ignores `textEdit.range`, `textEdit.insert`, and `textEdit.replace` entirely. -- [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117) always replaces AvalonEdit's `completionSegment`, not an LSP-provided edit range. - -#### Concern: text edits must not apply after the document version changed. -Verdict: verified gap. - -Evidence: - -- `LuaCompletionItem` has no document version or request-generation metadata in [LuaCompletionItem](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionItem.cs#L10). -- `LuaCompletionData.Complete` has no stale-version guard. - -#### Concern: snippets, `$0`, multiline insertion, and caret placement are correct. -Verdict: not correct if snippet or multiline completion text reaches the editor. - -Evidence: - -- [StripSnippetPlaceholders](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs#L359) strips `$1`, `${1:default}`, and `$0`, but it does not preserve caret intent. -- [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117) inserts plain text only. -- There is no Lua-aware multiline reindent pass anywhere in [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L562) or [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs#L10). - -Important nuance: - -- The client advertises `snippetSupport = false` in [LuaLanguageServerClient](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs#L280). -- Settings also set `callSnippet = "Disable"` in [LuaLanguageServerSettingsFactory](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerSettingsFactory.cs#L34). -- That lowers the frequency of snippet-shaped results, but it does not make the current insertion code correct if LuaLS still emits keyword snippets or multiline `newText`. - -#### Concern: completion-item resolve must preserve insertion text and ranges. -Verdict: future implementation requirement. - -Evidence: - -- Resolve reparses a new `LuaCompletionItem` in [ResolveCompletionItemAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs#L116). -- Once range metadata is added, resolve must merge detail/documentation onto the unresolved insertion metadata rather than replacing it blindly. - -### 5. Lua Enter / Indentation Strategy - -#### Concern: pressing Enter after `then` is missing one extra indent level. -Verdict: verified missing feature. - -Evidence: - -- [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L562) only implements bracket / quote auto-closing. -- There is no Lua-specific Enter handler, indentation strategy, or block-aware newline logic in [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs#L10) or its partials. - -#### Concern: `if ... then ... end` autocomplete puts `end` at the wrong indentation. -Verdict: verified gap for any multiline completion text. - -Evidence: - -- Multiline completion text is inserted verbatim by [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117). -- No reindent or caret-placement normalization exists before or after insertion. - -### 6. Signature Help And Navigation UX - -#### Concern: closing a method with `)` should dismiss signature help. -Verdict: verified UX bug. - -Evidence: - -- Lua dismisses signature help on `)` only in [TextArea_TextEntered](TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs#L104). -- The base editor can consume `)` earlier in [TryPerformElementSkip](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L596) when skipping over an auto-inserted close paren. -- That means the editor can move past `)` without the Lua-specific dismissal path running. - -#### Concern: signature help argument highlighting can desync. -Verdict: verified high-priority issue. - -Evidence: - -- Signature refresh happens on `(`, `,`, Backspace, and Delete only. See [TextArea_TextEntered](TombLib/TombLib.Scripting.Lua/LuaEditor.Intellisense.cs#L87) and [TextEditor_KeyDown](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs#L21). -- Normal typing inside an argument list does not refresh signature help. -- Signature help also lacks a request token in [RequestSignatureHelpAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.SignatureHelp.cs#L146), so stale responses can repaint older active-parameter state. - -#### Concern: go-to-definition should not act on stale results. -Verdict: verified hardening need. - -Evidence: - -- [TryNavigateToDefinitionAsync](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs#L55) has no generation or version check before invoking `DefinitionNavigationRequested`. - -### 7. Semantic Tokens, Syntax Coloring, And Diagnostic Lag - -#### Concern: quick edits like `local -> locl -> local` break colors, possibly due to autocomplete popup interaction. -Verdict: partially reclassified. - -Verified part: - -- Stale semantic tokens remain visible until the delayed document sync runs, because edits do not immediately clear semantic overlays. -- Lua semantic tokens are updated only after [TextChangedDelayed](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L92), which is driven by the 300 ms timer in [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L185). -- `ClearSemanticTokens()` is called on unload only, not on ordinary edits. See [LuaEditor.SemanticHighlighting](TombLib/TombLib.Scripting.Lua/LuaEditor.SemanticHighlighting.cs#L16). - -Not directly proven: - -- The TextMate path itself looks change-driven and should retokenize lines through [TextMateDocumentLineList](TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs#L48) and [TextMateColorizingTransformer](TombLib/TombLib.Scripting/Highlighting/TextMateColorizingTransformer.cs#L24). -- There is no strong code evidence that the completion popup itself blocks TextMate recoloring. - -Working conclusion: - -- Treat the reported recolor bug primarily as stale semantic-token / stale overlay behavior until a concrete TextMate-only repro proves otherwise. - -#### Concern: errors should clear immediately on text change because underlines can shift. -Verdict: verified high-priority UX defect. - -Evidence: - -- [TextEditor_TextChanged](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs#L269) only marks content changed and restarts the delayed timer. -- Diagnostics are not cleared on edit. -- Provider-side diagnostics are refreshed only through [LuaEditor_TextChangedDelayed](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs#L92). - -#### Concern: semantic-token version association / stale overwrite after rapid edits. -Verdict: normal version gating is present, but stale-visibility still exists. - -Evidence: - -- [TryStoreSemanticTokens](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaIntellisenseDocumentManager.cs#L216) rejects older token versions. -- However, the old tokens remain painted until a newer token set arrives or the editor clears them. - -#### Concern: failed semantic-token delta requests should preserve or clear state intentionally. -Verdict: verified hardening issue. - -Evidence: - -- On delta failure, [DecodeSemanticTokensResponse](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs#L89) can return `previousData` paired with a new `resultId`. -- That is internally inconsistent and should be replaced by a forced full refresh path. - -### 8. TextMate And Highlighting Fallback - -#### Concern: Lua should remain highlighted if TextMate grammar install fails. -Verdict: verified gap in the main editor. - -Evidence: - -- [LuaTextMateSyntaxHighlighting.TryInstall](TombLib/TombLib.Scripting/Highlighting/LuaTextMateSyntaxHighlighting.cs#L14) returns false when grammar load fails. -- [LuaEditor.UpdateSettings](TombLib/TombLib.Scripting.Lua/LuaEditor.cs#L51) always sets `SyntaxHighlighting = null` after trying TextMate. -- Markdown tooltips do have a fallback in [MarkdownToolTipRenderer](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L309), but the main editor does not. - -### 9. Tooltips, Watcher, Disposal, And Packaging - -#### Concern: tooltip embedded editors can steal focus. -Verdict: worth hardening. - -Evidence: - -- The FlowDocument viewer and hyperlinks are made non-focusable in [MarkdownToolTipRenderer](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L85) and [MarkdownToolTipRenderer](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L218). -- The embedded `TextEditor` created in [CreateCodeBlockElement](TombLib/TombLib.Scripting/Rendering/MarkdownToolTipRenderer.cs#L309) is read-only but not explicitly made non-focusable. - -#### Concern: watcher recovery / disposal safety. -Verdict: watch coverage is good, disposal race is real, recovery behavior is limited. - -Evidence: - -- The watcher covers `*.lua`, `.API`, and `.luarc.*` in [LuaWorkspaceFileWatcher.Start](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs#L43). -- [DispatchPendingChangesAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaWorkspaceFileWatcher.cs#L131) can still be in flight while `Dispose()` disposes `_dispatchGate`. -- `Error` currently logs only; it does not restart or visibly disable the watcher. - -#### Concern: event subscribers throwing exceptions should not starve others. -Verdict: mixed. - -Evidence: - -- Startup failures are protected in [ReportStartupFailure](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.cs#L320). -- The client diagnostics pump isolates handler exceptions in [PumpDiagnosticsAsync](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.Transport.cs#L301). -- Provider fan-out for [DiagnosticsUpdated](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Documents.cs#L271) and [SemanticTokensUpdated](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs#L59) is not wrapped. - -#### Concern: LuaLS attribution when bundled. -Verdict: verified documentation gap, not installer blocker. - -Evidence: - -- Bundling is build-backed in [TombIDE.Shared.csproj](TombIDE/TombIDE.Shared/TombIDE.Shared.csproj#L9). -- [ExternalResources.md](ExternalResources.md) does not currently list LuaLS. - -## Phase Plan - -### Phase 1: Transport Resilience Blockers -Goal: make restarts safe and automatic when LuaLS becomes unhealthy. - -Tasks: - -- Add a transport generation / session concept in [LuaLanguageServerClient](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerClient.cs). -- Scope pending requests and read-loop failure propagation to that generation. -- Ensure an old read loop or process exit cannot fault requests created by a newer process. -- Add timeout health tracking in [LuaLanguageServerIntellisenseProvider.Requests.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.Requests.cs). -- Restart after a small threshold of consecutive request timeouts on the same generation. -- Preserve the existing tracked-document replay path. - -Tests: - -- Extend [LuaLanguageServerClientTests](TombLib/TombLib.Test/LuaLanguageServerClientTests.cs). -- Extend [LuaLanguageServerIntellisenseProviderTests](TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs). -- Add tests for timeout-triggered restart, document replay, and old-generation isolation. - -### Phase 2: Document Identity And Path Ownership -Goal: keep all IntelliSense state attached to the real file path. - -Tasks: - -- Add a provider-level rename / rekey API rather than hand-rolling `CloseDocument` + `OpenDocument` in multiple UI call sites. -- Wire Save As in [EditorTabControl.SaveFileAs(TabPage)](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L363). -- Wire external rename in [EditorTabControl.RenameDocumentTabPage](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs#L691). -- Preserve diagnostics / semantic-token cache ownership when the path changes. - -Tests: - -- Save As of an open Lua file. -- External rename of an open Lua file. -- Multiple tabs referencing the same Lua file. - -### Phase 3: Editor Request Freshness And Signature UX -Goal: stale results must never drive UI. - -Tasks: - -- Add a signature request token similar to completion / hover. -- Refresh signature help on more than `(`, `,`, Backspace, and Delete. -- Dismiss signature help when `)` is typed or skipped over through the base auto-close path. -- Make signature-help and definition-result application no-op once the editor has unloaded or is otherwise no longer valid. -- Add a generation / version guard to definition navigation. -- Keep the policy as cancel-and-discard rather than allow-finish-and-apply. - -Tests: - -- Typing `)` after an auto-inserted close paren dismisses signature help. -- Typing and deleting inside an argument list refreshes the highlighted parameter. -- Closing a tab during an in-flight signature or definition request does not reopen UI or navigate. -- Editing before a definition response returns does not navigate. - -### Phase 4: Completion Insertion Correctness -Goal: completion insertion must match LSP semantics, not AvalonEdit guesses. - -Tasks: - -- Extend `LuaCompletionItem` with edit metadata: document version, request generation, and edit range information. -- Parse `textEdit.range` and `InsertReplaceEdit` (`insert` / `replace`) in [LuaLanguageServerResponseParser.Completion.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Completion.cs#L145). -- Apply those ranges in [LuaCompletionData.Complete](TombLib/TombLib.Scripting.Lua/Objects/LuaCompletionData.cs#L117). -- Reject stale completion application after a relevant document version change. -- When resolve is used, merge resolved detail/documentation into the unresolved insertion metadata. - -Tests: - -- Range replacement. -- Insert-vs-replace behavior. -- Stale version rejection. -- Resolve preserving insertion semantics. - -### Phase 5: Lua Indentation And Multiline Completion Behavior -Goal: Lua should indent blocks correctly whether the user presses Enter or commits a multiline completion. - -Tasks: - -- Introduce a Lua-specific Enter / indentation strategy in [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs). -- Indent one extra level after block openers such as `then`, `do`, `function`, `repeat`, and table / paren continuations as appropriate. -- Dedent on lines starting with `end`, `until`, `else`, or `elseif` as appropriate. -- Normalize multiline completion insertion indentation relative to the current line. -- Decide explicitly what to do with snippet `$0` intent when snippet support is disabled. - -Practical guidance: - -- Do not build a full tabstop snippet engine in this phase. -- Do preserve correct relative indentation and sensible caret placement for the common multiline Lua blocks users actually insert. - -Tests: - -- Pressing Enter after `then` increases indentation. -- `if ... then ... end` completion places `end` at the expected indentation. -- Multiline insertion preserves CRLF and caret placement intent as far as the plain-text model allows. - -### Phase 6: Immediate Stale-UI Cleanup During Editing -Goal: avoid showing obviously wrong colors and diagnostics while edits are in progress. - -Tasks: - -- Clear diagnostics immediately on text change in Lua editors. -- Decide whether to clear semantic tokens immediately on text change or keep them only when a lightweight remapping strategy exists. -- If immediate clearing is too visually noisy, add a very short debounce distinct from the 300 ms document sync. -- Keep provider-side version gating unchanged. - -Tests: - -- Underlines disappear immediately after edit. -- No stale semantic overlay remains after quick keyword edits. -- Rapid `local -> locl -> local` edits do not leave visually stale coloring. - -### Phase 7: Semantic Token And Highlighting Hardening -Goal: make fallback behavior intentional and deterministic. - -Tasks: - -- Fix delta-failure handling in [LuaLanguageServerIntellisenseProvider.SemanticTokens.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs#L89) so previous data is not paired with a new result id. -- Add a main-editor fallback highlighting path when TextMate install fails. -- Recheck lone-CR affected-line handling in [TextMateDocumentLineList](TombLib/TombLib.Scripting/Highlighting/TextMateDocumentLineList.cs#L164). -- Add resolver tests for the selector behavior the bundled themes actually depend on. - -Tests: - -- Failed delta forces full refresh. -- Main editor still has baseline Lua highlighting if TextMate is unavailable. -- CRLF, LF, and lone CR changes invalidate the correct line range. - -### Phase 8: Watcher, Disposal, Tooltip, And Packaging Hardening -Goal: finish the non-blocking safety and polish tasks. - -Tasks: - -- Make watcher disposal safe while dispatch is active. -- Decide whether watcher `Error` should restart, back off, or surface a disabled state. -- Wrap provider fan-out so one subscriber exception does not suppress later subscribers. -- Make tooltip code-block editors explicitly non-focusable and confirm resource lifetime behavior. -- Add LuaLS attribution to [ExternalResources.md](ExternalResources.md). - -Tests: - -- Watcher disposal during active dispatch. -- Subscriber exception isolation. -- Tooltip content does not steal focus. - -## Items Reclassified As Lower Priority Or Non-Blockers - -- Open-document replay after LuaLS restart is already present. -- Watch coverage for `*.lua`, `.luarc.*`, and `.API` is already present. -- Timeout-bounded LuaLS disposal is already present. -- The bundled themes do not currently rely on advanced TextMate parent-scope or excluded-selector semantics strongly enough to make that a first-wave blocker. -- A full snippet engine is not required for the first implementation pass. - -## Coverage Of Verified Issues - -Every concern below was re-verified as a real issue and has an explicit home in the plan: - -- Timeout-based server recovery: Phase 1. -- Old-generation transport isolation: Phase 1. -- Save As / rename document rekeying: Phase 2. -- Signature stale-response guards: Phase 3. -- Definition stale / disposed-editor guards: Phase 3. -- Signature-help dismissal on skipped `)`: Phase 3. -- Signature active-parameter refresh and desync: Phase 3. -- `textEdit.range` / `insert` / `replace` support: Phase 4. -- Completion stale-version application guard: Phase 4. -- Completion resolve preserving insertion metadata: Phase 4. -- Enter indentation after `then`: Phase 5. -- Multiline `if ... then ... end` completion indentation: Phase 5. -- Plain-text handling of snippet `$0` intent and caret placement: Phase 5. -- Immediate clearing of stale diagnostics after edit: Phase 6. -- Immediate handling of stale semantic overlays after edit: Phase 6. -- Semantic-token delta fallback consistency: Phase 7. -- Main-editor TextMate fallback: Phase 7. -- Watcher disposal / recovery hardening: Phase 8. -- Diagnostics / semantic-token fan-out isolation: Phase 8. -- Tooltip embedded-editor focus hardening: Phase 8. -- LuaLS attribution in packaged resources: Phase 8. - -The remaining concerns were intentionally not phased as defects because they were either already implemented, not reproduced as current production issues, or were narrower follow-on improvements rather than independently verified bugs. - -## Suggested Test Inventory - -- [LuaLanguageServerClientTests](TombLib/TombLib.Test/LuaLanguageServerClientTests.cs) -- [LuaLanguageServerIntellisenseProviderTests](TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs) -- [LuaLanguageServerResponseParserTests](TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs) -- [LuaIncrementalEditCalculatorTests](TombLib/TombLib.Test/LuaIncrementalEditCalculatorTests.cs) -- [LuaThemeConfigurationTests](TombLib/TombLib.Test/LuaThemeConfigurationTests.cs) - -Add one optional integration test that starts bundled LuaLS only when the executable exists in the test environment. - -## Recommended First Implementation Slice - -If the next agent wants the smallest safe slice with maximum user impact, do this order: - -1. Phase 1 transport resilience. -2. Phase 2 path rekeying. -3. Phase 3 signature / navigation stale guards. -4. Phase 4 completion `textEdit` correctness. -5. Phase 6 immediate diagnostic and semantic cleanup. - -That order addresses the largest correctness and survivability problems before moving into indentation polish and secondary hardening. diff --git a/LuaLS_ScriptingStudio_Features_Plan.md b/LuaLS_ScriptingStudio_Features_Plan.md deleted file mode 100644 index 8f4d160dbb..0000000000 --- a/LuaLS_ScriptingStudio_Features_Plan.md +++ /dev/null @@ -1,361 +0,0 @@ -# LuaLS / Scripting Studio Feature Plan - -Date: 2026-05-10. - -## Goal - -Add these Lua editor features in TombIDE Scripting Studio: - -- VSCode-like back / forward navigation across document, caret, and selection state. -- A dedicated diagnostics tool window for the active Lua document, with severity toggle filters. -- LuaLS Find References. -- LuaLS Rename Symbol. -- LuaLS document reformatting, exposed through the existing document cleanup command. - -This plan is written as an implementation handoff for the next agent. It is intentionally concrete and biased toward the smallest set of architectural changes that fit the current codebase. - -## Verified Starting Point - -- [LuaEditor](TombLib/TombLib.Scripting.Lua/LuaEditor.cs) already owns Lua-specific editor UX and currently wires completion, hover, signature help, and definition navigation. -- [LuaEditor.Navigation](TombLib/TombLib.Scripting.Lua/LuaEditor.Navigation.cs) already routes `F12` and `Ctrl+Click` into the definition-navigation controller, so definition jumps already have a single owner on the editor side. -- [LuaStudio.Intellisense](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs) is the current cross-document bridge. It opens Lua documents in the provider, applies diagnostics and semantic tokens, and performs the actual open-file jump for definitions. -- [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) currently exposes only completion, hover, definition, signature help, diagnostics, semantic tokens, and document lifecycle. References, rename, and formatting are not in the contract yet. -- [StudioBase](TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs) already owns command routing, dockable tool-window visibility, and the shared document command pipeline. -- [UICommand](TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs), [UIKeys](TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs), and the Lua menu/context XML files are the existing command-registration surface. -- [SearchResults](TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs) is a docked results window already, but it is tightly coupled to `FindReplaceEventArgs` and regex-match navigation. -- [TextEditorBase](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs) already raises `StatusChanged` on caret and selection changes, and stores diagnostics locally through `SetDiagnostics(...)`. -- [TextEditorDiagnostic](TombLib/TombLib.Scripting/Objects/TextEditorDiagnostic.cs) currently carries severity plus start/end offsets only. That is enough to build a current-document diagnostics list, but line/column text will need to be derived in the host UI. -- [TombIDE.ScriptingStudio.csproj](TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj) already has `UseWPF=true`, references `DarkUI.WPF`, and uses `ElementHost` elsewhere, so new WPF panes can be hosted inside existing `DarkToolWindow` shells. -- The visible `Reindent` command is currently routed through [StudioBase.HandleDocumentCommands](TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs) to [TextEditorBase.TidyCode](TombLib/TombLib.Scripting/Bases/TextEditorBase.cs), which only trims ending whitespace. Lua reformatting must override this path instead of reusing the current base behavior. - -## Recommended Decisions - -- Keep cross-document navigation history in the Scripting Studio host, not in `LuaEditor`. The editor knows about caret and selection, but only the studio knows about tabs, file opening, tool-window jumps, and document lifetime. -- Add new LuaLS protocol features inside `TombIDE.ScriptingStudio/Services/LuaIntellisense` using the existing feature-sliced layout. Do not collapse them into one generic parser file. -- Build new front-end panes as `DarkToolWindow` plus `ElementHost` plus a DarkUI.WPF `UserControl`. That gives a WPF front-end while preserving the existing WinForms dock host. -- Do not force `SearchResults` to become a generic results shell in the first pass. Extract only the shared jump helper if needed. A dedicated references window is lower risk than untangling the existing find/replace tree. -- Reuse the existing `InputBoxWindow` shape for rename unless the first iteration truly needs rename preview. A dedicated rename-preview dialog can wait. -- Keep the `UICommand.Reindent` identifier for now and rename only the visible localization strings to `Reformat`. That avoids broad command-churn across shared menus and settings. -- Treat diagnostics filter buttons as `Errors`, `Warnings`, and `Messages`, where `Information` and `Hint` roll up into `Messages`. Internally, keep the original severity values intact. -- Keep format-on-save out of the first Lua slice. The explicit document command should land first so edit-application, caret preservation, and latency can be validated before wiring it into save flows. - -## Phase 1. Shared Location And Navigation Infrastructure - -### Objective - -Create a reusable location model and navigation-history service that every Lua jump can use. - -### Why First - -Definition jumps already exist, and diagnostics and references both need the same open-file-and-position behavior. Landing this first avoids three separate navigation implementations. - -### Work Items - -- Add new commands and shortcuts: - - `NavigateBack` mapped to `Alt+Left`. - - `NavigateForward` mapped to `Alt+Right`. - - `FindReferences` mapped to `Shift+F12`. - - `RenameSymbol` mapped to `F2` when a text editor has focus. -- Update: - - [UICommand](TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs) - - [UIKeys](TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs) - - [Lua document menu](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml) - - [Lua context menu](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml) - - [Lua studio menu](TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml) - - [EN localization](TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml) - - [PL localization](TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml) -- Introduce a small studio-owned location model, for example: - - `EditorNavigationLocation` with file path, caret offset, selection start, selection length, and optional preferred line for scroll restoration. -- Introduce a studio-owned history service, for example: - - `EditorNavigationHistoryService` with back stack, forward stack, and a suppression scope for programmatic jumps. -- Subscribe to `IEditorControl.StatusChanged` in the studio host for Lua editors and record debounced user movement when it represents a meaningful location change. -- Add a single host-side navigation method in `LuaStudio`, for example `NavigateToLocation(EditorNavigationLocation location, NavigationOrigin origin)`, and route all Lua jumps through it. -- Change [LuaStudio.NavigateToDefinition](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs) so definition navigation pushes the current location before opening the target location. -- Extract the target-file jump logic from [SearchResults](TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs) into a shared helper or callback so later tool windows can reuse it. - -### Done When - -- `Alt+Left` and `Alt+Right` work after `F12`, `Ctrl+Click`, and existing Search Results jumps. -- Programmatic jumps do not create duplicate history entries. -- Same-file caret and selection movement can be recorded without polluting the history on every cursor tick. - -### Validation - -- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` -- Manual check: - - Jump to a definition in another file. - - Jump back. - - Jump forward. - - Select text, move caret materially, and verify history behaves predictably. - -## Phase 2. Active-Document Diagnostics Tool Window - -### Objective - -Add a dedicated diagnostics pane for the current Lua document, with three severity toggle buttons and jump-to-diagnostic behavior. - -### Recommended UI Shape - -- New `DarkToolWindow` hosted in the dock panel. -- Inside it, host a DarkUI.WPF `UserControl` through `ElementHost`. -- Use DarkUI.WPF `ToggleButton` controls for `Errors`, `Warnings`, and `Messages`. -- Use a WPF `DataGrid` or `ListBox` for rows. Prefer `DataGrid` because the row shape is tabular: severity, line, column, message. - -### Work Items - -- Add a new public tool-window field on `LuaStudio`, for example `LuaDiagnostics`, so it participates in the normal dock-layout serialization and View menu handling. -- Create new files under `TombIDE.ScriptingStudio`, for example: - - `ToolWindows/LuaDiagnostics.cs` - - `Views/LuaDiagnosticsView.xaml` - - `Views/LuaDiagnosticsView.xaml.cs` - - `ViewModels/LuaDiagnosticsViewModel.cs` - - `Objects/LuaDiagnosticListItem.cs` -- Populate the view model from the active Lua editor only. The source of truth should remain `ILuaIntellisenseProvider.GetDiagnostics(filePath)` plus the active editor document for line/column/message projection. -- Project each `TextEditorDiagnostic` into a row model with: - - severity - - line - - column - - message - - start offset - - end offset -- Refresh the pane when: - - the selected tab changes - - diagnostics update for the active file - - the current Lua editor changes locally -- On local edit, clear or mark pending diagnostics for the active file immediately instead of displaying known-stale results until the delayed provider refresh arrives. -- Double-click or press `Enter` on a row to navigate through the shared navigation service from Phase 1. -- Add a View menu entry and default bottom-dock placement near Search Results. - -### Done When - -- The pane always shows diagnostics for the active Lua document only. -- `Errors`, `Warnings`, and `Messages` toggles filter rows live. -- Jumping from the diagnostics list records history correctly. -- Switching to a non-Lua tab clears or disables the pane instead of leaving stale Lua results on screen. - -### Validation - -- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` -- Manual check: - - Open a Lua file with multiple diagnostics. - - Toggle each severity filter. - - Edit the document and verify stale rows clear quickly. - - Double-click a row and jump back with `Alt+Left`. - -## Phase 3. LuaLS Find References - -### Objective - -Add LuaLS references requests and surface the results in a dedicated docked results pane. - -### Recommended UI Shape - -- Use a dedicated references tool window instead of reusing the current Search Results tool window. -- Keep the shell pattern consistent with diagnostics: `DarkToolWindow` plus `ElementHost` plus WPF `UserControl`. -- Group results by file and show line/column plus preview text. - -### Work Items - -- Extend [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) with a new async references API. -- Add new DTOs under `TombLib.Scripting.Lua/Objects`, for example: - - `LuaReferenceLocation` - - `LuaDocumentRange` -- Add provider support inside `TombIDE.ScriptingStudio/Services/LuaIntellisense`: - - new request method in the provider partials - - new response parser under a new `References/` folder or under `Navigation/` if kept small - - capability detection during initialization -- Add a studio command handler in `LuaStudio` for `Shift+F12` and context-menu invocation. -- Create a new results pane, for example: - - `ToolWindows/LuaReferencesResults.cs` - - `Views/LuaReferencesResultsView.xaml` - - `ViewModels/LuaReferencesResultsViewModel.cs` -- Model the rows with enough information to jump directly: - - file path - - line - - column - - preview text - - start/end offsets where available -- Prefer file grouping plus count headers so the result list stays readable in multi-file workspaces. -- Route all activation through the Phase 1 navigation service. -- If LuaLS does not advertise references support, disable the command cleanly instead of failing at runtime. - -### Done When - -- `Shift+F12` from a valid symbol opens a references pane and groups matches by file. -- Double-clicking a result jumps to the location and back/forward navigation works afterward. -- Re-running references replaces the previous Lua references result set cleanly. - -### Validation - -- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` -- Targeted test pass if provider parser changes add or update testable seams under `TombLib.Test`. -- Manual check: - - local variable references in one file - - shared symbol references across multiple files - - no-result case - -## Phase 4. LuaLS Rename Symbol - -### Objective - -Add symbol rename via LuaLS and apply the returned workspace edits safely across open and unopened Lua files. - -### Recommended UI Shape - -- Start with the existing [InputBoxWindow](TombLib/TombLib.Forms/Views/InputBoxWindow.xaml) visual pattern. -- Reuse `InputBoxWindowViewModel` if the first slice only needs title, label, and new name text. -- Only create a dedicated rename dialog if a preview list or extra validation text becomes necessary. - -### Work Items - -- Extend [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) with a rename API. -- Add workspace-edit DTOs, for example: - - `LuaWorkspaceEdit` - - `LuaDocumentEdit` - - `LuaTextEdit` -- Add LuaLS rename request handling under `TombIDE.ScriptingStudio/Services/LuaIntellisense`: - - request method - - parser for `WorkspaceEdit` - - capability detection -- Add a studio-owned edit applier, for example `LuaWorkspaceEditApplier`, that: - - applies edits in descending offset order per file - - uses open editors when available - - opens files through `EditorTabControl` when needed - - leaves affected files dirty instead of silently saving them - - preserves the previously selected tab when practical -- Add a host-side command handler for `F2` when a Lua editor is focused. -- Seed the rename box from the current selection or the identifier at the caret. -- If the server returns no edits, show a non-blocking message and leave the editor untouched. -- If the server refuses the rename, surface the error cleanly through DarkUI message UI. -- After edits apply, refresh provider-tracked document state so diagnostics, semantic tokens, references, and future rename requests remain aligned. -- Keep file-explorer `F2` rename behavior intact when the editor does not have focus. - -### Done When - -- `F2` on a renameable Lua symbol opens a DarkUI.WPF-style prompt and applies changes across the workspace. -- Open tabs update in place and unopened files are updated safely. -- Back/forward history still works after the rename operation. -- Rename failures and unsupported cases are visible and non-destructive. - -### Validation - -- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` -- Manual check: - - rename a local variable in one file - - rename a shared symbol across files - - cancel rename - - invalid or unsupported rename - -## Phase 5. LuaLS Reformat Command - -### Objective - -Replace the current Lua `Reindent` behavior with provider-backed Lua formatting while keeping the existing shared command slot. - -### Work Items - -- Extend [ILuaIntellisenseProvider](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) with a document-formatting API. -- Add formatting request support under `TombIDE.ScriptingStudio/Services/LuaIntellisense`: - - request method - - parser for returned text edits - - capability detection -- Reuse the workspace-edit application machinery from Phase 4 for single-document formatting edits. -- Override the Lua document-command path in `LuaStudio` so `UICommand.Reindent` does this instead: - - when the current editor is `LuaEditor` and the provider supports formatting, request formatting edits and apply them - - when the provider is unavailable, disable the command or show a warning instead of silently falling back to trim-only behavior -- Change visible menu text from `Reindent` to `Reformat` in localization files. Keep the existing command and configuration identifiers for now. -- Decide explicitly whether the existing visible `ReindentOnSave` option should also be renamed to `Reformat on Save`. Recommended first slice: rename the visible text only if the save path is still intentionally trim-only across non-Lua editors; otherwise defer the label change to avoid implying Lua format-on-save before it exists. -- Keep range formatting out of scope for the first pass. - -### Done When - -- The Lua document menu command reformats a Lua document through LuaLS. -- Caret and selection are preserved well enough for normal editing. -- The visible UI says `Reformat` instead of `Reindent`. -- Non-Lua editors keep their current behavior. - -### Validation - -- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` -- Manual check: - - reformat a messy Lua file - - verify edits are applied once - - verify the editor state remains usable afterward - -## Phase 6. Polish, Layout, And Regression Pass - -### Work Items - -- Add default layout entries for the new diagnostics and references panes if they should participate in restored layouts from first launch. -- Verify View menu checked states and serialization keys for every new tool window. -- Add or update documentation notes in the LuaLS service README if ownership shifts or new folders are introduced. -- Update tests in `TombLib.Test` for any provider/parser contracts that change. -- Re-run a full manual regression pass over: - - completion - - hover - - signature help - - definition navigation - - diagnostics refresh - - semantic token stability after rename and reformat - -### Validation - -- Focused build: `dotnet build .\TombIDE\TombIDE.ScriptingStudio\TombIDE.ScriptingStudio.csproj -c Debug` -- Broader test pass: `dotnet test .\TombLib\TombLib.Test\TombLib.Test.csproj` - -## Suggested File Touch Map - -### Command And Menu Surface - -- [TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs](TombIDE/TombIDE.ScriptingStudio/UI/UICommand.cs) -- [TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs](TombIDE/TombIDE.ScriptingStudio/UI/UIKeys.cs) -- [TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/MenuStrips/Lua.xml) -- [TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml](TombIDE/TombIDE.ScriptingStudio/UI/DocumentModePresets/ContextMenus/Lua.xml) -- [TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml](TombIDE/TombIDE.ScriptingStudio/UI/StudioModePresets/MenuStrips/Lua.xml) -- [TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml](TombIDE/TombIDE.Shared/Resources/Localization/EN/TombIDE.xml) -- [TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml](TombIDE/TombIDE.Shared/Resources/Localization/PL/TombIDE.xml) - -### Host / Studio Side - -- [TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs](TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs) -- [TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs](TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs) -- [TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs](TombIDE/TombIDE.ScriptingStudio/Bases/StudioBase.cs) -- [TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs](TombIDE/TombIDE.ScriptingStudio/Controls/EditorTabControl.cs) -- [TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs](TombIDE/TombIDE.ScriptingStudio/ToolWindows/SearchResults.cs) - -### New Host Files Likely Needed - -- `TombIDE/TombIDE.ScriptingStudio/Objects/EditorNavigationLocation.cs` -- `TombIDE/TombIDE.ScriptingStudio/Services/EditorNavigationHistoryService.cs` -- `TombIDE/TombIDE.ScriptingStudio/Services/LuaWorkspaceEditApplier.cs` -- `TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaDiagnostics.cs` -- `TombIDE/TombIDE.ScriptingStudio/ToolWindows/LuaReferencesResults.cs` -- `TombIDE/TombIDE.ScriptingStudio/Views/LuaDiagnosticsView.xaml` -- `TombIDE/TombIDE.ScriptingStudio/Views/LuaReferencesResultsView.xaml` -- `TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaDiagnosticsViewModel.cs` -- `TombIDE/TombIDE.ScriptingStudio/ViewModels/LuaReferencesResultsViewModel.cs` - -### Provider / Contract Side - -- [TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs](TombLib/TombLib.Scripting.Lua/Services/ILuaIntellisenseProvider.cs) -- `TombLib/TombLib.Scripting.Lua/Objects/LuaReferenceLocation.cs` -- `TombLib/TombLib.Scripting.Lua/Objects/LuaWorkspaceEdit.cs` -- `TombLib/TombLib.Scripting.Lua/Objects/LuaTextEdit.cs` -- [TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs) -- New service folders under [TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense](TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense) - -## Not In Scope For The First Slice - -- Code actions and quick fixes. -- Rename preview with per-file accept/reject UI. -- Range formatting. -- Workspace-wide diagnostics across every Lua file. -- Generalizing every existing results surface into a single mega-control. - -## Agent Execution Notes - -- Implement one phase at a time and validate it before widening scope. -- Do not start rename-edit application before the shared navigation and location model exist. -- Do not change non-Lua editor behavior unless a shared command surface absolutely requires it. -- Prefer small, reversible refactors in the studio host over broad shell rewrites. -- If a WPF result pane adds too much friction inside the dock host, keep the `DarkToolWindow` shell and debug the `ElementHost` bridge first instead of falling back immediately to a second WinForms tree/grid implementation. diff --git a/Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md b/Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md deleted file mode 100644 index d49159ac92..0000000000 --- a/Lua_Intellisense_And_AvalonEdit_Cleanup_Plan.md +++ /dev/null @@ -1,344 +0,0 @@ -# Lua IntelliSense And AvalonEdit Cleanup Plan - -## Scope - -This plan covers the Lua editor and the Lua language-server integration code that currently spans these areas: - -- `TombLib/TombLib.Scripting.Lua/LuaEditor*.cs` -- `TombLib/TombLib.Scripting.Lua/Utils/*` -- `TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/*` -- `TombLib/TombLib.Scripting/Bases/TextEditorBase.cs` - -Nearby editors such as `GameFlowEditor` and `ClassicScriptEditor` are comparison points only. They are not part of the first cleanup passes unless a small shared helper clearly benefits more than one editor. - -## Goals - -- Reduce the number of responsibilities owned by `LuaEditor` and its partials. -- Move stateful feature logic behind focused collaborators so timers, cancellation, popups, and request tokens have a single owner per feature. -- Replace unclear multi-value returns with named result types where the tuple shape hides meaning. -- Reorganize the LuaLS implementation into slices that are easy to discover by feature and by responsibility. -- Keep behavior stable while refactoring by adding tests before moving the highest-risk code. -- Follow `AGENTS.md`: partials only when the responsibility still belongs to the same type, prefer helper or service extraction when it does not, keep touched code nullable-aware, and avoid broad helper types with fuzzy ownership. - -## Current Findings - -### Editor-side hotspots - -- `LuaEditor.Completion.cs` owns too much in one place: debounce scheduling, request orchestration, popup lifecycle, tooltip lifecycle, reflection-based AvalonEdit integration, width measurement, and query-offset calculation. -- `LuaEditor.SignatureHelp.cs` owns both presentation and workflow state: popup UI elements, request-in-flight state, refresh timer, positioning, and active-parameter formatting. -- `LuaEditor.Hover.cs` mixes request orchestration, fallback selection, and tooltip composition. -- `LuaEditor.Navigation.cs` duplicates parts of the editor request pipeline and shares state patterns with hover and completion. -- `LuaEditor.Intellisense.cs` still acts as a central wiring file for many unrelated concerns, so field ownership is difficult to follow even though the code is split into partials. - -### LuaLS service-side hotspots - -- `TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense` is currently a flat folder containing client transport, protocol, response parsing, workspace watching, document synchronization, semantic tokens, and provider orchestration. -- `LuaLanguageServerIntellisenseProvider` is still a large composition point with significant state and workflow spread across partials. -- Several feature-specific files already exist, but they are not grouped together on disk in a way that helps maintainers navigate by feature. - -### Tuple and result-shape hotspots - -The following methods are good candidates for named result types because their return values carry multiple meanings or mixed null and boolean state: - -- `LuaIndentationStrategy.BuildEnterInsertion()` -- `LuaIndentationStrategy.NormalizeCompletionInsertion()` -- `LuaLanguageServerResponseParser.StripSnippetPlaceholders()` -- `LuaLanguageServerIntellisenseProvider.DecodeSemanticTokensResponse()` -- `LuaLanguageServerIntellisenseProvider.SynchronizeDocumentCoreAsync()` -- `LuaIntellisenseDocumentManager.GetSemanticTokensDeltaState()` - -Small, local coordinate pairs such as line and column can remain tuples until a wider text-position abstraction is clearly justified. Not every two-value tuple needs to become a record. - -## Cleanup Rules - -- Keep `LuaEditor` as the public control and composition root. Do not move public editor behavior into a maze of tiny pass-through wrappers. -- Extract collaborators only when they own real state, workflow, or policy. -- Use `record struct` for small immutable result carriers and state snapshots. -- Prefer one top-level type per new file. -- Keep partial classes only where the split still represents one type with one coherent ownership boundary. -- Avoid introducing a generic cross-language framework before at least two editors need the same abstraction with similar complexity. - -## Phase 0 - Safeguards And Baseline - -Purpose: lock down behavior before structural work begins. - -Work items: - -1. Add focused tests for the current behavior that is easiest to break during extraction. -2. Cover completion request debounce, completion window refresh, completion tooltip resolve, hover vs diagnostic fallback, signature help open and refresh and dismiss, definition navigation, document sync, and semantic-token delta fallback. -3. Add a short maintainer note near the Lua editor and LuaLS service roots describing which file currently owns which feature. -4. Adopt the naming convention before creating new collaborators: use `Controller` for editor-side stateful owners, `Coordinator` for provider-side workflow owners, and keep `Service` for stable external integration boundaries or shared utilities. - -Exit criteria: - -- Refactor-sensitive behavior has direct tests. -- Maintainers can see the intended cleanup direction before code starts moving. - -## Phase 1 - Replace Ambiguous Tuple Returns - -Purpose: improve readability first with low-risk changes that clarify intent. - -Recommended result types: - -- `LuaEnterInsertionResult` - - replaces the tuple returned by `BuildEnterInsertion()` -- `LuaCompletionNormalizationResult` - - replaces the tuple returned by `NormalizeCompletionInsertion()` -- `LuaSnippetPlaceholderResult` - - replaces the tuple returned by `StripSnippetPlaceholders()` -- `LuaSemanticTokensDecodeResult` - - replaces the four-part tuple returned by `DecodeSemanticTokensResponse()` -- `LuaDocumentSynchronizationResult` - - replaces the tuple returned by `SynchronizeDocumentCoreAsync()` -- `LuaSemanticTokensDeltaState` - - replaces the tuple returned by `GetSemanticTokensDeltaState()` - -Notes: - -- Favor `internal readonly record struct` for these types. -- Keep the first pass narrow: rename only the returns that improve comprehension immediately. -- Do not convert short, obvious local tuples just for consistency. - -Exit criteria: - -- Mixed-state tuple returns are replaced with named result types. -- Method call sites read as domain concepts instead of index-based unpacking. - -## Phase 2 - Extract Editor Feature Controllers - -Purpose: remove intertwined state from `LuaEditor` without breaking its public role. - -Target shape: - -- `LuaEditor` remains the host control, public API surface, and event source. -- Each major editor feature gets one internal owner for its fields, timers, request tokens, and UI state. - -Recommended extractions: - -1. `LuaCompletionController` - - Owns completion debounce scheduling. - - Owns popup lifecycle. - - Owns tooltip update scheduling and resolve flow. - - Owns width measurement and query-offset calculation. - - Owns AvalonEdit-specific reflection and non-activating window behavior. - -2. `LuaSignatureHelpController` - - Owns signature popup elements. - - Owns refresh timer and pending-offset state. - - Owns request-in-flight state. - - Owns positioning and active-parameter rendering. - -3. `LuaHoverController` - - Owns hover request cancellation and tokens. - - Owns hover-offset validation. - - Owns hover vs diagnostic fallback policy. - - Owns combined tooltip rendering decisions. - -4. `LuaDefinitionNavigationController` - - Owns F12 and Ctrl+Click navigation flow. - - Owns definition request cancellation and freshness checks. - -5. Optional shared internal helper after the first extractions only - - `LuaEditorRequestGate` or `LuaEditorAsyncState` - - Create this only if completion, hover, signature help, and navigation still duplicate freshness logic after the first controller pass. - -Recommended folder direction: - -```text -TombLib/TombLib.Scripting.Lua/ - Editor/ - LuaEditor.cs - Completion/ - Hover/ - Navigation/ - SignatureHelp/ - SemanticHighlighting/ - Objects/ - Resources/ - Utils/ -``` - -Notes: - -- Do not extract theme application or semantic-highlighting attachment until the feature controllers settle. Those areas are smaller and less entangled. -- Keep event wiring in `LuaEditor` or one small composition file, not spread across every controller. - -Exit criteria: - -- No single feature stores its timers and request state directly on `LuaEditor` unless that state is trivial. -- The owner of each field is easy to infer from the file name. - -## Phase 3 - Re-slice The LuaLS Implementation In TombIDE - -Purpose: turn the flat LuaLS service folder into a discoverable feature-oriented structure. - -Recommended folder direction: - -```text -TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/ - Infrastructure/ - Client/ - Pathing/ - Startup/ - Workspace/ - Documents/ - Provider/ - Completion/ - Hover/ - Navigation/ - SignatureHelp/ - Diagnostics/ - SemanticTokens/ -``` - -Suggested file moves: - -- `Infrastructure/Client/` - - `ILuaLanguageServerClient.cs` - - `LuaLanguageServerClient.cs` - - `LuaLanguageServerClient.Protocol.cs` - - `LuaLanguageServerClient.Transport.cs` - -- `Infrastructure/Pathing/` - - `LuaLanguageServerPathHelper.cs` - - `LuaLanguageServerLocator.cs` - - `LuaLanguageServerSettingsFactory.cs` - -- `Infrastructure/Startup/` - - `LuaLanguageServerStartupFailure.cs` - - `LuaProcessJobObject.cs` - -- `Infrastructure/Workspace/` - - `LuaWorkspaceFileWatcher.cs` - - `LuaWorkspaceWatcherFailure.cs` - -- `Documents/` - - `LuaIntellisenseDocumentManager.cs` - - `LuaDocumentSnapshot.cs` - - `LuaDocumentSynchronizationRequest.cs` - - `LuaDocumentRenameRequest.cs` - - `LuaDocumentLineOffsets.cs` - - `LuaIncrementalEditCalculator.cs` - - `LuaTextDocumentSyncKind.cs` - -- `Provider/` - - `LuaLanguageServerIntellisenseProvider.cs` - - `LuaLanguageServerIntellisenseProvider.Documents.cs` - - `LuaLanguageServerIntellisenseProvider.Requests.cs` - - `LuaLanguageServerIntellisenseProvider.SemanticTokens.cs` - -- `Completion/` - - `LuaLanguageServerResponseParser.Completion.cs` - -- `Navigation/` - - `LuaLanguageServerResponseParser.Navigation.cs` - -- `SignatureHelp/` - - `LuaLanguageServerResponseParser.SignatureHelp.cs` - -- `Diagnostics/` - - `LuaLanguageServerDiagnosticsParser.cs` - - `LuaPublishedDiagnostics.cs` - - shared response-parser pieces that are diagnostics-specific if more are split later - -- `SemanticTokens/` - - `LuaLanguageServerSemanticTokensDeltaParser.cs` - - future semantic-token decoder or result helpers - -Implementation order inside this phase: - -1. Move files without behavioral changes. -2. Rename partials only when the new file names better match the responsibility. -3. Extract dedicated stateful coordinators only where there is real state ownership pressure. - -Recommended coordinator candidates inside the provider layer: - -- `LuaDocumentSynchronizationCoordinator` -- `LuaSemanticTokensCoordinator` -- `LuaWorkspaceWatcherCoordinator` - -Non-goal for this phase: - -- Do not create separate completion, hover, navigation, and signature-help service classes if they remain thin request wrappers around parser calls. That would add indirection without paying down much complexity. - -Exit criteria: - -- A maintainer can find document sync, semantic tokens, workspace watching, or client transport without scanning the whole folder. -- Provider partials and helper types match clear feature boundaries. - -## Phase 4 - Consolidate Shared AvalonEdit Infrastructure Carefully - -Purpose: extract only the reusable pieces that are already proven to repeat. - -Shared abstractions that are worth considering: - -- `TextDocumentPosition` - - only if Lua editor code and LuaLS infrastructure both need the same line and character concept in multiple places -- `AsyncRequestGate` - - only if multiple editor features or multiple editors share the same request freshness and lifecycle pattern -- `CompletionWindowHost` - - only if another async editor needs the same styled completion popup and tooltip behavior -- `HoverToolTipFactory` - - only if tooltip composition starts repeating across more than one editor - -Shared abstractions that are not worth building now: - -- A generic `IIntellisenseProvider` -- A generic editor framework for completion, hover, definition, and signature help across all AvalonEdit editors - -Reason: - -- Lua currently has the only rich async LSP-backed pipeline. -- `GameFlowEditor` and `ClassicScriptEditor` are much simpler and mostly synchronous. -- A shared full-framework abstraction would force weaker editors into stub implementations and increase indirection before there is a second real consumer. - -Recommendation: - -- Keep the Lua feature contracts Lua-specific for now. -- Revisit a broader abstraction only when at least one other editor reaches a Lua-like capability set or moves to an LSP-backed async model. - -Exit criteria: - -- Shared helpers exist only where they already have at least two concrete consumers. -- No new abstraction is introduced just to make the architecture diagram look cleaner. - -## Phase 5 - Final Simplification And Maintainer Handoff - -Purpose: finish the cleanup by reducing leftover friction for future contributors. - -Work items: - -1. Remove partials that no longer improve navigation after service extraction. -2. Ensure touched files follow nullable guidance and remove redundant null-forgiving usage where practical. -3. Remove unused `using` directives and redundant framework qualification in touched files. -4. Add a short `README.md` inside the LuaLS service root describing the slices and their ownership. -5. Add a small regression checklist for completion, hover, signature help, definition navigation, document rename, diagnostics, and semantic tokens. - -Exit criteria: - -- A new maintainer can identify the owner of a behavior in one or two guesses. -- The cleanup leaves fewer hidden couplings, not just more files. - -## Recommended Execution Order - -1. Phase 0 baseline tests and notes. -2. Phase 1 named result types. -3. Phase 2 completion controller extraction. -4. Phase 2 signature-help controller extraction. -5. Phase 2 hover and navigation extraction. -6. Phase 3 file moves for LuaLS slices. -7. Phase 3 targeted provider coordinators where state remains dense. -8. Phase 4 shared infrastructure only if the first three phases reveal a real repeated pattern. -9. Phase 5 final simplification, docs, and regression pass. - -## Decision On A Shared IntelliSense Abstraction - -Short answer: not as a full framework yet. - -The worthwhile cleanup right now is to separate Lua editor features and LuaLS infrastructure into well-owned pieces. That work will make later sharing easier if another editor actually grows into the same capability set. Building a generic abstraction for completion, hover, definition, signature help, and related plumbing before that point would most likely add complexity instead of removing duplication. - -The pragmatic middle ground is: - -- extract Lua-specific controllers and provider coordinators first -- promote only small reusable building blocks when a second consumer appears -- delay any broad cross-language IntelliSense contract until there is a second editor with comparable async behavior and lifecycle needs diff --git a/Tomb Editor.sln b/Tomb Editor.sln index a10bb5cede..025f30f07b 100644 --- a/Tomb Editor.sln +++ b/Tomb Editor.sln @@ -52,6 +52,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TombLib.Scripting.ClassicSc EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TombLib.Scripting.Lua", "TombLib\TombLib.Scripting.Lua\TombLib.Scripting.Lua.csproj", "{87D4149C-E716-49F6-848F-ACA345D11B30}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TombLib.Scripting.Lua.LanguageServer", "TombLib\TombLib.Scripting.Lua.LanguageServer\TombLib.Scripting.Lua.LanguageServer.csproj", "{BAC24926-D29E-4E42-905B-CDBAB29C0B53}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileAssociation", "FileAssociation\FileAssociation.csproj", "{934E79A8-2B20-4E0E-A145-08404493A7F6}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TombLib.Scripting.GameFlowScript", "TombLib\TombLib.Scripting.GameFlowScript\TombLib.Scripting.GameFlowScript.csproj", "{98E13BC4-6196-4346-AB4F-92DE33D84589}" @@ -216,6 +218,14 @@ Global {87D4149C-E716-49F6-848F-ACA345D11B30}.Release|x64.Build.0 = Release|x64 {87D4149C-E716-49F6-848F-ACA345D11B30}.Release|x86.ActiveCfg = Release|x86 {87D4149C-E716-49F6-848F-ACA345D11B30}.Release|x86.Build.0 = Release|x86 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Debug|x64.ActiveCfg = Debug|x64 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Debug|x64.Build.0 = Debug|x64 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Debug|x86.ActiveCfg = Debug|x86 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Debug|x86.Build.0 = Debug|x86 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Release|x64.ActiveCfg = Release|x64 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Release|x64.Build.0 = Release|x64 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Release|x86.ActiveCfg = Release|x86 + {BAC24926-D29E-4E42-905B-CDBAB29C0B53}.Release|x86.Build.0 = Release|x86 {934E79A8-2B20-4E0E-A145-08404493A7F6}.Debug|x64.ActiveCfg = Debug|x64 {934E79A8-2B20-4E0E-A145-08404493A7F6}.Debug|x64.Build.0 = Debug|x64 {934E79A8-2B20-4E0E-A145-08404493A7F6}.Debug|x86.ActiveCfg = Debug|x86 @@ -306,6 +316,7 @@ Global {3EAAFD71-DD96-427D-8793-643DADD2F3A3} = {642147AB-23FD-4715-AE26-90BE6C755FD0} {5D9A72E7-4B33-4177-AD7C-1B46591005FD} = {642147AB-23FD-4715-AE26-90BE6C755FD0} {87D4149C-E716-49F6-848F-ACA345D11B30} = {642147AB-23FD-4715-AE26-90BE6C755FD0} + {BAC24926-D29E-4E42-905B-CDBAB29C0B53} = {642147AB-23FD-4715-AE26-90BE6C755FD0} {98E13BC4-6196-4346-AB4F-92DE33D84589} = {642147AB-23FD-4715-AE26-90BE6C755FD0} {7987FD7B-AAC9-4C7F-8188-C54FDE35C3D6} = {642147AB-23FD-4715-AE26-90BE6C755FD0} {61E45B12-B972-136D-6066-1CD28A5429E1} = {6F5F6BB9-64D2-4F82-B6AE-162361DF4965} diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs index 090468ad9c..b47475c943 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.Intellisense.cs @@ -6,10 +6,11 @@ using System.Collections.Generic; using System.IO; using System.Windows.Forms; +using LuaLanguageServerLocator = TombIDE.ScriptingStudio.Services.LuaIntellisense.LuaLanguageServerLocator; using TombIDE.ScriptingStudio.Helpers; using TombIDE.ScriptingStudio.Objects; -using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombLib.Scripting.Bases; +using TombLib.Scripting.Lua.LanguageServer; using TombLib.Scripting.Lua; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; diff --git a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs index 3a26fe15fa..5d713e442e 100644 --- a/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs +++ b/TombIDE/TombIDE.ScriptingStudio/LuaStudio.cs @@ -10,7 +10,6 @@ using TombIDE.ScriptingStudio.Bases; using TombIDE.ScriptingStudio.Controls; using TombIDE.ScriptingStudio.Services; -using TombIDE.ScriptingStudio.Services.LuaIntellisense; using TombIDE.ScriptingStudio.ToolWindows; using TombIDE.ScriptingStudio.UI; using TombIDE.Shared; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs deleted file mode 100644 index 43ad72f9e5..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaSnippetPlaceholderResult.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -/// -/// Represents snippet text after placeholder stripping and the resolved caret placement. -/// -internal readonly record struct LuaSnippetPlaceholderResult(string Text, int? CaretOffset); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs deleted file mode 100644 index 2e26198792..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -#nullable enable - -using TombLib.Scripting.Lua.Objects; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -/// -/// Represents the outcome of synchronizing one document with the Lua language server. -/// -internal readonly record struct LuaDocumentSynchronizationResult(bool Success, LuaDocumentSnapshot? Document); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs deleted file mode 100644 index 40a2be8155..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Hover/LuaLanguageServerResponseParser.Hover.cs +++ /dev/null @@ -1,24 +0,0 @@ -#nullable enable - -using System.Text.Json; -using TombLib.Scripting.Lua.Objects; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal static partial class LuaLanguageServerResponseParser -{ - /// - /// Parses hover content from a LuaLS hover response. - /// - public static LuaHoverInfo? ParseHoverInfo(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object || !response.TryGetProperty("contents", out JsonElement contentsElement)) - return null; - - MarkupContent hoverContent = ExtractMarkupContent(contentsElement); - - return string.IsNullOrWhiteSpace(hoverContent.Text) - ? null - : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); - } -} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs deleted file mode 100644 index 8d2d68c2f7..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs +++ /dev/null @@ -1,224 +0,0 @@ -#nullable enable - -using System; -using System.Buffers; -using System.Buffers.Text; -using System.Collections.Generic; -using System.IO; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal sealed partial class LuaLanguageServerClient -{ - private Task SendNotificationCoreAsync(string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) - => SendNotificationCoreAsync(GetRequiredActiveSession(allowDisposed), method, parameters, cancellationToken, allowDisposed); - - private Task SendNotificationCoreAsync(LuaLanguageServerTransportSession session, string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) - => WriteMessageAsync(session, new { jsonrpc = "2.0", method, @params = parameters }, cancellationToken, allowDisposed); - - private async Task SendRequestCoreAsync(string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) - => await SendRequestCoreAsync(GetRequiredActiveSession(allowDisposed), method, parameters, cancellationToken, allowDisposed).ConfigureAwait(false); - - private async Task SendRequestCoreAsync(LuaLanguageServerTransportSession session, string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) - { - long requestId = Interlocked.Increment(ref _requestId); - var responseSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - - if (!session.PendingRequests.TryAdd(requestId, responseSource)) - throw new InvalidOperationException("Unable to track a new language server request."); - - await using var registration = cancellationToken.Register(() => responseSource.TrySetCanceled(cancellationToken)); - - try - { - await WriteMessageAsync(session, new { jsonrpc = "2.0", id = requestId, method, @params = parameters }, cancellationToken, allowDisposed).ConfigureAwait(false); - return await responseSource.Task.ConfigureAwait(false); - } - catch (OperationCanceledException) - { - SendCancelNotification(session, requestId); - throw; - } - finally - { - session.PendingRequests.TryRemove(requestId, out _); - } - } - - private void SendCancelNotification(LuaLanguageServerTransportSession session, long requestId) - { - if (_isDisposed) - return; - - Task.Run(async () => - { - try - { - await WriteMessageAsync(session, - new { jsonrpc = "2.0", method = "$/cancelRequest", @params = new { id = requestId } }, - CancellationToken.None, - allowDisposed: true).ConfigureAwait(false); - } - catch - { - // Best-effort: cancellation notifications are advisory. - } - }); - } - - private async Task HandleServerRequestAsync(LuaLanguageServerTransportSession session, JsonElement idElement, string method, JsonElement parameters) - { - switch (method) - { - case "workspace/configuration": - await WriteResponseAsync(session, idElement, BuildConfigurationResponse(parameters)).ConfigureAwait(false); - return; - - case "workspace/workspaceFolders": - await WriteResponseAsync(session, idElement, BuildWorkspaceFolderResponse()).ConfigureAwait(false); - return; - - case "workspace/semanticTokens/refresh": - try - { - SemanticTokensRefreshRequested?.Invoke(); - } - catch (Exception exception) - { - Log.Warn(exception, "Lua semantic-tokens refresh request handler threw; acknowledging the request anyway."); - } - - await WriteResponseAsync(session, idElement, result: null).ConfigureAwait(false); - return; - - case "client/registerCapability": - case "client/unregisterCapability": - case "window/workDoneProgress/create": - // Acknowledge with a successful empty result so the server can proceed. - await WriteResponseAsync(session, idElement, result: null).ConfigureAwait(false); - return; - - default: - // Reply with JSON-RPC "Method Not Found" (-32601) for everything else so the server does not block on us. - await WriteErrorResponseAsync(session, idElement, code: -32601, message: $"Method '{method}' is not supported by the client.").ConfigureAwait(false); - return; - } - } - - private Task WriteResponseAsync(LuaLanguageServerTransportSession session, JsonElement idElement, object? result) - => WriteMessageAsync(session, new { jsonrpc = "2.0", id = idElement, result }, CancellationToken.None, allowDisposed: true); - - private Task WriteErrorResponseAsync(LuaLanguageServerTransportSession session, JsonElement idElement, int code, string message) - => WriteMessageAsync(session, new { jsonrpc = "2.0", id = idElement, error = new { code, message } }, CancellationToken.None, allowDisposed: true); - - private object[] BuildConfigurationResponse(JsonElement parameters) - { - if (!parameters.TryGetProperty("items", out JsonElement itemsElement) || itemsElement.ValueKind != JsonValueKind.Array) - return []; - - JsonElement settingsElement = JsonSerializer.SerializeToElement(_settingsProvider()); - JsonElement luaElement = settingsElement.GetProperty("Lua"); - - var results = new List(); - - foreach (JsonElement item in itemsElement.EnumerateArray()) - { - string? section = item.TryGetProperty("section", out JsonElement sectionElement) - ? sectionElement.GetString() - : null; - - results.Add(GetConfigurationSection(settingsElement, luaElement, section)); - } - - return [.. results]; - } - - private static object GetConfigurationSection(JsonElement settingsElement, JsonElement luaElement, string? section) - { - if (string.IsNullOrWhiteSpace(section)) - return settingsElement.Clone(); - - if (section.Equals("Lua", StringComparison.OrdinalIgnoreCase)) - return luaElement.Clone(); - - if (section.StartsWith("Lua.", StringComparison.OrdinalIgnoreCase)) - { - JsonElement nestedSection = luaElement; - string[] parts = section[4..].Split('.'); - - foreach (string part in parts) - { - if (!nestedSection.TryGetProperty(part, out JsonElement nextSection)) - return new { }; - - nestedSection = nextSection; - } - - return nestedSection.Clone(); - } - - return new { }; - } - - private object[] BuildWorkspaceFolderResponse() => - [ - new - { - uri = LuaLanguageServerPathHelper.CreateFileUri(_workspaceRootDirectoryPath), - name = Path.GetFileName(_workspaceRootDirectoryPath) - } - ]; - - private async Task WriteMessageAsync(LuaLanguageServerTransportSession session, object payload, CancellationToken cancellationToken, bool allowDisposed) - { - ThrowIfDisposed(allowDisposed); - - byte[] payloadBytes = JsonSerializer.SerializeToUtf8Bytes(payload); - - // Header layout: "Content-Length: \r\n\r\n". Worst-case digits fit comfortably in 32 bytes. - const int HeaderReserve = 64; - byte[] frameBuffer = ArrayPool.Shared.Rent(HeaderReserve + payloadBytes.Length); - int headerLength = WriteContentLengthHeader(frameBuffer, payloadBytes.Length); - int frameLength = headerLength + payloadBytes.Length; - - try - { - Buffer.BlockCopy(payloadBytes, 0, frameBuffer, headerLength, payloadBytes.Length); - - await _writeLock.WaitAsync(cancellationToken).ConfigureAwait(false); - - try - { - await session.OutputStream.WriteAsync(frameBuffer.AsMemory(0, frameLength), cancellationToken).ConfigureAwait(false); - await session.OutputStream.FlushAsync(cancellationToken).ConfigureAwait(false); - } - finally - { - _writeLock.Release(); - } - } - finally - { - ArrayPool.Shared.Return(frameBuffer); - } - } - - private static int WriteContentLengthHeader(Span destination, int payloadLength) - { - ReadOnlySpan prefix = "Content-Length: "u8; - ReadOnlySpan terminator = "\r\n\r\n"u8; - - prefix.CopyTo(destination); - int position = prefix.Length; - - if (!Utf8Formatter.TryFormat(payloadLength, destination[position..], out int digitsWritten)) - throw new InvalidOperationException("Failed to encode the LSP Content-Length header."); - - position += digitsWritten; - terminator.CopyTo(destination[position..]); - return position + terminator.Length; - } -} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Transport.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Transport.cs deleted file mode 100644 index 59dab20c51..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.Transport.cs +++ /dev/null @@ -1,372 +0,0 @@ -#nullable enable - -using System; -using System.Buffers; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Text; -using System.Text.Json; -using System.Threading; -using System.Threading.Channels; -using System.Threading.Tasks; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal sealed partial class LuaLanguageServerClient -{ - private async Task ReadLoopAsync(LuaLanguageServerTransportSession session) - { - Exception? failure = null; - - try - { - while (!_isDisposed) - { - int? contentLengthValue = await ReadHeadersAsync(session).ConfigureAwait(false); - - if (contentLengthValue is null || !TryAcceptPayloadSize(contentLengthValue.Value, out int contentLength)) - break; - - byte[]? payloadBytes = await ReadPayloadAsync(session, contentLength).ConfigureAwait(false); - - if (payloadBytes is null) - break; - - using JsonDocument document = JsonDocument.Parse(payloadBytes); - await HandleMessageAsync(session, document.RootElement).ConfigureAwait(false); - } - } - catch (Exception exception) - { - failure = exception; - } - finally - { - if (IsCurrentSession(session)) - IsReady = false; - - if (!session.PendingRequests.IsEmpty) - FailPendingRequests(session, failure ?? new IOException("The Lua language server connection was closed.")); - } - } - - private async Task ReadStandardErrorLoopAsync(LuaLanguageServerTransportSession session) - { - try - { - while (!_isDisposed) - { - Process? process = session.Process; - - if (process is null || process.HasExited) - break; - - string? line = await process.StandardError.ReadLineAsync(_lifetimeCts.Token).ConfigureAwait(false); - - if (line is null) - break; - - if (!string.IsNullOrWhiteSpace(line)) - Log.Debug("[LuaLS stderr] {Line}", line); - } - } - catch (OperationCanceledException) - { } - catch - { - // Ignore stderr read failures. - } - } - - private async Task ReadHeadersAsync(LuaLanguageServerTransportSession session) - { - while (true) - { - int headerTerminatorIndex = FindHeaderTerminatorIndex(session); - - if (headerTerminatorIndex >= 0) - return ConsumeHeaders(session, headerTerminatorIndex); - - if (!await ReadIntoReceiveBufferAsync(session).ConfigureAwait(false)) - return null; - } - } - - private int? ConsumeHeaders(LuaLanguageServerTransportSession session, int headerTerminatorIndex) - { - string headerText = Encoding.ASCII.GetString(session.ReceiveBuffer, 0, headerTerminatorIndex); - ConsumeReceiveBuffer(session, headerTerminatorIndex + HeaderTerminator.Length); - return ExtractContentLength(headerText); - } - - private static int? ExtractContentLength(string headerText) - { - foreach (string line in headerText.Split(["\r\n"], StringSplitOptions.RemoveEmptyEntries)) - { - int separatorIndex = line.IndexOf(':'); - - if (separatorIndex <= 0) - continue; - - ReadOnlySpan key = line.AsSpan(0, separatorIndex).Trim(); - - if (!key.Equals("Content-Length".AsSpan(), StringComparison.OrdinalIgnoreCase)) - continue; - - ReadOnlySpan value = line.AsSpan(separatorIndex + 1).Trim(); - - if (int.TryParse(value, out int parsedContentLength) && parsedContentLength > 0) - return parsedContentLength; - - return null; - } - - return null; - } - - private int FindHeaderTerminatorIndex(LuaLanguageServerTransportSession session) - => new ReadOnlySpan(session.ReceiveBuffer, 0, session.ReceiveBufferCount).IndexOf(HeaderTerminator); - - private async Task ReadIntoReceiveBufferAsync(LuaLanguageServerTransportSession session) - { - EnsureReceiveBufferCapacity(session, session.ReceiveBufferCount + ReceiveChunkSize); - - int bytesAvailable = session.ReceiveBuffer.Length - session.ReceiveBufferCount; - int bytesRead = await session.InputStream - .ReadAsync(session.ReceiveBuffer.AsMemory(session.ReceiveBufferCount, bytesAvailable), _lifetimeCts.Token) - .ConfigureAwait(false); - - if (bytesRead == 0) - return false; - - session.ReceiveBufferCount += bytesRead; - return true; - } - - private void EnsureReceiveBufferCapacity(LuaLanguageServerTransportSession session, int requiredCapacity) - { - if (session.ReceiveBuffer.Length >= requiredCapacity) - return; - - int newCapacity = Math.Max(ReceiveChunkSize, session.ReceiveBuffer.Length); - - while (newCapacity < requiredCapacity) - newCapacity *= 2; - - byte[] newBuffer = ArrayPool.Shared.Rent(newCapacity); - - if (session.ReceiveBufferCount > 0) - Buffer.BlockCopy(session.ReceiveBuffer, 0, newBuffer, 0, session.ReceiveBufferCount); - - ReturnReceiveBuffer(session); - session.ReceiveBuffer = newBuffer; - } - - private void ReturnReceiveBuffer(LuaLanguageServerTransportSession session) - { - if (session.ReceiveBuffer.Length == 0) - return; - - ArrayPool.Shared.Return(session.ReceiveBuffer, clearArray: false); - session.ReceiveBuffer = []; - } - - private void ConsumeReceiveBuffer(LuaLanguageServerTransportSession session, int bytesToConsume) - { - int remainingBytes = session.ReceiveBufferCount - bytesToConsume; - - if (remainingBytes > 0) - Buffer.BlockCopy(session.ReceiveBuffer, bytesToConsume, session.ReceiveBuffer, 0, remainingBytes); - - session.ReceiveBufferCount = Math.Max(0, remainingBytes); - } - - private async Task ReadPayloadAsync(LuaLanguageServerTransportSession session, int contentLength) - { - byte[] payloadBytes = new byte[contentLength]; - int totalBytesRead = 0; - - if (session.ReceiveBufferCount > 0) - { - int bufferedBytesToCopy = Math.Min(contentLength, session.ReceiveBufferCount); - Buffer.BlockCopy(session.ReceiveBuffer, 0, payloadBytes, 0, bufferedBytesToCopy); - ConsumeReceiveBuffer(session, bufferedBytesToCopy); - totalBytesRead = bufferedBytesToCopy; - } - - while (totalBytesRead < contentLength) - { - int bytesRead = await session.InputStream - .ReadAsync(payloadBytes.AsMemory(totalBytesRead, contentLength - totalBytesRead), _lifetimeCts.Token) - .ConfigureAwait(false); - - if (bytesRead == 0) - return null; - - totalBytesRead += bytesRead; - } - - return payloadBytes; - } - - private async Task HandleMessageAsync(LuaLanguageServerTransportSession session, JsonElement message) - { - bool hasId = message.TryGetProperty("id", out JsonElement idElement); - bool hasMethod = message.TryGetProperty("method", out JsonElement methodElement); - - if (hasId && !hasMethod) - { - HandleServerResponse(session, idElement, message); - return; - } - - if (!hasMethod) - return; - - string? method = methodElement.GetString(); - - if (string.IsNullOrWhiteSpace(method)) - return; - - JsonElement parameters = message.TryGetProperty("params", out JsonElement paramsElement) - ? paramsElement.Clone() - : default; - - if (hasId) - await HandleServerRequestAsync(session, idElement.Clone(), method, parameters).ConfigureAwait(false); - else - HandleServerNotification(method, parameters); - } - - private void HandleServerResponse(LuaLanguageServerTransportSession session, JsonElement idElement, JsonElement message) - { - if (!idElement.TryGetInt64(out long requestId)) - return; - - if (!session.PendingRequests.TryGetValue(requestId, out TaskCompletionSource? responseSource)) - { - Log.Debug("Received Lua language server response with no matching pending request (id={RequestId}).", requestId); - return; - } - - if (message.TryGetProperty("error", out JsonElement errorElement)) - { - string messageText = errorElement.TryGetProperty("message", out JsonElement errorMessageElement) - ? errorMessageElement.GetString() ?? "Lua language server request failed." - : "Lua language server request failed."; - - responseSource.TrySetException(new InvalidOperationException(messageText)); - return; - } - - if (message.TryGetProperty("result", out JsonElement resultElement)) - responseSource.TrySetResult(resultElement.Clone()); - else - responseSource.TrySetResult(default); - } - - private void HandleServerNotification(string method, JsonElement parameters) - { - switch (method) - { - case "textDocument/publishDiagnostics": - RaiseDiagnosticsPublished(parameters); - return; - - case "window/logMessage": - case "window/showMessage": - LogServerMessage(method, parameters); - return; - - case "telemetry/event": - case "$/progress": - return; - } - } - - private void RaiseDiagnosticsPublished(JsonElement parameters) - { - // Stash only the newest diagnostics payload per file and wake the pump if it is idle. - // Parameters were already cloned by the dispatcher in HandleMessageAsync. - _pendingDiagnostics[GetDiagnosticsQueueKey(parameters)] = parameters; - _diagnosticsSignal.Writer.TryWrite(true); - } - - private async Task PumpDiagnosticsAsync() - { - ChannelReader reader = _diagnosticsSignal.Reader; - - try - { - while (await reader.WaitToReadAsync(_lifetimeCts.Token).ConfigureAwait(false)) - { - while (reader.TryRead(out _)) - { } - - while (!_pendingDiagnostics.IsEmpty) - { - KeyValuePair[] pendingDiagnostics = [.. _pendingDiagnostics]; - - for (int i = 0; i < pendingDiagnostics.Length; i++) - { - if (!_pendingDiagnostics.TryRemove(pendingDiagnostics[i].Key, out JsonElement parameters)) - continue; - - try - { - DiagnosticsPublished?.Invoke(parameters); - } - catch (Exception exception) - { - Log.Warn(exception, "Lua diagnostics handler threw; the diagnostics pump is being kept alive."); - } - } - } - } - } - catch (OperationCanceledException) - { - // Expected on dispose. - } - } - - private string GetDiagnosticsQueueKey(JsonElement parameters) - { - if (parameters.ValueKind == JsonValueKind.Object - && parameters.TryGetProperty("uri", out JsonElement uriElement) - && uriElement.ValueKind == JsonValueKind.String) - { - string? uri = uriElement.GetString(); - - if (!string.IsNullOrWhiteSpace(uri)) - return uri; - } - - return "diagnostics:" + Interlocked.Increment(ref _diagnosticsFallbackSequence); - } - - private static void LogServerMessage(string method, JsonElement parameters) - { - if (parameters.ValueKind != JsonValueKind.Object) - return; - - string? messageText = parameters.TryGetProperty("message", out JsonElement messageElement) - ? messageElement.GetString() - : null; - - if (string.IsNullOrWhiteSpace(messageText)) - return; - - int messageType = parameters.TryGetProperty("type", out JsonElement typeElement) - && typeElement.TryGetInt32(out int parsedType) ? parsedType : 4; - - switch (messageType) - { - case 1: Log.Error("[LuaLS {Method}] {Message}", method, messageText); break; - case 2: Log.Warn("[LuaLS {Method}] {Message}", method, messageText); break; - case 3: Log.Info("[LuaLS {Method}] {Message}", method, messageText); break; - default: Log.Debug("[LuaLS {Method}] {Message}", method, messageText); break; - } - } -} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerLocator.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs similarity index 100% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerLocator.cs rename to TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerLocator.cs diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Navigation/LuaLanguageServerResponseParser.Navigation.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Navigation/LuaLanguageServerResponseParser.Navigation.cs deleted file mode 100644 index de7b7321d7..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Navigation/LuaLanguageServerResponseParser.Navigation.cs +++ /dev/null @@ -1,80 +0,0 @@ -#nullable enable - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Linq; -using System.Text.Json; -using TombLib.Scripting.Lua.Objects; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal static partial class LuaLanguageServerResponseParser -{ - private static readonly string[] DefinitionRangeProperties = - [ - "targetSelectionRange", - "targetRange", - "range" - ]; - - /// - /// Parses a definition location from a LuaLS definition response. - /// - public static LuaDefinitionLocation? ParseDefinitionLocation(JsonElement response) - { - JsonElement definitionElement = response; - - if (response.ValueKind == JsonValueKind.Array) - { - definitionElement = response.EnumerateArray().FirstOrDefault(); - - if (definitionElement.ValueKind == JsonValueKind.Undefined) - return null; - } - - if (definitionElement.ValueKind != JsonValueKind.Object) - return null; - - if (!TryGetDefinitionUri(definitionElement, out Uri? parsedUri)) - return null; - - if (!TryGetDefinitionStartElement(definitionElement, out JsonElement startElement)) - return null; - - int lineNumber = startElement.TryGetProperty("line", out JsonElement lineElement) - && lineElement.TryGetInt32(out int parsedLine) ? parsedLine + 1 : 1; - int columnNumber = startElement.TryGetProperty("character", out JsonElement characterElement) - && characterElement.TryGetInt32(out int parsedCharacter) ? parsedCharacter + 1 : 1; - - return new LuaDefinitionLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), lineNumber, columnNumber); - } - - private static bool TryGetDefinitionUri(JsonElement definitionElement, [NotNullWhen(true)] out Uri? parsedUri) - { - parsedUri = null; - - string? uri = definitionElement.TryGetProperty("targetUri", out JsonElement targetUriElement) - ? targetUriElement.GetString() - : definitionElement.TryGetProperty("uri", out JsonElement uriElement) - ? uriElement.GetString() - : null; - - return !string.IsNullOrWhiteSpace(uri) && Uri.TryCreate(uri, UriKind.Absolute, out parsedUri) && parsedUri.IsFile; - } - - private static bool TryGetDefinitionStartElement(JsonElement definitionElement, out JsonElement startElement) - { - foreach (string rangeProperty in DefinitionRangeProperties) - { - if (definitionElement.TryGetProperty(rangeProperty, out JsonElement rangeElement) - && rangeElement.TryGetProperty("start", out startElement) - && startElement.ValueKind == JsonValueKind.Object) - { - return true; - } - } - - startElement = default; - return false; - } -} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md deleted file mode 100644 index a357ac3118..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# Lua Language Server Ownership Notes - -This note is a maintainer map for the current LuaLS integration layout after the phase 3 re-slice. It is intentionally short and should be updated as cleanup work lands. - -## Current ownership - -- `Provider/`: provider composition root, startup and restart flow, request orchestration, document replay, and semantic-token refresh coordination. -- `Documents/`: tracked document snapshots, version and open-reference state, synchronization requests and results, incremental edit calculation, and text-sync kinds. -- `Infrastructure/Client/`: process lifetime, JSON-RPC session state, transport I/O, and server capability tracking. -- `Infrastructure/Pathing/`: path normalization, server discovery, and settings generation. -- `Infrastructure/Startup/`: startup failure reporting and process-host job-object integration. -- `Infrastructure/Workspace/`: workspace file watching, external change batching, and watcher failure reporting. -- `Completion/`: completion response parsing and snippet-placeholder result shaping. -- `Hover/`: hover response parsing. -- `Navigation/`: definition-location response parsing. -- `References/`: reference-location response parsing for `textDocument/references`. -- `Rename/`: workspace-edit parsing for `textDocument/rename` results. -- `Formatting/`: document-formatting edit parsing for `textDocument/formatting` results. -- `SignatureHelp/`: signature-help response parsing. -- `Diagnostics/`: diagnostics payload mapping and published diagnostics snapshots. -- `SemanticTokens/`: semantic-tokens delta parsing plus cached delta and decode result carriers. -- `LuaLanguageServerResponseParser.Shared.cs`: shared markup parsing helpers used by the response-parser partials. -- `LuaStudio.Formatting.cs` plus `LuaWorkspaceEditApplier`: host-side reformat command ownership, including selection preservation when formatting edits are applied back into the editor. - -## Extraction naming - -- Use `Coordinator` for new provider-side owners of document sync, semantic tokens, restart handling, or workspace watching. -- Avoid introducing feature-specific `Service` types when the result would only wrap one parser call and add another hop. -- Keep parser and transport types focused on one protocol concern each. - -## Cleanup guardrails - -- Move files by feature first, then extract new stateful owners only where state is still dense. -- Keep document tracking centralized instead of splitting version and cache state across several helpers. -- Prefer feature-oriented folders over a larger set of flat provider partials. -- Keep XML docs current on provider-facing contracts, result carriers, and other maintainer-facing entry points when responsibilities change. - -## Regression checklist - -- Completion: verify `.` `:` and manual `Ctrl+Space` requests still open the completion list, refresh correctly after edits, and continue to resolve selected-item tooltip content. -- Hover: verify symbol hover still shows hover content, and that hover falls back to diagnostics when no hover payload is available. -- Signature help: verify `(` and `,` open or refresh the popup, `)` dismisses it, and editor deactivation clears transient UI. -- Definition navigation: verify `F12` and `Ctrl+Click` navigate for valid identifiers and stay inert for comments, strings, or unresolved symbols. -- References: verify Find References opens or refreshes the references results pane, groups locations by file, and keeps activation navigation aligned with the selected result. -- Rename: verify Rename Symbol applies workspace edits across open and unopened files, preserves diagnostics ownership after the rename, and keeps the global undo action working for the full rename batch. -- Formatting: verify the existing cleanup command routes Lua documents through LuaLS formatting, preserves caret or selection state in the active editor, and falls back cleanly when formatting is unavailable. -- Document lifecycle: verify open, update, rename, close, and restart replay keep document versions, URIs, and open references synchronized with LuaLS. -- Diagnostics: verify published diagnostics replace stale results, clear when documents change or close, and stay attached to the correct file after rename and restart flows. -- Semantic tokens: verify full refresh, delta apply, and delta fallback all keep coloring stable after edits, file changes, and server restart. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs deleted file mode 100644 index 8640555c43..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/References/LuaLanguageServerResponseParser.References.cs +++ /dev/null @@ -1,89 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using TombLib.Scripting.Lua.Objects; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal static partial class LuaLanguageServerResponseParser -{ - /// - /// Parses reference locations from a LuaLS references response. - /// - public static IReadOnlyList ParseReferenceLocations(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Array) - return []; - - var locations = new List(); - - foreach (JsonElement referenceElement in response.EnumerateArray()) - { - if (referenceElement.ValueKind != JsonValueKind.Object) - continue; - - if (!TryGetReferenceUri(referenceElement, out Uri? parsedUri) - || !TryGetReferenceRange(referenceElement, out LuaDocumentRange? range)) - { - continue; - } - - locations.Add(new LuaReferenceLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), range)); - } - - return locations; - } - - private static bool TryGetReferenceUri(JsonElement referenceElement, [NotNullWhen(true)] out Uri? parsedUri) - { - parsedUri = null; - - if (!referenceElement.TryGetProperty("uri", out JsonElement uriElement)) - return false; - - string? uri = uriElement.GetString(); - return !string.IsNullOrWhiteSpace(uri) && Uri.TryCreate(uri, UriKind.Absolute, out parsedUri) && parsedUri.IsFile; - } - - private static bool TryGetReferenceRange(JsonElement referenceElement, [NotNullWhen(true)] out LuaDocumentRange? range) - { - range = null; - - if (!referenceElement.TryGetProperty("range", out JsonElement rangeElement) - || !rangeElement.TryGetProperty("start", out JsonElement startElement) - || !rangeElement.TryGetProperty("end", out JsonElement endElement)) - { - return false; - } - - if (!TryGetLineAndColumn(startElement, out int startLineNumber, out int startColumnNumber) - || !TryGetLineAndColumn(endElement, out int endLineNumber, out int endColumnNumber)) - { - return false; - } - - range = new LuaDocumentRange(startLineNumber, startColumnNumber, endLineNumber, endColumnNumber); - return true; - } - - private static bool TryGetLineAndColumn(JsonElement positionElement, out int lineNumber, out int columnNumber) - { - lineNumber = 1; - columnNumber = 1; - - if (!positionElement.TryGetProperty("line", out JsonElement lineElement) - || !lineElement.TryGetInt32(out int parsedLine) - || !positionElement.TryGetProperty("character", out JsonElement characterElement) - || !characterElement.TryGetInt32(out int parsedCharacter)) - { - return false; - } - - lineNumber = parsedLine + 1; - columnNumber = parsedCharacter + 1; - return true; - } -} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs deleted file mode 100644 index d1b35918f4..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Rename/LuaLanguageServerResponseParser.Rename.cs +++ /dev/null @@ -1,148 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using TombLib.Scripting.Lua.Objects; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal static partial class LuaLanguageServerResponseParser -{ - /// - /// Parses a workspace edit from a LuaLS rename response. - /// - public static LuaWorkspaceEdit? ParseWorkspaceEdit(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object) - return null; - - var editsByFile = new Dictionary>(StringComparer.OrdinalIgnoreCase); - - ParseChangeMap(response, editsByFile); - ParseDocumentChanges(response, editsByFile); - - if (editsByFile.Count == 0) - return null; - - var documentEdits = new List(editsByFile.Count); - - foreach ((string filePath, List textEdits) in editsByFile) - { - if (textEdits.Count == 0) - continue; - - documentEdits.Add(new LuaDocumentEdit(filePath, textEdits)); - } - - return documentEdits.Count == 0 - ? null - : new LuaWorkspaceEdit(documentEdits); - } - - private static void ParseChangeMap(JsonElement response, Dictionary> editsByFile) - { - if (!response.TryGetProperty("changes", out JsonElement changesElement) - || changesElement.ValueKind != JsonValueKind.Object) - { - return; - } - - foreach (JsonProperty changeProperty in changesElement.EnumerateObject()) - { - if (!Uri.TryCreate(changeProperty.Name, UriKind.Absolute, out Uri? parsedUri) || !parsedUri.IsFile) - continue; - - string filePath = LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri); - List textEdits = GetOrCreateTextEditBucket(editsByFile, filePath); - AppendTextEdits(changeProperty.Value, textEdits); - } - } - - private static void ParseDocumentChanges(JsonElement response, Dictionary> editsByFile) - { - if (!response.TryGetProperty("documentChanges", out JsonElement documentChangesElement) - || documentChangesElement.ValueKind != JsonValueKind.Array) - { - return; - } - - foreach (JsonElement documentChangeElement in documentChangesElement.EnumerateArray()) - { - if (documentChangeElement.ValueKind != JsonValueKind.Object - || !documentChangeElement.TryGetProperty("textDocument", out JsonElement textDocumentElement) - || !textDocumentElement.TryGetProperty("uri", out JsonElement uriElement)) - { - continue; - } - - string? uri = uriElement.GetString(); - - if (string.IsNullOrWhiteSpace(uri) || !Uri.TryCreate(uri, UriKind.Absolute, out Uri? parsedUri) || !parsedUri.IsFile) - continue; - - if (!documentChangeElement.TryGetProperty("edits", out JsonElement editsElement)) - continue; - - string filePath = LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri); - List textEdits = GetOrCreateTextEditBucket(editsByFile, filePath); - AppendTextEdits(editsElement, textEdits); - } - } - - private static void AppendTextEdits(JsonElement editsElement, List textEdits) - { - if (editsElement.ValueKind != JsonValueKind.Array) - return; - - foreach (JsonElement editElement in editsElement.EnumerateArray()) - { - if (TryParseTextEdit(editElement, out LuaTextEdit? textEdit)) - textEdits.Add(textEdit); - } - } - - private static bool TryParseTextEdit(JsonElement editElement, [NotNullWhen(true)] out LuaTextEdit? textEdit) - { - textEdit = null; - - if (editElement.ValueKind != JsonValueKind.Object - || !editElement.TryGetProperty("range", out JsonElement rangeElement) - || !TryParseRange(rangeElement, out LuaDocumentRange? range) - || !editElement.TryGetProperty("newText", out JsonElement newTextElement)) - { - return false; - } - - textEdit = new LuaTextEdit(range, newTextElement.GetString() ?? string.Empty); - return true; - } - - private static bool TryParseRange(JsonElement rangeElement, [NotNullWhen(true)] out LuaDocumentRange? range) - { - range = null; - - if (!rangeElement.TryGetProperty("start", out JsonElement startElement) - || !rangeElement.TryGetProperty("end", out JsonElement endElement) - || !TryGetLineAndColumn(startElement, out int startLineNumber, out int startColumnNumber) - || !TryGetLineAndColumn(endElement, out int endLineNumber, out int endColumnNumber)) - { - return false; - } - - range = new LuaDocumentRange(startLineNumber, startColumnNumber, endLineNumber, endColumnNumber); - return true; - } - - private static List GetOrCreateTextEditBucket(Dictionary> editsByFile, string filePath) - { - if (!editsByFile.TryGetValue(filePath, out List? textEdits)) - { - textEdits = []; - editsByFile[filePath] = textEdits; - } - - return textEdits; - } -} \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs deleted file mode 100644 index 3b46ea6eec..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDeltaState.cs +++ /dev/null @@ -1,8 +0,0 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -/// -/// Represents the cached semantic-tokens delta state used for incremental refresh requests. -/// -internal readonly record struct LuaSemanticTokensDeltaState(string? PreviousResultId, int[]? PreviousData); \ No newline at end of file diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs b/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs deleted file mode 100644 index 772b8982da..0000000000 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs +++ /dev/null @@ -1,125 +0,0 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Text.Json; -using TombLib.Scripting.Lua.Objects; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal static partial class LuaLanguageServerResponseParser -{ - /// - /// Parses signature help metadata from a LuaLS signature-help response. - /// - public static LuaSignatureInfo? ParseSignatureHelp(JsonElement response) - { - if (response.ValueKind != JsonValueKind.Object - || !response.TryGetProperty("signatures", out JsonElement signaturesElement) - || signaturesElement.ValueKind != JsonValueKind.Array) - { - return null; - } - - int signatureCount = signaturesElement.GetArrayLength(); - - if (signatureCount == 0) - return null; - - int activeSignature = response.TryGetProperty("activeSignature", out JsonElement activeSignatureElement) - && activeSignatureElement.TryGetInt32(out int parsedActiveSignature) - ? Math.Clamp(parsedActiveSignature, 0, signatureCount - 1) - : 0; - - JsonElement signatureElement = signaturesElement[activeSignature]; - - if (signatureElement.ValueKind != JsonValueKind.Object - || !signatureElement.TryGetProperty("label", out JsonElement labelElement)) - { - return null; - } - - string? label = labelElement.GetString(); - - if (string.IsNullOrWhiteSpace(label)) - return null; - - string? documentation = signatureElement.TryGetProperty("documentation", out JsonElement documentationElement) - ? ExtractMarkupText(documentationElement) - : null; - - int activeParameter = ResolveActiveParameter(response, signatureElement); - - var parameters = new List(); - - if (signatureElement.TryGetProperty("parameters", out JsonElement parametersElement) - && parametersElement.ValueKind == JsonValueKind.Array) - { - foreach (JsonElement paramElement in parametersElement.EnumerateArray()) - { - string? parameterLabel = paramElement.TryGetProperty("label", out JsonElement paramLabelElement) - ? paramLabelElement.ValueKind == JsonValueKind.String - ? paramLabelElement.GetString() - : TryExtractParameterLabel(label, paramLabelElement, out string? extractedLabel) - ? extractedLabel - : null - : null; - - string? parameterDocumentation = paramElement.TryGetProperty("documentation", out JsonElement parameterDocumentationElement) - ? ExtractMarkupText(parameterDocumentationElement) - : null; - - parameters.Add(new LuaParameterInfo(parameterLabel ?? string.Empty, parameterDocumentation)); - } - } - - return new LuaSignatureInfo(label, documentation, parameters, activeParameter); - } - - private static int ResolveActiveParameter(JsonElement response, JsonElement signatureElement) - { - if (response.TryGetProperty("activeParameter", out JsonElement responseActiveParameterElement) - && responseActiveParameterElement.TryGetInt32(out int responseActiveParameter)) - { - return Math.Max(0, responseActiveParameter); - } - - if (signatureElement.TryGetProperty("activeParameter", out JsonElement signatureActiveParameterElement) - && signatureActiveParameterElement.TryGetInt32(out int signatureActiveParameter)) - { - return Math.Max(0, signatureActiveParameter); - } - - return 0; - } - - private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, - [NotNullWhen(true)] out string? parameterLabel) - { - parameterLabel = null; - - if (string.IsNullOrEmpty(signatureLabel) - || parameterLabelElement.ValueKind != JsonValueKind.Array) - { - return false; - } - - JsonElement.ArrayEnumerator labelParts = parameterLabelElement.EnumerateArray(); - - if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int startIndex)) - return false; - - if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int endIndex)) - return false; - - startIndex = Math.Max(0, Math.Min(startIndex, signatureLabel.Length)); - endIndex = Math.Max(startIndex, Math.Min(endIndex, signatureLabel.Length)); - - if (endIndex <= startIndex) - return false; - - parameterLabel = signatureLabel[startIndex..endIndex]; - return true; - } -} diff --git a/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj b/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj index 4e50298760..3bc30e3c68 100644 --- a/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj +++ b/TombIDE/TombIDE.ScriptingStudio/TombIDE.ScriptingStudio.csproj @@ -67,6 +67,7 @@ + diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaCompletionPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaCompletionPayloads.cs new file mode 100644 index 0000000000..87c0d49682 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaCompletionPayloads.cs @@ -0,0 +1,106 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents a completion response that may arrive either as an item array or as an LSP completion list. +/// +[JsonConverter(typeof(LuaCompletionResponseJsonConverter))] +public sealed record LuaCompletionResponse(LuaCompletionItemPayload[]? Items); + +/// +/// Represents a single typed completion item returned by LuaLS. +/// +public sealed record LuaCompletionItemPayload +{ + [JsonPropertyName("label")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Label { get; init; } + + [JsonPropertyName("kind")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public int? Kind { get; init; } + + [JsonPropertyName("detail")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? Detail { get; init; } + + [JsonPropertyName("documentation")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public JsonElement? Documentation { get; init; } + + [JsonPropertyName("insertText")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? InsertText { get; init; } + + [JsonPropertyName("insertTextFormat")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public int? InsertTextFormat { get; init; } + + [JsonPropertyName("filterText")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? FilterText { get; init; } + + [JsonPropertyName("preselect")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public bool? Preselect { get; init; } + + [JsonPropertyName("textEdit")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public LuaCompletionTextEditPayload? TextEdit { get; init; } +} + +/// +/// Represents the supported completion text-edit shapes returned by LuaLS. +/// +public sealed record LuaCompletionTextEditPayload +{ + [JsonPropertyName("newText")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public string? NewText { get; init; } + + [JsonPropertyName("range")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public LuaProtocolRangePayload? Range { get; init; } + + [JsonPropertyName("insert")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public LuaProtocolRangePayload? Insert { get; init; } + + [JsonPropertyName("replace")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + public LuaProtocolRangePayload? Replace { get; init; } +} + +/// +/// Deserializes completion responses from either LSP array or completion-list form. +/// +public sealed class LuaCompletionResponseJsonConverter : JsonConverter +{ + public override LuaCompletionResponse? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + return new LuaCompletionResponse(null); + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + JsonElement root = document.RootElement; + LuaCompletionItemPayload[]? items = null; + + if (root.ValueKind == JsonValueKind.Array) + { + items = JsonSerializer.Deserialize(root.GetRawText(), options); + } + else if (root.ValueKind == JsonValueKind.Object + && root.TryGetProperty("items", out JsonElement itemsElement) + && itemsElement.ValueKind == JsonValueKind.Array) + { + items = JsonSerializer.Deserialize(itemsElement.GetRawText(), options); + } + + return new LuaCompletionResponse(items); + } + + public override void Write(Utf8JsonWriter writer, LuaCompletionResponse value, JsonSerializerOptions options) + => throw new NotSupportedException(); +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaLanguageServerResponseParser.Completion.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaLanguageServerResponseParser.Completion.cs similarity index 68% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaLanguageServerResponseParser.Completion.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaLanguageServerResponseParser.Completion.cs index 269766cdb4..1c404627db 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Completion/LuaLanguageServerResponseParser.Completion.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaLanguageServerResponseParser.Completion.cs @@ -1,16 +1,10 @@ -#nullable enable - -using System; -using System.Collections.Generic; using System.Text; using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; -internal static partial class LuaLanguageServerResponseParser +public static partial class LuaLanguageServerResponseParser { // Lua identifiers are case-sensitive, so `Player` and `player` must be reported as distinct // completion items. Use ordinal (case-sensitive) comparison everywhere completion identity @@ -21,7 +15,7 @@ private sealed class CompletionIdentityComparer : IEqualityComparer<(string Labe public bool Equals((string Label, string InsertText) x, (string Label, string InsertText) y) => StringComparer.Ordinal.Equals(x.Label, y.Label) - && StringComparer.Ordinal.Equals(x.InsertText, y.InsertText); + && StringComparer.Ordinal.Equals(x.InsertText, y.InsertText); public int GetHashCode((string Label, string InsertText) value) => HashCode.Combine( @@ -79,44 +73,21 @@ public CompletionTextAnalysis(string? detail, string? description) } /// - /// Extracts the completion-item array from either an LSP completion list or a plain array response. - /// - /// The raw completion response payload. - /// The cloned completion-item elements. - public static IReadOnlyList ExtractCompletionItems(JsonElement response) - { - JsonElement itemsElement = response; - - if (response.ValueKind == JsonValueKind.Object && response.TryGetProperty("items", out JsonElement completionItemsElement)) - itemsElement = completionItemsElement; - - if (itemsElement.ValueKind != JsonValueKind.Array) - return []; - - var itemElements = new List(itemsElement.GetArrayLength()); - - foreach (JsonElement itemElement in itemsElement.EnumerateArray()) - itemElements.Add(itemElement.Clone()); - - return itemElements; - } - - /// - /// Parses a sequence of raw completion items into editor completion entries. + /// Parses a sequence of typed completion-item payloads into editor completion entries. /// - /// The raw completion-item payloads. + /// The typed completion-item payloads. /// Builds an optional lazy-resolve callback for each item. /// The parsed completion items. - public static IReadOnlyList ParseCompletionItems(IEnumerable itemElements, - Func>?>? resolveFactory = null) + public static IReadOnlyList ParseCompletionItems(IEnumerable itemPayloads, + Func>?>? resolveFactory = null) { var items = new List(); var seenItems = new HashSet<(string Label, string InsertText)>(CompletionIdentityComparer.Instance); int itemIndex = 0; - foreach (JsonElement itemElement in itemElements) + foreach (LuaCompletionItemPayload itemPayload in itemPayloads) { - LuaCompletionItem? item = ParseCompletionItem(itemElement, itemIndex); + LuaCompletionItem? item = ParseCompletionItem(itemPayload, itemIndex); itemIndex++; if (item is null) @@ -124,7 +95,7 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< if (resolveFactory is not null && CompletionItemNeedsResolve(item)) { - Func>? resolveAsync = resolveFactory(item, itemElement, itemIndex - 1); + Func>? resolveAsync = resolveFactory(item, itemPayload, itemIndex - 1); if (resolveAsync is not null) item = item.WithResolveCallback(resolveAsync); @@ -138,54 +109,44 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< } /// - /// Parses a single raw LSP completion item into a . + /// Parses a single typed LSP completion-item payload into a . /// - /// The raw completion-item payload. + /// The typed completion-item payload. /// The zero-based response index used for priority weighting. /// An optional lazy-resolve callback. /// The parsed completion item, or when the payload is invalid. - public static LuaCompletionItem? ParseCompletionItem(JsonElement itemElement, int itemIndex, + public static LuaCompletionItem? ParseCompletionItem(LuaCompletionItemPayload itemPayload, int itemIndex, Func>? resolveAsync = null) { - if (!itemElement.TryGetProperty("label", out JsonElement labelElement)) - return null; - - string? label = labelElement.GetString(); + string? label = itemPayload.Label; if (string.IsNullOrWhiteSpace(label)) return null; - LuaCompletionTextEdit? textEdit = ExtractCompletionTextEdit(itemElement, out string? textEditText); + LuaCompletionTextEdit? textEdit = ExtractCompletionTextEdit(itemPayload, out string? textEditText); string insertText = textEditText ?? string.Empty; if (string.IsNullOrWhiteSpace(insertText)) - { - insertText = itemElement.TryGetProperty("insertText", out JsonElement insertTextElement) - ? insertTextElement.GetString() ?? label - : label; - } + insertText = itemPayload.InsertText ?? label; int? insertCaretOffset = null; - if (itemElement.TryGetProperty("insertTextFormat", out JsonElement insertTextFormatElement) - && insertTextFormatElement.TryGetInt32(out int insertTextFormat) && insertTextFormat == 2) + if (itemPayload.InsertTextFormat == 2) { LuaSnippetPlaceholderResult snippetResult = StripSnippetPlaceholders(insertText); insertText = snippetResult.Text; insertCaretOffset = snippetResult.CaretOffset; } - string filterText = itemElement.TryGetProperty("filterText", out JsonElement filterTextElement) - ? filterTextElement.GetString() ?? label - : label; + string filterText = itemPayload.FilterText ?? label; - LuaLanguageServerCompletionKind completionKind = TryReadCompletionKind(itemElement, out LuaLanguageServerCompletionKind parsedCompletionKind) + LuaLanguageServerCompletionKind completionKind = TryReadCompletionKind(itemPayload, out LuaLanguageServerCompletionKind parsedCompletionKind) ? parsedCompletionKind : LuaLanguageServerCompletionKind.Text; - string? detail = BuildCompletionDetail(itemElement); - MarkupContent description = BuildCompletionDescription(itemElement); + string? detail = BuildCompletionDetail(itemPayload); + MarkupContent description = BuildCompletionDescription(itemPayload); string? searchableDescription = NormalizeMarkupText(description.Text); var textAnalysis = new CompletionTextAnalysis(detail, searchableDescription); @@ -195,7 +156,7 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< detail, description.Text, filterText, - BuildCompletionPriority(itemElement, textAnalysis, itemIndex), + BuildCompletionPriority(itemPayload, textAnalysis, itemIndex), BuildCompletionIconKind(completionKind, textAnalysis), description.IsMarkdown, resolveAsync, @@ -203,38 +164,25 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< insertCaretOffset: insertCaretOffset); } - private static LuaCompletionTextEdit? ExtractCompletionTextEdit(JsonElement itemElement, out string? textEditText) + private static LuaCompletionTextEdit? ExtractCompletionTextEdit(LuaCompletionItemPayload itemPayload, out string? textEditText) { textEditText = null; - if (!itemElement.TryGetProperty("textEdit", out JsonElement textEditElement) - || textEditElement.ValueKind != JsonValueKind.Object) - { + if (itemPayload.TextEdit is not { } textEditElement) return null; - } - textEditText = textEditElement.TryGetProperty("newText", out JsonElement newTextElement) - ? newTextElement.GetString() - : null; + textEditText = textEditElement.NewText; return ParseCompletionTextEdit(textEditElement); } - private static LuaCompletionTextEdit? ParseCompletionTextEdit(JsonElement textEditElement) + private static LuaCompletionTextEdit? ParseCompletionTextEdit(LuaCompletionTextEditPayload textEditElement) { - if (textEditElement.ValueKind != JsonValueKind.Object) - return null; - - if (textEditElement.TryGetProperty("range", out JsonElement rangeElement) - && TryParseCompletionRange(rangeElement, out LuaCompletionRange range)) - { + if (TryParseCompletionRange(textEditElement.Range, out LuaCompletionRange range)) return new LuaCompletionTextEdit(range); - } - if (textEditElement.TryGetProperty("insert", out JsonElement insertRangeElement) - && textEditElement.TryGetProperty("replace", out JsonElement replaceRangeElement) - && TryParseCompletionRange(insertRangeElement, out LuaCompletionRange insertRange) - && TryParseCompletionRange(replaceRangeElement, out LuaCompletionRange replaceRange)) + if (TryParseCompletionRange(textEditElement.Insert, out LuaCompletionRange insertRange) + && TryParseCompletionRange(textEditElement.Replace, out LuaCompletionRange replaceRange)) { return new LuaCompletionTextEdit(insertRange, replaceRange); } @@ -242,12 +190,12 @@ public static IReadOnlyList ParseCompletionItems(IEnumerable< return null; } - private static bool TryParseCompletionRange(JsonElement rangeElement, out LuaCompletionRange range) + private static bool TryParseCompletionRange(LuaProtocolRangePayload? rangeElement, out LuaCompletionRange range) { range = default; - if (!TryParseCompletionPosition(rangeElement, "start", out LuaCompletionPosition start) - || !TryParseCompletionPosition(rangeElement, "end", out LuaCompletionPosition end)) + if (!TryParseCompletionPosition(rangeElement?.Start, out LuaCompletionPosition start) + || !TryParseCompletionPosition(rangeElement?.End, out LuaCompletionPosition end)) { return false; } @@ -256,25 +204,15 @@ private static bool TryParseCompletionRange(JsonElement rangeElement, out LuaCom return true; } - private static bool TryParseCompletionPosition(JsonElement parentElement, string propertyName, out LuaCompletionPosition position) + private static bool TryParseCompletionPosition(LuaProtocolNullablePosition? positionElement, out LuaCompletionPosition position) { position = default; - if (!parentElement.TryGetProperty(propertyName, out JsonElement positionElement) - || positionElement.ValueKind != JsonValueKind.Object) - { + if (positionElement is not { Line: int line, Character: int character }) return false; - } - if (!positionElement.TryGetProperty("line", out JsonElement lineElement) - || !lineElement.TryGetInt32(out int line) - || !positionElement.TryGetProperty("character", out JsonElement characterElement) - || !characterElement.TryGetInt32(out int character) - || line < 0 - || character < 0) - { + if (line < 0 || character < 0) return false; - } position = new LuaCompletionPosition(line, character); return true; @@ -295,18 +233,14 @@ private static class CompletionPriorityWeights private static bool CompletionItemNeedsResolve(LuaCompletionItem item) => string.IsNullOrEmpty(item.Detail) || string.IsNullOrEmpty(item.Description); - private static double BuildCompletionPriority(JsonElement itemElement, CompletionTextAnalysis textAnalysis, int itemIndex) + private static double BuildCompletionPriority(LuaCompletionItemPayload itemPayload, CompletionTextAnalysis textAnalysis, int itemIndex) { double priority = CompletionPriorityWeights.ResponseOrderWeight - itemIndex; - if (itemElement.TryGetProperty("preselect", out JsonElement preselectElement) - && preselectElement.ValueKind == JsonValueKind.True) - { + if (itemPayload.Preselect == true) priority += CompletionPriorityWeights.PreselectedBonus; - } - if (itemElement.TryGetProperty("kind", out JsonElement kindElement) - && kindElement.TryGetInt32(out int completionKind)) + if (itemPayload.Kind is int completionKind) { priority += completionKind switch { @@ -329,12 +263,11 @@ private static double BuildCompletionPriority(JsonElement itemElement, Completio return priority; } - private static bool TryReadCompletionKind(JsonElement itemElement, out LuaLanguageServerCompletionKind kind) + private static bool TryReadCompletionKind(LuaCompletionItemPayload itemPayload, out LuaLanguageServerCompletionKind kind) { kind = LuaLanguageServerCompletionKind.Text; - if (!itemElement.TryGetProperty("kind", out JsonElement kindElement) - || !kindElement.TryGetInt32(out int rawKind) + if (itemPayload.Kind is not int rawKind || !Enum.IsDefined(typeof(LuaLanguageServerCompletionKind), rawKind)) { return false; @@ -415,19 +348,19 @@ private static bool ContainsToken(string? text, string token) return null; } - private static string? BuildCompletionDetail(JsonElement itemElement) + private static string? BuildCompletionDetail(LuaCompletionItemPayload itemPayload) { - if (!itemElement.TryGetProperty("detail", out JsonElement detailElement)) - return null; - - string? detail = detailElement.GetString(); + string? detail = itemPayload.Detail; return string.IsNullOrWhiteSpace(detail) ? null : detail.Trim(); } - private static MarkupContent BuildCompletionDescription(JsonElement itemElement) + private static MarkupContent BuildCompletionDescription(LuaCompletionItemPayload itemPayload) { - if (!itemElement.TryGetProperty("documentation", out JsonElement documentationElement)) + if (itemPayload.Documentation is not { } documentationElement + || documentationElement.ValueKind == JsonValueKind.Undefined) + { return default; + } MarkupContent documentation = ExtractMarkupContent(documentationElement); @@ -464,6 +397,7 @@ private static LuaSnippetPlaceholderResult StripSnippetPlaceholders(string snipp { string placeholder = snippet[(index + 2)..endIndex]; int separatorIndex = placeholder.IndexOf(':'); + ReadOnlySpan placeholderNumber = separatorIndex >= 0 ? placeholder.AsSpan(0, separatorIndex) : placeholder.AsSpan(); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaSnippetPlaceholderResult.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaSnippetPlaceholderResult.cs new file mode 100644 index 0000000000..7686de4394 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Completion/LuaSnippetPlaceholderResult.cs @@ -0,0 +1,6 @@ +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents snippet text after placeholder stripping and the resolved caret placement. +/// +public readonly record struct LuaSnippetPlaceholderResult(string Text, int? CaretOffset); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaLanguageServerDiagnosticsParser.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Diagnostics/LuaLanguageServerDiagnosticsParser.cs similarity index 71% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaLanguageServerDiagnosticsParser.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Diagnostics/LuaLanguageServerDiagnosticsParser.cs index c54da83d02..4defa85d13 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaLanguageServerDiagnosticsParser.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Diagnostics/LuaLanguageServerDiagnosticsParser.cs @@ -1,59 +1,39 @@ -#nullable enable - -using System; -using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using System.Linq; using System.Text; using System.Text.Json; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; -internal static class LuaLanguageServerDiagnosticsParser +public static class LuaLanguageServerDiagnosticsParser { /// /// Parses a LuaLS diagnostics notification into editor diagnostics for a tracked document. /// - public static bool TryParse(JsonElement parameters, string filePath, + public static bool TryParse(LuaPublishDiagnosticsParams parameters, string filePath, string documentContent, int documentVersion, [NotNullWhen(true)] out LuaPublishedDiagnostics? publishedDiagnostics) { publishedDiagnostics = null; - if (parameters.ValueKind != JsonValueKind.Object) - return false; - - int diagnosticsVersion = 0; - - if (parameters.TryGetProperty("version", out JsonElement versionElement) - && versionElement.ValueKind == JsonValueKind.Number - && versionElement.TryGetInt32(out int parsedVersion) - && parsedVersion > 0) - { - diagnosticsVersion = parsedVersion; - } + int diagnosticsVersion = parameters.Version is > 0 ? parameters.Version.Value : 0; if (diagnosticsVersion > 0 && documentVersion > 0 && diagnosticsVersion != documentVersion) return false; - IReadOnlyList diagnostics = []; - - if (parameters.TryGetProperty("diagnostics", out JsonElement diagnosticsElement) - && diagnosticsElement.ValueKind == JsonValueKind.Array) - { - diagnostics = BuildDiagnostics(documentContent, diagnosticsElement); - } + IReadOnlyList diagnostics = parameters.Diagnostics is { Length: > 0 } + ? BuildDiagnostics(documentContent, parameters.Diagnostics) + : []; publishedDiagnostics = new LuaPublishedDiagnostics(filePath, diagnostics, diagnosticsVersion); return true; } - private static IReadOnlyList BuildDiagnostics(string content, JsonElement diagnosticsElement) + private static IReadOnlyList BuildDiagnostics(string content, LuaDiagnosticPayload[] diagnosticsPayloads) { LuaDocumentLineOffsets lineOffsets = LuaDocumentLineOffsets.Build(content); var diagnostics = new List(); - foreach (JsonElement diagnosticElement in diagnosticsElement.EnumerateArray()) + foreach (LuaDiagnosticPayload diagnosticElement in diagnosticsPayloads) { TextEditorDiagnosticSeverity severity = GetDiagnosticSeverity(diagnosticElement); @@ -71,43 +51,34 @@ private static IReadOnlyList BuildDiagnostics(string conte .ThenBy(diagnostic => diagnostic.Severity)]; } - private static bool TryCreateDiagnostic(LuaDocumentLineOffsets lineOffsets, JsonElement diagnosticElement, + private static bool TryCreateDiagnostic(LuaDocumentLineOffsets lineOffsets, LuaDiagnosticPayload diagnosticElement, TextEditorDiagnosticSeverity severity, [NotNullWhen(true)] out TextEditorDiagnostic? diagnostic) { diagnostic = null; if (lineOffsets.LineCount == 0 - || !diagnosticElement.TryGetProperty("range", out JsonElement rangeElement) - || !rangeElement.TryGetProperty("start", out JsonElement startElement) - || startElement.ValueKind != JsonValueKind.Object - || !startElement.TryGetProperty("line", out JsonElement lineElement) - || !lineElement.TryGetInt32(out int lineIndex)) + || diagnosticElement.Range is not { } rangeElement + || rangeElement.Start is not { } startElement + || startElement.Line is not int lineIndex) { return false; } lineIndex = Math.Max(0, Math.Min(lineIndex, lineOffsets.LineCount - 1)); - int startCharacter = startElement.TryGetProperty("character", out JsonElement characterElement) - && characterElement.TryGetInt32(out int character) - ? Math.Max(0, character) - : 0; + int startCharacter = startElement.Character is int character + ? Math.Max(0, character) + : 0; int endLineIndex = lineIndex; int endCharacter = startCharacter; - if (rangeElement.TryGetProperty("end", out JsonElement endElement) - && endElement.ValueKind == JsonValueKind.Object - && endElement.TryGetProperty("line", out JsonElement endLineElement) - && endLineElement.TryGetInt32(out int rawEndLineIndex)) + if (rangeElement.End is { } endElement && endElement.Line is int rawEndLineIndex) { endLineIndex = Math.Max(lineIndex, Math.Min(rawEndLineIndex, lineOffsets.LineCount - 1)); - if (endElement.TryGetProperty("character", out JsonElement endCharacterElement) - && endCharacterElement.TryGetInt32(out int endCharacterValue)) - { + if (endElement.Character is int endCharacterValue) endCharacter = Math.Max(0, endCharacterValue); - } } if (!TryGetDiagnosticOffsets(lineOffsets, lineIndex, startCharacter, endLineIndex, endCharacter, @@ -239,20 +210,17 @@ private static bool TryGetWordBounds(string lineText, int index, out int wordSta private static bool IsDiagnosticSegmentCharacter(char c) => char.IsLetterOrDigit(c) || c == '_' || c == '.' || c == ':' || c == '\'' || c == '"'; - private static TextEditorDiagnosticSeverity GetDiagnosticSeverity(JsonElement diagnosticElement) + private static TextEditorDiagnosticSeverity GetDiagnosticSeverity(LuaDiagnosticPayload diagnosticElement) { - return diagnosticElement.TryGetProperty("severity", out JsonElement severityElement) - && severityElement.TryGetInt32(out int severity) + return diagnosticElement.Severity is int severity && severity > 0 ? (TextEditorDiagnosticSeverity)severity : TextEditorDiagnosticSeverity.Warning; } - private static string BuildDiagnosticMessage(JsonElement diagnosticElement, TextEditorDiagnosticSeverity severity) + private static string BuildDiagnosticMessage(LuaDiagnosticPayload diagnosticElement, TextEditorDiagnosticSeverity severity) { - string? message = diagnosticElement.TryGetProperty("message", out JsonElement messageElement) - ? messageElement.GetString()?.Trim() - : null; + string? message = diagnosticElement.Message?.Trim(); if (string.IsNullOrWhiteSpace(message)) message = "Unknown Lua diagnostic."; @@ -262,11 +230,9 @@ private static string BuildDiagnosticMessage(JsonElement diagnosticElement, Text builder.Append(": "); builder.Append(message); - string? source = diagnosticElement.TryGetProperty("source", out JsonElement sourceElement) - ? sourceElement.GetString() - : null; + string? source = diagnosticElement.Source; - string? code = diagnosticElement.TryGetProperty("code", out JsonElement codeElement) + string? code = diagnosticElement.Code is { } codeElement ? codeElement.ValueKind == JsonValueKind.String ? codeElement.GetString() : codeElement.ValueKind == JsonValueKind.Number diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaPublishedDiagnostics.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Diagnostics/LuaPublishedDiagnostics.cs similarity index 87% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaPublishedDiagnostics.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Diagnostics/LuaPublishedDiagnostics.cs index 71f8f39b39..6424914d72 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Diagnostics/LuaPublishedDiagnostics.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Diagnostics/LuaPublishedDiagnostics.cs @@ -1,14 +1,11 @@ -#nullable enable - -using System.Collections.Generic; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Represents a diagnostics payload published by LuaLS for a specific document version. /// -internal sealed class LuaPublishedDiagnostics +public sealed class LuaPublishedDiagnostics { /// /// Initializes a new instance of the class. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentLineOffsets.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentLineOffsets.cs similarity index 95% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentLineOffsets.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentLineOffsets.cs index 28b0e85ccf..b656c8782b 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentLineOffsets.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentLineOffsets.cs @@ -1,9 +1,4 @@ -#nullable enable - -using System; -using System.Collections.Generic; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Provides a precomputed table of line start offsets and lengths for a Lua document content string. @@ -11,7 +6,7 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; /// diagnostics and semantic tokens, which only need to translate between line/character and document offsets. /// Both \r\n and lone \r are treated as line breaks for parity with LSP positions. /// -internal sealed class LuaDocumentLineOffsets +public sealed class LuaDocumentLineOffsets { private readonly string _content; private readonly int[] _lineStartOffsets; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentRenameRequest.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentRenameRequest.cs similarity index 56% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentRenameRequest.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentRenameRequest.cs index 7402052299..3a1d7a2ce4 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentRenameRequest.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentRenameRequest.cs @@ -1,11 +1,9 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Describes a tracked-document path rekey that may need to be mirrored to LuaLS as a close/open pair. /// -internal readonly record struct LuaDocumentRenameRequest( +public readonly record struct LuaDocumentRenameRequest( LuaDocumentSnapshot? PreviousDocument, LuaDocumentSnapshot RenamedDocument, - bool ReopenServerDocument); \ No newline at end of file + bool ReopenServerDocument); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSnapshot.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSnapshot.cs similarity index 90% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSnapshot.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSnapshot.cs index 132dda738b..0930660f33 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSnapshot.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSnapshot.cs @@ -1,11 +1,9 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Captures the current synchronized state of a tracked Lua document. /// -internal sealed class LuaDocumentSnapshot +public sealed class LuaDocumentSnapshot { /// /// Initializes a new instance of the class. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationKind.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationKind.cs similarity index 72% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationKind.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationKind.cs index 50c30cc53e..8f52ff11f2 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationKind.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationKind.cs @@ -1,11 +1,9 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Identifies the LSP document-synchronization action that should be sent for a tracked file. /// -internal enum LuaDocumentSynchronizationKind +public enum LuaDocumentSynchronizationKind { /// /// The document must be opened on the server. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationRequest.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationRequest.cs similarity index 66% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationRequest.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationRequest.cs index f6d635a32a..98b437fff0 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaDocumentSynchronizationRequest.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationRequest.cs @@ -1,22 +1,20 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Lightweight value-type carrier for an in-flight LuaLS document synchronization request. Returned /// from as a nullable so the per-keystroke /// path does not allocate a heap instance for every character. /// -internal readonly record struct LuaDocumentSynchronizationRequest( +public readonly record struct LuaDocumentSynchronizationRequest( LuaDocumentSynchronizationKind Kind, LuaDocumentSnapshot Document, LuaDocumentChangeRange? ChangeRange = null); /// -/// Describes a single incremental `textDocument/didChange` range edit computed from the difference +/// Describes a single incremental textDocument/didChange range edit computed from the difference /// between the previously-synced and newly-synced document contents. /// -internal readonly record struct LuaDocumentChangeRange( +public readonly record struct LuaDocumentChangeRange( int StartLine, int StartCharacter, int EndLine, diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationResult.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationResult.cs new file mode 100644 index 0000000000..e822b55970 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaDocumentSynchronizationResult.cs @@ -0,0 +1,6 @@ +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the outcome of synchronizing one document with the Lua language server. +/// +public readonly record struct LuaDocumentSynchronizationResult(bool Success, LuaDocumentSnapshot? Document); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIncrementalEditCalculator.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaIncrementalEditCalculator.cs similarity index 94% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIncrementalEditCalculator.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaIncrementalEditCalculator.cs index 53e02df930..a4b59f010c 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIncrementalEditCalculator.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaIncrementalEditCalculator.cs @@ -1,8 +1,4 @@ -#nullable enable - -using System; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Computes a minimal single-range edit that transforms oldText into newText using a @@ -10,7 +6,7 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; /// incremental notification: a server applying the returned range and replacement text to the old /// content reproduces the new content byte-for-byte. /// -internal static class LuaIncrementalEditCalculator +public static class LuaIncrementalEditCalculator { /// /// Computes the minimal single-range edit that transforms one document snapshot into another. @@ -83,6 +79,7 @@ private static (int Line, int Character) OffsetToPosition(LuaDocumentLineOffsets int lineStart = offsets.GetLineStartOffset(low); int character = Math.Max(0, offset - lineStart); + return (low, character); } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaIntellisenseDocumentManager.cs similarity index 90% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaIntellisenseDocumentManager.cs index bf16120f2e..a994d21590 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaIntellisenseDocumentManager.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaIntellisenseDocumentManager.cs @@ -1,17 +1,12 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Tracks the local document state mirrored to LuaLS, including versions, diagnostics, and semantic-token caches. /// -internal sealed class LuaIntellisenseDocumentManager +public sealed class LuaIntellisenseDocumentManager { private sealed class DocumentState { @@ -37,6 +32,7 @@ private sealed class DocumentState // file, kept around so an incoming delta `edits` payload can be applied without forcing the // server to resend the entire token stream. public int[]? SemanticTokensData { get; set; } + public string? SemanticTokensResultId { get; set; } } @@ -166,17 +162,20 @@ public IReadOnlyList GetSemanticTokens(string filePath) /// /// Releases one open reference for . The document is only fully - /// removed (and a `didClose` snapshot returned) once the reference count drops to zero, - /// so multiple editor tabs sharing the same file do not invalidate each other on close. + /// removed once the reference count drops to zero, so multiple editor tabs sharing the same + /// file do not invalidate each other on close. When the server-side document is still open, + /// contains the snapshot that should be mirrored with didClose. + /// If a restart is pending and the server copy is already gone, the document is still removed + /// locally but is . /// /// The normalized file path. - /// When this method returns, contains the closing snapshot if the document was removed. - /// when the caller should send didClose; otherwise, . - public bool TryClose(string filePath, [NotNullWhen(true)] out LuaDocumentSnapshot? document) + /// When this method returns, contains the closing snapshot if the server copy is still open. + /// when the document was removed locally; otherwise, . + public bool TryClose(string filePath, out LuaDocumentSnapshot? document) { lock (_syncRoot) { - if (!_documents.TryGetValue(filePath, out DocumentState? state) || !state.IsOpen) + if (!_documents.TryGetValue(filePath, out DocumentState? state)) { document = null; return false; @@ -191,14 +190,16 @@ public bool TryClose(string filePath, [NotNullWhen(true)] out LuaDocumentSnapsho return false; } - document = CreateSnapshot(state); + document = state.IsOpen ? CreateSnapshot(state) : null; _documents.Remove(filePath); return true; } } /// - /// Marks all open documents for replay after a language-server restart and returns their snapshots. + /// Marks every tracked document as closed on the server after a language-server restart. Documents + /// that still have live editor references are returned so the provider can reopen them eagerly on + /// the next successful start, while request-only tracked documents reopen lazily on demand. /// /// The snapshots that should be reopened on the next successful start. public IReadOnlyList PrepareForRestart() @@ -209,11 +210,10 @@ public IReadOnlyList PrepareForRestart() foreach (DocumentState state in _documents.Values) { - if (!state.IsOpen) - continue; - - documentsToReopen.Add(CreateSnapshot(state)); state.IsOpen = false; + + if (state.OpenReferenceCount > 0) + documentsToReopen.Add(CreateSnapshot(state)); } return documentsToReopen; @@ -355,6 +355,7 @@ public bool InvalidateServerSynchronization(string filePath) state.SemanticTokensVersion = 0; state.SemanticTokensResultId = null; state.SemanticTokensData = null; + return true; } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaTextDocumentSyncKind.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaTextDocumentSyncKind.cs similarity index 77% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaTextDocumentSyncKind.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaTextDocumentSyncKind.cs index d31e80d1ae..72ff25cabf 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Documents/LuaTextDocumentSyncKind.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Documents/LuaTextDocumentSyncKind.cs @@ -1,11 +1,9 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Describes the text-document synchronization mode negotiated with LuaLS. /// -internal enum LuaTextDocumentSyncKind +public enum LuaTextDocumentSyncKind { /// /// No document synchronization is supported. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Formatting/LuaLanguageServerResponseParser.Formatting.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Formatting/LuaLanguageServerResponseParser.Formatting.cs similarity index 54% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Formatting/LuaLanguageServerResponseParser.Formatting.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Formatting/LuaLanguageServerResponseParser.Formatting.cs index d14501734b..5a255dc9bd 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Formatting/LuaLanguageServerResponseParser.Formatting.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Formatting/LuaLanguageServerResponseParser.Formatting.cs @@ -1,23 +1,19 @@ -#nullable enable - -using System.Collections.Generic; -using System.Text.Json; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; -internal static partial class LuaLanguageServerResponseParser +public static partial class LuaLanguageServerResponseParser { /// /// Parses document-formatting edits from a LuaLS formatting response. /// - public static IReadOnlyList ParseDocumentFormattingEdits(JsonElement response) + public static IReadOnlyList ParseDocumentFormattingEdits(IReadOnlyList? response) { - if (response.ValueKind != JsonValueKind.Array) + if (response is null) return []; var textEdits = new List(); AppendTextEdits(response, textEdits); return textEdits; } -} \ No newline at end of file +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaHoverPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaHoverPayloads.cs new file mode 100644 index 0000000000..d3e62e0a95 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaHoverPayloads.cs @@ -0,0 +1,13 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the typed top-level hover payload returned by LuaLS. +/// +public sealed record LuaHoverResponse +{ + [JsonPropertyName("contents")] + public JsonElement Contents { get; init; } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaLanguageServerResponseParser.Hover.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaLanguageServerResponseParser.Hover.cs new file mode 100644 index 0000000000..c24e7d3df6 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Hover/LuaLanguageServerResponseParser.Hover.cs @@ -0,0 +1,22 @@ +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses hover content from a LuaLS hover response. + /// + public static LuaHoverInfo? ParseHoverInfo(LuaHoverResponse? response) + { + if (response is null || response.Contents.ValueKind == JsonValueKind.Undefined) + return null; + + MarkupContent hoverContent = ExtractMarkupContent(response.Contents); + + return string.IsNullOrWhiteSpace(hoverContent.Text) + ? null + : new LuaHoverInfo(hoverContent.Text.Trim(), hoverContent.IsMarkdown); + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/ILuaLanguageServerClient.cs similarity index 86% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/ILuaLanguageServerClient.cs index 7bf4144f45..274b71c20c 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/ILuaLanguageServerClient.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/ILuaLanguageServerClient.cs @@ -1,17 +1,9 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Defines the transport and capability surface used by the Lua IntelliSense provider to talk to LuaLS. /// -internal interface ILuaLanguageServerClient : IDisposable +public interface ILuaLanguageServerClient : IDisposable { /// /// Gets a value indicating whether the language server finished initialization and can accept requests. @@ -66,7 +58,7 @@ internal interface ILuaLanguageServerClient : IDisposable /// /// Occurs when the server publishes diagnostics for a tracked document. /// - event Action? DiagnosticsPublished; + event Action? DiagnosticsPublished; /// /// Occurs when the server requests a semantic-token refresh for open documents. @@ -94,11 +86,12 @@ internal interface ILuaLanguageServerClient : IDisposable Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken); /// - /// Sends a JSON-RPC request to the language server and waits for the response payload. + /// Sends a JSON-RPC request to the language server and waits for a typed response payload. /// + /// The typed response payload to deserialize. /// The LSP method name. /// The request payload. /// A token that can cancel the request. - /// The raw JSON response payload. - Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken); + /// The typed response payload. + Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken); } diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCallbackPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCallbackPayloads.cs new file mode 100644 index 0000000000..daf308b4b7 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCallbackPayloads.cs @@ -0,0 +1,46 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public readonly record struct LuaEmptyParams(); + +public readonly record struct LuaWorkspaceConfigurationParams( + [property: JsonPropertyName("items")] LuaWorkspaceConfigurationItem[]? Items); + +public readonly record struct LuaWorkspaceConfigurationItem( + [property: JsonPropertyName("section")] string? Section); + +public readonly record struct LuaWorkspaceFolder( + [property: JsonPropertyName("uri")] string Uri, + [property: JsonPropertyName("name")] string Name); + +public readonly record struct LuaWindowMessageParams( + [property: JsonPropertyName("type")] int? Type, + [property: JsonPropertyName("message")] string? Message); + +/// +/// Represents a typed diagnostics notification raised by LuaLS for a tracked document. +/// +public readonly record struct LuaPublishDiagnosticsParams( + [property: JsonPropertyName("uri")] string? Uri, + [property: JsonPropertyName("version")] int? Version, + [property: JsonPropertyName("diagnostics")] LuaDiagnosticPayload[]? Diagnostics); + +/// +/// Represents a single diagnostic entry from a publish-diagnostics notification. +/// +public readonly record struct LuaDiagnosticPayload( + [property: JsonPropertyName("range")] LuaProtocolRangePayload? Range, + [property: JsonPropertyName("severity")] int? Severity, + [property: JsonPropertyName("message")] string? Message, + [property: JsonPropertyName("source")] string? Source, + [property: JsonPropertyName("code")] JsonElement? Code); + +public readonly record struct LuaProtocolRangePayload( + [property: JsonPropertyName("start")] LuaProtocolNullablePosition? Start, + [property: JsonPropertyName("end")] LuaProtocolNullablePosition? End); + +public readonly record struct LuaProtocolNullablePosition( + [property: JsonPropertyName("line")] int? Line, + [property: JsonPropertyName("character")] int? Character); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCapabilityPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCapabilityPayloads.cs new file mode 100644 index 0000000000..eaeb96141a --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerCapabilityPayloads.cs @@ -0,0 +1,195 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the typed result of the LSP initialize request. +/// +public sealed record LuaInitializeResponse +{ + [JsonPropertyName("capabilities")] + public LuaServerCapabilities? Capabilities { get; init; } +} + +/// +/// Represents the subset of LuaLS capabilities consumed by the host Lua IntelliSense provider. +/// +public sealed record LuaServerCapabilities +{ + [JsonPropertyName("textDocumentSync")] + public LuaTextDocumentSyncCapability? TextDocumentSync { get; init; } + + [JsonPropertyName("completionProvider")] + public LuaCompletionProviderCapability? CompletionProvider { get; init; } + + [JsonPropertyName("referencesProvider")] + public LuaSupportedCapability? ReferencesProvider { get; init; } + + [JsonPropertyName("renameProvider")] + public LuaSupportedCapability? RenameProvider { get; init; } + + [JsonPropertyName("documentFormattingProvider")] + public LuaSupportedCapability? DocumentFormattingProvider { get; init; } + + [JsonPropertyName("semanticTokensProvider")] + public LuaSemanticTokensProviderCapability? SemanticTokensProvider { get; init; } +} + +public sealed record LuaCompletionProviderCapability +{ + [JsonPropertyName("resolveProvider")] + public bool? ResolveProvider { get; init; } +} + +public sealed record LuaSemanticTokensProviderCapability +{ + [JsonPropertyName("full")] + public LuaSemanticTokensFullCapability? Full { get; init; } + + [JsonPropertyName("legend")] + public LuaSemanticTokensLegendCapability? Legend { get; init; } +} + +public sealed record LuaSemanticTokensLegendCapability +{ + [JsonPropertyName("tokenTypes")] + public string[]? TokenTypes { get; init; } + + [JsonPropertyName("tokenModifiers")] + public string[]? TokenModifiers { get; init; } +} + +[JsonConverter(typeof(LuaSupportedCapabilityJsonConverter))] +public readonly record struct LuaSupportedCapability(bool IsSupported); + +[JsonConverter(typeof(LuaTextDocumentSyncCapabilityJsonConverter))] +public readonly record struct LuaTextDocumentSyncCapability(LuaTextDocumentSyncKind Kind); + +[JsonConverter(typeof(LuaSemanticTokensFullCapabilityJsonConverter))] +public readonly record struct LuaSemanticTokensFullCapability(bool SupportsDelta); + +/// +/// Deserializes LSP capability fields that may be advertised as either booleans or objects. +/// +public sealed class LuaSupportedCapabilityJsonConverter : JsonConverter +{ + public override LuaSupportedCapability Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.True => new LuaSupportedCapability(true), + JsonTokenType.False => new LuaSupportedCapability(false), + JsonTokenType.StartObject => ReadObject(ref reader), + JsonTokenType.Null => default, + _ => ReadUnsupported(ref reader) + }; + } + + public override void Write(Utf8JsonWriter writer, LuaSupportedCapability value, JsonSerializerOptions options) + => throw new NotSupportedException(); + + private static LuaSupportedCapability ReadObject(ref Utf8JsonReader reader) + { + using JsonDocument ignored = JsonDocument.ParseValue(ref reader); + return new LuaSupportedCapability(true); + } + + private static LuaSupportedCapability ReadUnsupported(ref Utf8JsonReader reader) + { + using JsonDocument ignored = JsonDocument.ParseValue(ref reader); + return new LuaSupportedCapability(false); + } +} + +/// +/// Deserializes the LSP text-document sync capability from either numeric or object form. +/// +public sealed class LuaTextDocumentSyncCapabilityJsonConverter : JsonConverter +{ + public override LuaTextDocumentSyncCapability Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + switch (reader.TokenType) + { + case JsonTokenType.Number: + return reader.TryGetInt32(out int rawSyncKind) + ? new LuaTextDocumentSyncCapability(ParseTextDocumentSyncKind(rawSyncKind)) + : new LuaTextDocumentSyncCapability(LuaTextDocumentSyncKind.None); + + case JsonTokenType.StartObject: + return ReadObject(ref reader); + + case JsonTokenType.Null: + return default; + + default: + using (JsonDocument ignored = JsonDocument.ParseValue(ref reader)) + { } + + return new LuaTextDocumentSyncCapability(LuaTextDocumentSyncKind.None); + } + } + + public override void Write(Utf8JsonWriter writer, LuaTextDocumentSyncCapability value, JsonSerializerOptions options) + => throw new NotSupportedException(); + + private static LuaTextDocumentSyncCapability ReadObject(ref Utf8JsonReader reader) + { + using JsonDocument document = JsonDocument.ParseValue(ref reader); + JsonElement root = document.RootElement; + + if (!root.TryGetProperty("change", out JsonElement changeElement) + || !changeElement.TryGetInt32(out int rawSyncKind)) + { + return new LuaTextDocumentSyncCapability(LuaTextDocumentSyncKind.None); + } + + return new LuaTextDocumentSyncCapability(ParseTextDocumentSyncKind(rawSyncKind)); + } + + private static LuaTextDocumentSyncKind ParseTextDocumentSyncKind(int rawSyncKind) => rawSyncKind switch + { + 0 => LuaTextDocumentSyncKind.None, + 1 => LuaTextDocumentSyncKind.Full, + 2 => LuaTextDocumentSyncKind.Incremental, + _ => LuaTextDocumentSyncKind.None + }; +} + +/// +/// Deserializes the semantic-token full capability and whether delta refresh is supported. +/// +public sealed class LuaSemanticTokensFullCapabilityJsonConverter : JsonConverter +{ + public override LuaSemanticTokensFullCapability Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return reader.TokenType switch + { + JsonTokenType.True => new LuaSemanticTokensFullCapability(false), + JsonTokenType.False => new LuaSemanticTokensFullCapability(false), + JsonTokenType.StartObject => ReadObject(ref reader), + JsonTokenType.Null => default, + _ => ReadUnsupported(ref reader) + }; + } + + public override void Write(Utf8JsonWriter writer, LuaSemanticTokensFullCapability value, JsonSerializerOptions options) + => throw new NotSupportedException(); + + private static LuaSemanticTokensFullCapability ReadObject(ref Utf8JsonReader reader) + { + using JsonDocument document = JsonDocument.ParseValue(ref reader); + JsonElement root = document.RootElement; + + bool supportsDelta = root.TryGetProperty("delta", out JsonElement deltaElement) + && deltaElement.ValueKind == JsonValueKind.True; + + return new LuaSemanticTokensFullCapability(supportsDelta); + } + + private static LuaSemanticTokensFullCapability ReadUnsupported(ref Utf8JsonReader reader) + { + using JsonDocument ignored = JsonDocument.ParseValue(ref reader); + return new LuaSemanticTokensFullCapability(false); + } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Diagnostics.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Diagnostics.cs new file mode 100644 index 0000000000..ee042eac58 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Diagnostics.cs @@ -0,0 +1,86 @@ +using System.Collections.Concurrent; +using System.Threading.Channels; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public sealed partial class LuaLanguageServerClient +{ + private readonly record struct QueuedDiagnostics(long TransportGeneration, LuaPublishDiagnosticsParams Parameters); + + private readonly ConcurrentDictionary _pendingDiagnostics = new(StringComparer.OrdinalIgnoreCase); + + // Diagnostics arrive on the LSP read loop and are stored as the latest payload per file URI. + // A bounded single-slot channel acts only as a wake signal for the pump, so bursty notifications + // for the same file collapse to one queued wake-up instead of building an unbounded backlog. + private readonly Channel _diagnosticsSignal = Channel.CreateBounded( + new BoundedChannelOptions(1) + { + SingleReader = true, + SingleWriter = true, + AllowSynchronousContinuations = false, + FullMode = BoundedChannelFullMode.DropWrite + }); + + private Task? _diagnosticsPumpTask; + private long _diagnosticsFallbackSequence; + + /// + /// Occurs when the server publishes diagnostics for a tracked document. + /// + public event Action? DiagnosticsPublished; + + private void RaiseDiagnosticsPublished(long transportGeneration, LuaPublishDiagnosticsParams parameters) + { + // Stash only the newest diagnostics payload per file and wake the pump if it is idle. + // Parameters were already cloned by the dispatcher in HandleMessageAsync. + _pendingDiagnostics[GetDiagnosticsQueueKey(parameters)] = new QueuedDiagnostics(transportGeneration, parameters); + _diagnosticsSignal.Writer.TryWrite(true); + } + + private async Task PumpDiagnosticsAsync() + { + ChannelReader reader = _diagnosticsSignal.Reader; + + try + { + while (await reader.WaitToReadAsync(_lifetimeCts.Token).ConfigureAwait(false)) + { + while (reader.TryRead(out _)) + { } + + while (!_pendingDiagnostics.IsEmpty) + { + KeyValuePair[] pendingDiagnostics = [.. _pendingDiagnostics]; + + for (int i = 0; i < pendingDiagnostics.Length; i++) + { + if (!_pendingDiagnostics.TryRemove(pendingDiagnostics[i].Key, out QueuedDiagnostics queuedDiagnostics) + || queuedDiagnostics.TransportGeneration != Volatile.Read(ref _activeTransportGeneration)) + continue; + + try + { + DiagnosticsPublished?.Invoke(queuedDiagnostics.Parameters); + } + catch (Exception exception) + { + Log.Warn(exception, "Lua diagnostics handler threw; the diagnostics pump is being kept alive."); + } + } + } + } + } + catch (OperationCanceledException) + { + // Expected on dispose. + } + } + + private string GetDiagnosticsQueueKey(LuaPublishDiagnosticsParams parameters) + { + if (!string.IsNullOrWhiteSpace(parameters.Uri)) + return parameters.Uri; + + return "diagnostics:" + Interlocked.Increment(ref _diagnosticsFallbackSequence); + } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs new file mode 100644 index 0000000000..91730853c5 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.Protocol.cs @@ -0,0 +1,146 @@ +using StreamJsonRpc; +using System.Text.Json; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public sealed partial class LuaLanguageServerClient +{ + private Task SendNotificationCoreAsync(LuaLanguageServerTransportSession session, string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) + { + ThrowIfDisposed(allowDisposed); + + if (cancellationToken.IsCancellationRequested) + return Task.FromCanceled(cancellationToken); + + JsonRpc jsonRpc = session.JsonRpc + ?? throw new IOException("The Lua language server JSON-RPC transport is not available."); + + return jsonRpc.NotifyWithParameterObjectAsync(method, parameters); + } + + private Task SendRequestCoreAsync(LuaLanguageServerTransportSession session, string method, object parameters, CancellationToken cancellationToken, bool allowDisposed) + { + ThrowIfDisposed(allowDisposed); + + JsonRpc jsonRpc = session.JsonRpc + ?? throw new IOException("The Lua language server JSON-RPC transport is not available."); + + return jsonRpc.InvokeWithParameterObjectAsync(method, parameters, cancellationToken); + } + + private object[] BuildConfigurationResponse(LuaWorkspaceConfigurationParams parameters) + { + LuaWorkspaceConfigurationItem[] items = parameters.Items ?? []; + + if (items.Length == 0) + return []; + + JsonElement settingsElement = JsonSerializer.SerializeToElement(_settingsProvider()); + JsonElement luaElement = settingsElement.GetProperty("Lua"); + + var results = new List(); + + foreach (LuaWorkspaceConfigurationItem item in items) + results.Add(GetConfigurationSection(settingsElement, luaElement, item.Section)); + + return [.. results]; + } + + private static object GetConfigurationSection(JsonElement settingsElement, JsonElement luaElement, string? section) + { + if (string.IsNullOrWhiteSpace(section)) + return settingsElement.Clone(); + + if (section.Equals("Lua", StringComparison.OrdinalIgnoreCase)) + return luaElement.Clone(); + + if (section.StartsWith("Lua.", StringComparison.OrdinalIgnoreCase)) + { + JsonElement nestedSection = luaElement; + string[] parts = section[4..].Split('.'); + + foreach (string part in parts) + { + if (!nestedSection.TryGetProperty(part, out JsonElement nextSection)) + return new { }; + + nestedSection = nextSection; + } + + return nestedSection.Clone(); + } + + return new { }; + } + + private sealed class LuaLanguageServerClientRpcTarget + { + private readonly LuaLanguageServerClient _owner; + private readonly long _transportGeneration; + + public LuaLanguageServerClientRpcTarget(LuaLanguageServerClient owner, long transportGeneration) + { + _owner = owner; + _transportGeneration = transportGeneration; + } + + [JsonRpcMethod("workspace/configuration", UseSingleObjectParameterDeserialization = true)] + public object[] WorkspaceConfiguration(LuaWorkspaceConfigurationParams parameters) + => _owner.BuildConfigurationResponse(parameters); + + [JsonRpcMethod("workspace/workspaceFolders")] + public LuaWorkspaceFolder[] WorkspaceFolders() => + [ + new LuaWorkspaceFolder( + LuaLanguageServerPathHelper.CreateFileUri(_owner._workspaceRootDirectoryPath), + Path.GetFileName(_owner._workspaceRootDirectoryPath)) + ]; + + [JsonRpcMethod("workspace/semanticTokens/refresh")] + public Task RefreshSemanticTokensAsync() + { + try + { + _owner.SemanticTokensRefreshRequested?.Invoke(); + } + catch (Exception exception) + { + Log.Warn(exception, "Lua semantic-tokens refresh request handler threw; acknowledging the request anyway."); + } + + return Task.FromResult(null); + } + + [JsonRpcMethod("client/registerCapability", UseSingleObjectParameterDeserialization = true)] + public object? RegisterCapability(LuaEmptyParams parameters) + => null; + + [JsonRpcMethod("client/unregisterCapability", UseSingleObjectParameterDeserialization = true)] + public object? UnregisterCapability(LuaEmptyParams parameters) + => null; + + [JsonRpcMethod("window/workDoneProgress/create", UseSingleObjectParameterDeserialization = true)] + public object? CreateWorkDoneProgress(LuaEmptyParams parameters) + => null; + + [JsonRpcMethod("textDocument/publishDiagnostics", UseSingleObjectParameterDeserialization = true)] + public void PublishDiagnostics(LuaPublishDiagnosticsParams parameters) + => _owner.RaiseDiagnosticsPublished(_transportGeneration, parameters); + + [JsonRpcMethod("window/logMessage", UseSingleObjectParameterDeserialization = true)] + public void LogMessage(LuaWindowMessageParams parameters) + => LogServerMessage("window/logMessage", parameters); + + [JsonRpcMethod("window/showMessage", UseSingleObjectParameterDeserialization = true)] + public void ShowMessage(LuaWindowMessageParams parameters) + => LogServerMessage("window/showMessage", parameters); + + [JsonRpcMethod("telemetry/event", UseSingleObjectParameterDeserialization = true)] + public void TelemetryEvent(LuaEmptyParams parameters) + { } + + [JsonRpcMethod("$/progress", UseSingleObjectParameterDeserialization = true)] + public void Progress(LuaEmptyParams parameters) + { } + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.cs similarity index 69% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.cs index 866ea7b074..d304cc9ec8 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Client/LuaLanguageServerClient.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Client/LuaLanguageServerClient.cs @@ -1,52 +1,25 @@ -#nullable enable - using NLog; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; +using StreamJsonRpc; using System.Diagnostics; -using System.IO; using System.Text.Json; -using System.Threading; -using System.Threading.Channels; -using System.Threading.Tasks; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Hosts the LuaLS process, performs the LSP handshake, and transports JSON-RPC requests and notifications. /// -internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient +public sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); - private const int ReceiveChunkSize = 4096; - private const int MaxPayloadByteCount = 64 * 1024 * 1024; // 64 MiB safety cap for inbound LSP payloads. private static readonly TimeSpan DisposeWaitTimeout = TimeSpan.FromSeconds(3); - private static readonly byte[] HeaderTerminator = [(byte)'\r', (byte)'\n', (byte)'\r', (byte)'\n']; private readonly string _workspaceRootDirectoryPath; private readonly string _serverExecutablePath; private readonly Func _settingsProvider; private readonly SemaphoreSlim _startLock = new(1, 1); - private readonly SemaphoreSlim _writeLock = new(1, 1); private readonly CancellationTokenSource _lifetimeCts = new(); - private readonly ConcurrentDictionary _pendingDiagnostics = new(StringComparer.OrdinalIgnoreCase); - - // Diagnostics arrive on the LSP read loop and are stored as the latest payload per file URI. - // A bounded single-slot channel acts only as a wake signal for the pump, so bursty notifications - // for the same file collapse to one queued wake-up instead of building an unbounded backlog. - private readonly Channel _diagnosticsSignal = Channel.CreateBounded( - new BoundedChannelOptions(1) - { - SingleReader = true, - SingleWriter = true, - AllowSynchronousContinuations = false, - FullMode = BoundedChannelFullMode.DropWrite - }); - - private Task? _diagnosticsPumpTask; private static readonly string[] SupportedSemanticTokenTypes = [ @@ -62,8 +35,6 @@ internal sealed partial class LuaLanguageServerClient : ILuaLanguageServerClient "async", "modification", "documentation", "defaultLibrary", "global" ]; - private long _requestId; - private long _diagnosticsFallbackSequence; private long _transportGeneration; private long _activeTransportGeneration; private volatile bool _isDisposed; @@ -89,7 +60,7 @@ public bool IsReady } /// - /// Gets the current transport generation for the active server session. + /// Gets the current transport generation for the active language-server session. /// public long TransportGeneration => Volatile.Read(ref _activeTransportGeneration); @@ -133,11 +104,6 @@ public bool IsReady /// public bool SupportsSemanticTokensDelta => _supportsSemanticTokensDelta; - /// - /// Occurs when the server publishes diagnostics for a tracked document. - /// - public event Action? DiagnosticsPublished; - /// /// Occurs when the server requests that semantic tokens be refreshed. /// @@ -204,23 +170,25 @@ public async Task StartAsync(CancellationToken cancellationToken) LuaLanguageServerTransportSession session = CreateTransportSession(process); SetActiveSession(session); + _diagnosticsPumpTask ??= Task.Run(PumpDiagnosticsAsync, CancellationToken.None); // Complete the LSP handshake before marking the client ready for provider requests. using var initializeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); initializeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); - JsonElement initializeResponse = await SendRequestCoreAsync(session, + LuaInitializeResponse initializeResponse = await SendRequestCoreAsync(session, "initialize", BuildInitializeParams(), initializeTimeout.Token, allowDisposed: false).ConfigureAwait(false); + CaptureServerCapabilities(initializeResponse); IsReady = true; - await SendNotificationCoreAsync(session, "initialized", new { }, cancellationToken, allowDisposed: false).ConfigureAwait(false); + await SendNotificationCoreAsync(session, "initialized", new LuaEmptyParams(), cancellationToken, allowDisposed: false).ConfigureAwait(false); await SendNotificationCoreAsync(session, "workspace/didChangeConfiguration", - new { settings = _settingsProvider() }, + new LuaDidChangeConfigurationParams(_settingsProvider()), cancellationToken, allowDisposed: false).ConfigureAwait(false); @@ -253,17 +221,18 @@ await SendNotificationCoreAsync(session, /// The notification payload. /// A token that can cancel the send operation. public Task SendNotificationAsync(string method, object parameters, CancellationToken cancellationToken) - => SendNotificationCoreAsync(method, parameters, cancellationToken, allowDisposed: false); + => SendNotificationCoreAsync(GetRequiredActiveSession(allowDisposed: false), method, parameters, cancellationToken, allowDisposed: false); /// - /// Sends a JSON-RPC request to the language server and returns the raw response payload. + /// Sends a JSON-RPC request to the language server and returns the typed response payload. /// + /// The typed response payload to deserialize. /// The LSP method name. /// The request payload. /// A token that can cancel the request. - /// The raw JSON response payload. - public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) - => SendRequestCoreAsync(method, parameters, cancellationToken, allowDisposed: false); + /// The typed response payload. + public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) + => SendRequestCoreAsync(GetRequiredActiveSession(allowDisposed: false), method, parameters, cancellationToken, allowDisposed: false); /// /// Marks the current transport unhealthy so the provider restarts it on the next request. @@ -284,7 +253,7 @@ public void MarkTransportUnhealthy() changeConfiguration = true, viewDocument = true, // Do NOT set trustByClient = true: LuaLS uses that flag to skip the user prompt before - // loading workspace-supplied plugins (runtime.plugin in .luarc.json). TombIDE has no + // loading workspace-supplied plugins (runtime.plugin in .luarc.json). The host editor has no // equivalent workspace-trust gate, so leaving the prompt enabled keeps malicious or // accidental third-party Lua scripts from being executed silently inside the host process. trustByClient = false, @@ -378,7 +347,7 @@ public void MarkTransportUnhealthy() } }; - private void CaptureServerCapabilities(JsonElement initializeResponse) + private void CaptureServerCapabilities(LuaInitializeResponse initializeResponse) { _supportsCompletionResolve = false; _supportsReferences = false; @@ -389,131 +358,87 @@ private void CaptureServerCapabilities(JsonElement initializeResponse) _semanticTokenTypes = []; _semanticTokenModifiers = []; - if (!initializeResponse.TryGetProperty("capabilities", out JsonElement capabilities)) + if (initializeResponse.Capabilities is not { } capabilities) return; - if (TryReadTextDocumentSyncKind(capabilities, out LuaTextDocumentSyncKind textDocumentSyncKind)) + if (capabilities.TextDocumentSync is { } textDocumentSync) { - if (textDocumentSyncKind == LuaTextDocumentSyncKind.None) + if (textDocumentSync.Kind == LuaTextDocumentSyncKind.None) { throw new NotSupportedException( - "The Lua language server does not advertise full or incremental text synchronization required by TombIDE."); + "The Lua language server does not advertise full or incremental text synchronization required by the Lua IntelliSense provider."); } - _textDocumentSyncKind = textDocumentSyncKind; - } - - if (capabilities.TryGetProperty("completionProvider", out JsonElement completionProvider) - && completionProvider.TryGetProperty("resolveProvider", out JsonElement resolveProvider)) - { - _supportsCompletionResolve = resolveProvider.ValueKind == JsonValueKind.True; - } - - if (capabilities.TryGetProperty("referencesProvider", out JsonElement referencesProvider)) - { - _supportsReferences = referencesProvider.ValueKind == JsonValueKind.True - || referencesProvider.ValueKind == JsonValueKind.Object; - } - - if (capabilities.TryGetProperty("renameProvider", out JsonElement renameProvider)) - { - _supportsRename = renameProvider.ValueKind == JsonValueKind.True - || renameProvider.ValueKind == JsonValueKind.Object; + _textDocumentSyncKind = textDocumentSync.Kind; } - if (capabilities.TryGetProperty("documentFormattingProvider", out JsonElement formattingProvider)) - { - _supportsFormatting = formattingProvider.ValueKind == JsonValueKind.True - || formattingProvider.ValueKind == JsonValueKind.Object; - } + _supportsCompletionResolve = capabilities.CompletionProvider?.ResolveProvider == true; + _supportsReferences = capabilities.ReferencesProvider?.IsSupported == true; + _supportsRename = capabilities.RenameProvider?.IsSupported == true; + _supportsFormatting = capabilities.DocumentFormattingProvider?.IsSupported == true; - if (!capabilities.TryGetProperty("semanticTokensProvider", out JsonElement semanticTokensProvider)) + if (capabilities.SemanticTokensProvider is not { } semanticTokensProvider) return; - if (semanticTokensProvider.TryGetProperty("full", out JsonElement fullElement)) - { - _supportsSemanticTokensDelta = fullElement.ValueKind == JsonValueKind.Object - && fullElement.TryGetProperty("delta", out JsonElement deltaElement) - && deltaElement.ValueKind == JsonValueKind.True; - } + _supportsSemanticTokensDelta = semanticTokensProvider.Full?.SupportsDelta == true; - if (!semanticTokensProvider.TryGetProperty("legend", out JsonElement legend)) + if (semanticTokensProvider.Legend is not { } legend) return; - _semanticTokenTypes = ReadStringArray(legend, "tokenTypes"); - _semanticTokenModifiers = ReadStringArray(legend, "tokenModifiers"); + _semanticTokenTypes = legend.TokenTypes ?? []; + _semanticTokenModifiers = legend.TokenModifiers ?? []; } - private static bool TryReadTextDocumentSyncKind(JsonElement capabilities, out LuaTextDocumentSyncKind textDocumentSyncKind) + private LuaLanguageServerTransportSession CreateTransportSession(Process process) { - textDocumentSyncKind = LuaTextDocumentSyncKind.Incremental; - - if (!capabilities.TryGetProperty("textDocumentSync", out JsonElement textDocumentSyncElement)) - return false; + long generation = Interlocked.Increment(ref _transportGeneration); - if (textDocumentSyncElement.ValueKind == JsonValueKind.Number - && textDocumentSyncElement.TryGetInt32(out int rawSyncKind)) - { - textDocumentSyncKind = ParseTextDocumentSyncKind(rawSyncKind); - return true; - } + var session = new LuaLanguageServerTransportSession(generation, + process, + process.StandardOutput.BaseStream, + process.StandardInput.BaseStream); - if (textDocumentSyncElement.ValueKind != JsonValueKind.Object) - return false; + session.MessageHandler = CreateMessageHandler(session.OutputStream, session.InputStream); + session.RpcTarget = new LuaLanguageServerClientRpcTarget(this, generation); + session.JsonRpc = CreateJsonRpc(session); + session.RpcCompletionTask = session.JsonRpc.Completion; - if (!textDocumentSyncElement.TryGetProperty("change", out JsonElement changeElement) - || !changeElement.TryGetInt32(out rawSyncKind)) - { - textDocumentSyncKind = LuaTextDocumentSyncKind.None; - return true; - } + session.ProcessExitedHandler = (_, _) => Process_Exited(session); + process.Exited += session.ProcessExitedHandler; + session.StderrLoopTask = Task.Run(() => ReadStandardErrorLoopAsync(session), CancellationToken.None); + session.JsonRpc.StartListening(); - textDocumentSyncKind = ParseTextDocumentSyncKind(rawSyncKind); - return true; + return session; } - private static LuaTextDocumentSyncKind ParseTextDocumentSyncKind(int rawSyncKind) => rawSyncKind switch - { - 0 => LuaTextDocumentSyncKind.None, - 1 => LuaTextDocumentSyncKind.Full, - 2 => LuaTextDocumentSyncKind.Incremental, - _ => LuaTextDocumentSyncKind.None - }; - - private static string[] ReadStringArray(JsonElement parent, string propertyName) + private static HeaderDelimitedMessageHandler CreateMessageHandler(Stream outputStream, Stream inputStream) { - if (!parent.TryGetProperty(propertyName, out JsonElement property) || property.ValueKind != JsonValueKind.Array) - return []; - - var values = new List(); - - foreach (JsonElement item in property.EnumerateArray()) + var formatter = new SystemTextJsonFormatter { - if (item.ValueKind == JsonValueKind.String) + JsonSerializerOptions = new JsonSerializerOptions { - string? value = item.GetString(); - - if (!string.IsNullOrEmpty(value)) - values.Add(value); + PropertyNameCaseInsensitive = true } - } + }; - return [.. values]; + return new HeaderDelimitedMessageHandler(outputStream, inputStream, formatter); } - private LuaLanguageServerTransportSession CreateTransportSession(Process process) + private JsonRpc CreateJsonRpc(LuaLanguageServerTransportSession session) { - long generation = Interlocked.Increment(ref _transportGeneration); - var session = new LuaLanguageServerTransportSession(generation, - process, - process.StandardOutput.BaseStream, - process.StandardInput.BaseStream); + HeaderDelimitedMessageHandler messageHandler = session.MessageHandler + ?? throw new InvalidOperationException("The Lua language server transport session is missing a JSON-RPC message handler."); - session.ProcessExitedHandler = (_, _) => Process_Exited(session); - process.Exited += session.ProcessExitedHandler; - session.ReadLoopTask = Task.Run(() => ReadLoopAsync(session), CancellationToken.None); - session.StderrLoopTask = Task.Run(() => ReadStandardErrorLoopAsync(session), CancellationToken.None); - return session; + LuaLanguageServerClientRpcTarget rpcTarget = session.RpcTarget + ?? throw new InvalidOperationException("The Lua language server transport session is missing a JSON-RPC callback target."); + + var jsonRpc = new JsonRpc(messageHandler, rpcTarget) + { + CancelLocallyInvokedMethodsWhenConnectionIsClosed = true + }; + + jsonRpc.Disconnected += (_, eventArgs) => JsonRpc_Disconnected(session, eventArgs); + return jsonRpc; } private void SetActiveSession(LuaLanguageServerTransportSession session) @@ -537,6 +462,8 @@ private LuaLanguageServerTransportSession GetRequiredActiveSession(bool allowDis private LuaLanguageServerTransportSession? DetachActiveSession() { LuaLanguageServerTransportSession? session = Interlocked.Exchange(ref _activeSession, null); + Volatile.Write(ref _activeTransportGeneration, 0); + IsReady = false; return session; } @@ -560,61 +487,98 @@ private void Process_Exited(LuaLanguageServerTransportSession session) if (!_isDisposed && isCurrentSession) Log.Warn("Lua language server process exited unexpectedly{ExitCodeSuffix}.", exitCode is not null ? $" with code {exitCode.Value}" : string.Empty); - - FailPendingRequests(session, new IOException("The Lua language server process exited unexpectedly.")); } private bool IsCurrentSession(LuaLanguageServerTransportSession session) => ReferenceEquals(Volatile.Read(ref _activeSession), session); - private static int? TryReadProcessExitCode(Process? process) + private void JsonRpc_Disconnected(LuaLanguageServerTransportSession session, JsonRpcDisconnectedEventArgs eventArgs) { - if (process is null) - return null; + if (!IsCurrentSession(session)) + return; + + IsReady = false; + + if (_isDisposed) + return; + + Exception? exception = eventArgs.Exception; + + if (exception is not null) + { + Log.Warn(exception, "Lua language server JSON-RPC transport disconnected: {Description}", eventArgs.Description); + return; + } + + Log.Warn("Lua language server JSON-RPC transport disconnected: {Description}", eventArgs.Description); + } + private async Task ReadStandardErrorLoopAsync(LuaLanguageServerTransportSession session) + { try { - return process.HasExited ? process.ExitCode : null; + while (!_isDisposed) + { + Process? process = session.Process; + + if (process is null || process.HasExited) + break; + + string? line = await process.StandardError.ReadLineAsync(_lifetimeCts.Token).ConfigureAwait(false); + + if (line is null) + break; + + if (!string.IsNullOrWhiteSpace(line)) + Log.Debug("[LuaLS stderr] {Line}", line); + } } - catch (InvalidOperationException) + catch (OperationCanceledException) + { } + catch { - // Includes ObjectDisposedException; the process state is no longer accessible. - return null; + // Ignore stderr read failures. } } - private static bool TryAcceptPayloadSize(int parsedContentLength, out int contentLength) + private static void LogServerMessage(string method, LuaWindowMessageParams parameters) { - contentLength = 0; + string? messageText = parameters.Message; - if (parsedContentLength <= 0) - return false; + if (string.IsNullOrWhiteSpace(messageText)) + return; + + int messageType = parameters.Type ?? 4; - if (parsedContentLength > MaxPayloadByteCount) + switch (messageType) { - Log.Warn("Refusing Lua language server payload of {Bytes} bytes (cap is {Cap}).", parsedContentLength, MaxPayloadByteCount); - return false; + case 1: Log.Error("[LuaLS {Method}] {Message}", method, messageText); break; + case 2: Log.Warn("[LuaLS {Method}] {Message}", method, messageText); break; + case 3: Log.Info("[LuaLS {Method}] {Message}", method, messageText); break; + default: Log.Debug("[LuaLS {Method}] {Message}", method, messageText); break; } - - contentLength = parsedContentLength; - return true; } - private void FailPendingRequests(LuaLanguageServerTransportSession session, Exception exception) + private static int? TryReadProcessExitCode(Process? process) { - foreach (KeyValuePair> pendingRequest in session.PendingRequests) - pendingRequest.Value.TrySetException(exception); + if (process is null) + return null; + + try + { + return process.HasExited ? process.ExitCode : null; + } + catch (InvalidOperationException) + { + // Includes ObjectDisposedException; the process state is no longer accessible. + return null; + } } private async Task DisposeSessionAsync(LuaLanguageServerTransportSession session) { - Task? readLoopTask = session.ReadLoopTask; + Task? rpcCompletionTask = session.RpcCompletionTask; Task? stderrLoopTask = session.StderrLoopTask; - Exception pendingRequestFailure = _isDisposed - ? new ObjectDisposedException(nameof(LuaLanguageServerClient)) - : new IOException("The Lua language server transport was closed."); - - FailPendingRequests(session, pendingRequestFailure); try { @@ -643,13 +607,32 @@ private async Task DisposeSessionAsync(LuaLanguageServerTransportSession session } finally { + try + { + session.JsonRpc?.Dispose(); + } + catch + { + // Ignore JSON-RPC disposal failures. + } + + try + { + if (session.MessageHandler is not null) + await session.MessageHandler.DisposeAsync().ConfigureAwait(false); + } + catch + { + // Ignore message-handler disposal failures. + } + CleanupSessionResources(session); } - await WaitForBackgroundLoopsAsync(readLoopTask, stderrLoopTask).ConfigureAwait(false); + await WaitForBackgroundLoopsAsync(rpcCompletionTask, stderrLoopTask).ConfigureAwait(false); } - private void CleanupSessionResources(LuaLanguageServerTransportSession session) + private static void CleanupSessionResources(LuaLanguageServerTransportSession session) { try { @@ -662,19 +645,19 @@ private void CleanupSessionResources(LuaLanguageServerTransportSession session) // Ignore stream disposal failures. } - ReturnReceiveBuffer(session); - session.ReceiveBufferCount = 0; - session.ReadLoopTask = null; + session.RpcCompletionTask = null; session.StderrLoopTask = null; + session.JsonRpc = null; + session.MessageHandler = null; + session.RpcTarget = null; } private async Task TrySendShutdownAsync(LuaLanguageServerTransportSession session) { - using var shutdownTimeout = new CancellationTokenSource(TimeSpan.FromSeconds(1)); - try { - await SendRequestCoreAsync(session, "shutdown", new { }, shutdownTimeout.Token, allowDisposed: true).ConfigureAwait(false); + Task shutdownTask = SendRequestCoreAsync(session, "shutdown", new LuaEmptyParams(), CancellationToken.None, allowDisposed: true); + await shutdownTask.WaitAsync(TimeSpan.FromSeconds(1)).ConfigureAwait(false); } catch { @@ -767,7 +750,6 @@ public void Dispose() _lifetimeCts.Dispose(); _startLock.Dispose(); - _writeLock.Dispose(); } private sealed class LuaLanguageServerTransportSession @@ -788,15 +770,15 @@ public LuaLanguageServerTransportSession(long generation, Process? process, Stre public Stream OutputStream { get; } - public EventHandler? ProcessExitedHandler { get; set; } + public HeaderDelimitedMessageHandler? MessageHandler { get; set; } - public ConcurrentDictionary> PendingRequests { get; } = new(); + public JsonRpc? JsonRpc { get; set; } - public byte[] ReceiveBuffer { get; set; } = []; + public LuaLanguageServerClientRpcTarget? RpcTarget { get; set; } - public int ReceiveBufferCount { get; set; } + public EventHandler? ProcessExitedHandler { get; set; } - public Task? ReadLoopTask { get; set; } + public Task? RpcCompletionTask { get; set; } public Task? StderrLoopTask { get; set; } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs similarity index 78% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs index 5437ab7f01..a1d68cd9bd 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Pathing/LuaLanguageServerPathHelper.cs @@ -1,15 +1,9 @@ -#nullable enable - -using System; -using System.IO; -using System.Text.Json; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// -/// Normalizes local paths and file URIs so LuaLS and TombIDE use a consistent document identity. +/// Normalizes local paths and file URIs so LuaLS and the host editor use a consistent document identity. /// -internal static class LuaLanguageServerPathHelper +public static class LuaLanguageServerPathHelper { /// /// Converts a local file path into a normalized file URI for LuaLS requests. @@ -80,27 +74,18 @@ public static bool TryNormalizeLocalPath(string filePath, out string normalizedF } /// - /// Attempts to extract and normalize a local file path from an LSP payload. + /// Attempts to extract and normalize a local file path from a file URI. /// - /// The JSON payload containing the document URI. + /// The file URI text. /// The normalized local file path when successful. /// when a local file path was resolved; otherwise, . - public static bool TryGetFilePath(JsonElement parameters, out string filePath) + public static bool TryGetFilePath(string? uriText, out string filePath) { filePath = string.Empty; - if (parameters.ValueKind != JsonValueKind.Object - || !parameters.TryGetProperty("uri", out JsonElement uriElement)) - { - return false; - } - - string? uriText = uriElement.GetString(); - if (string.IsNullOrWhiteSpace(uriText) || !Uri.TryCreate(uriText, UriKind.Absolute, out Uri? uri) - || uri is null - || !uri.IsFile) + || uri?.IsFile != true) { return false; } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs similarity index 86% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs index b9cc7e6c59..d86f1e7fca 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Pathing/LuaLanguageServerSettingsFactory.cs @@ -1,10 +1,6 @@ -#nullable enable +namespace TombLib.Scripting.Lua.LanguageServer; -using System.IO; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal static class LuaLanguageServerSettingsFactory +public static class LuaLanguageServerSettingsFactory { /// /// Builds the Lua language server settings payload for the active script workspace. diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs similarity index 54% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs index df8318937d..680c621933 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Startup/LuaLanguageServerStartupFailure.cs @@ -1,10 +1,8 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Describes a Lua language server startup failure that should be surfaced to the UI. /// /// The user-facing failure message. -/// Whether IntelliSense is disabled until TombIDE restarts. -internal readonly record struct LuaLanguageServerStartupFailure(string Message, bool IsPersistent); +/// Whether IntelliSense is disabled until the host application restarts. +public readonly record struct LuaLanguageServerStartupFailure(string Message, bool IsPersistent); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaProcessJobObject.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Startup/LuaProcessJobObject.cs similarity index 92% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaProcessJobObject.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Startup/LuaProcessJobObject.cs index 1e9095c392..8c9ac75ab6 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Startup/LuaProcessJobObject.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Startup/LuaProcessJobObject.cs @@ -1,18 +1,15 @@ -#nullable enable - using NLog; -using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.Versioning; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Wraps a Windows job object configured with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE so that any -/// child processes assigned to it are forcibly terminated when the host (TombIDE) crashes or the +/// child processes assigned to it are forcibly terminated when the host application crashes or the /// last handle to the job is released. This prevents stranded lua-language-server.exe -/// processes if the editor never gets a chance to run its disposal path. +/// processes if the host never gets a chance to run its disposal path. /// [SupportedOSPlatform("windows")] internal static class LuaProcessJobObject @@ -45,8 +42,8 @@ public static void TryAssignProcess(Process process) { int errorCode = Marshal.GetLastWin32Error(); - // 5 = ERROR_ACCESS_DENIED. Pre-Windows 8 hosts (which TombIDE no longer ships for) - // or processes already inside an unbreakable job will return this; we just log and move on. + // 5 = ERROR_ACCESS_DENIED. Pre-Windows 8 systems or processes already inside an + // unbreakable job will return this; we just log and move on. Log.Debug("AssignProcessToJobObject failed with Win32 error {ErrorCode} for the Lua language server process.", errorCode); } } @@ -94,7 +91,9 @@ private static IntPtr EnsureJobHandle() if (!SetInformationJobObject(handle, JobObjectInformationClass.ExtendedLimitInformation, payloadPointer, (uint)payloadSize)) { int errorCode = Marshal.GetLastWin32Error(); + CloseHandle(handle); + _initializationFailed = true; Log.Debug("SetInformationJobObject failed with Win32 error {ErrorCode}; the Lua language server will rely on graceful shutdown.", errorCode); return IntPtr.Zero; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs similarity index 92% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs index 1eaedeed3c..6cf264d6a7 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Workspace/LuaWorkspaceFileWatcher.cs @@ -1,21 +1,14 @@ -#nullable enable - using NLog; -using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// -/// Watches the Lua workspace root for relevant external file changes (`*.lua`, `.luarc.json`, -/// `.luarc.jsonc`) and forwards them to LuaLS through `workspace/didChangeWatchedFiles`. LuaLS does -/// not poll the file system itself for clients that opt into this capability, so without this hook -/// changes made by Git pull, file copy, or any other out-of-band tool would not reach the language -/// server until the user touched the affected document inside TombIDE. +/// Watches the Lua workspace root for relevant external file changes (*.lua, .luarc.json, +/// .luarc.jsonc) and forwards them to LuaLS through workspace/didChangeWatchedFiles. +/// LuaLS does not poll the file system itself for clients that opt into this capability, +/// so without this hook changes made by Git pull, file copy, or any other out-of-band tool would not reach +/// the language server until the user touched the affected document inside the host editor. /// internal sealed class LuaWorkspaceFileWatcher : IDisposable { @@ -43,7 +36,9 @@ internal sealed class LuaWorkspaceFileWatcher : IDisposable /// /// The workspace root directory to watch. /// The callback that forwards coalesced changes to LuaLS. - public LuaWorkspaceFileWatcher(string workspaceRootDirectoryPath, Func dispatchAsync, + public LuaWorkspaceFileWatcher( + string workspaceRootDirectoryPath, + Func dispatchAsync, Action? watcherFailed = null) { _workspaceRootDirectoryPath = workspaceRootDirectoryPath; @@ -100,8 +95,10 @@ private FileSystemWatcher CreateWatcher(string filter, bool includeSubdirectorie QueueChange(e.OldFullPath, FileChangeKind.Deleted); QueueChange(e.FullPath, FileChangeKind.Created); }; + watcher.Error += (_, e) => HandleWatcherError(e.GetException()); watcher.EnableRaisingEvents = true; + return watcher; } @@ -212,7 +209,7 @@ private void HandleWatcherError(Exception? exception) return; Log.Warn(exception, - "Lua workspace file watcher was disabled for '{Workspace}'. External workspace changes will no longer be forwarded to LuaLS until TombIDE is restarted.", + "Lua workspace file watcher was disabled for '{Workspace}'. External workspace changes will no longer be forwarded to LuaLS until the host application is restarted.", _workspaceRootDirectoryPath); try diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs similarity index 53% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs index f5e02946f4..7b9e20d1b6 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Infrastructure/Workspace/LuaWorkspaceWatcherFailure.cs @@ -1,9 +1,7 @@ -#nullable enable - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Describes a workspace-watcher failure that should be surfaced to the UI. /// /// The user-facing failure message. -internal readonly record struct LuaWorkspaceWatcherFailure(string Message); \ No newline at end of file +public readonly record struct LuaWorkspaceWatcherFailure(string Message); diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/LuaLanguageServerResponseParser.Shared.cs similarity index 70% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/LuaLanguageServerResponseParser.Shared.cs index 22de7f1aca..5934794a85 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/LuaLanguageServerResponseParser.Shared.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/LuaLanguageServerResponseParser.Shared.cs @@ -1,16 +1,13 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Linq; +using System.Diagnostics.CodeAnalysis; using System.Text.Json; +using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// -/// Converts raw LuaLS JSON payloads into the editor-facing result objects shared by completion, hover, navigation, signature-help, diagnostics, and semantic-token parsing. +/// Provides shared markup and payload-conversion helpers used by the LuaLS response parsers. /// -internal static partial class LuaLanguageServerResponseParser +public static partial class LuaLanguageServerResponseParser { private readonly struct MarkupContent(string? text, bool isMarkdown) { @@ -89,4 +86,31 @@ private static MarkupContent CombineArrayMarkupContent(JsonElement arrayElement) .Replace('\r', '\n') .Trim(); } + + private static bool TryParseDocumentRange(LuaProtocolRangePayload? rangePayload, [NotNullWhen(true)] out LuaDocumentRange? range) + { + range = null; + + if (!TryGetOneBasedLineAndColumn(rangePayload?.Start, out int startLineNumber, out int startColumnNumber) + || !TryGetOneBasedLineAndColumn(rangePayload?.End, out int endLineNumber, out int endColumnNumber)) + { + return false; + } + + range = new LuaDocumentRange(startLineNumber, startColumnNumber, endLineNumber, endColumnNumber); + return true; + } + + private static bool TryGetOneBasedLineAndColumn(LuaProtocolNullablePosition? position, out int lineNumber, out int columnNumber) + { + lineNumber = 1; + columnNumber = 1; + + if (position is not { Line: int parsedLine, Character: int parsedCharacter }) + return false; + + lineNumber = parsedLine + 1; + columnNumber = parsedCharacter + 1; + return true; + } } diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/LuaTextEditPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/LuaTextEditPayloads.cs new file mode 100644 index 0000000000..169b60816f --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/LuaTextEditPayloads.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents a single text edit returned by LuaLS. +/// +public readonly record struct LuaTextEditPayload( + [property: JsonPropertyName("range")] LuaProtocolRangePayload? Range, + [property: JsonPropertyName("newText")] string? NewText); + +/// +/// Represents the typed top-level workspace edit response used by rename. +/// +public readonly record struct LuaWorkspaceEditResponse( + [property: JsonPropertyName("changes")] Dictionary? Changes, + [property: JsonPropertyName("documentChanges")] LuaWorkspaceDocumentChangePayload[]? DocumentChanges); + +public readonly record struct LuaWorkspaceDocumentChangePayload( + [property: JsonPropertyName("textDocument")] LuaTextDocumentUriPayload? TextDocument, + [property: JsonPropertyName("edits")] LuaTextEditPayload[]? Edits); + +public readonly record struct LuaTextDocumentUriPayload( + [property: JsonPropertyName("uri")] string? Uri); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaDefinitionPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaDefinitionPayloads.cs new file mode 100644 index 0000000000..1a040722f6 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaDefinitionPayloads.cs @@ -0,0 +1,82 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the first usable definition target returned by LuaLS. +/// +[JsonConverter(typeof(LuaDefinitionResponseJsonConverter))] +public readonly record struct LuaDefinitionResponse(string? Uri, int LineNumber, int ColumnNumber); + +/// +/// Deserializes definition responses from LSP location and location-link payloads. +/// +public sealed class LuaDefinitionResponseJsonConverter : JsonConverter +{ + private static readonly string[] RangeProperties = + [ + "targetSelectionRange", + "targetRange", + "range" + ]; + + public override LuaDefinitionResponse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + return default; + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + JsonElement root = document.RootElement; + JsonElement definitionElement = root; + + if (root.ValueKind == JsonValueKind.Array) + { + definitionElement = root.EnumerateArray().FirstOrDefault(); + + if (definitionElement.ValueKind == JsonValueKind.Undefined) + return default; + } + + if (definitionElement.ValueKind != JsonValueKind.Object) + return default; + + string? uri = definitionElement.TryGetProperty("targetUri", out JsonElement targetUriElement) + ? targetUriElement.GetString() + : definitionElement.TryGetProperty("uri", out JsonElement uriElement) + ? uriElement.GetString() + : null; + + if (string.IsNullOrWhiteSpace(uri) || !TryGetStartElement(definitionElement, out JsonElement startElement)) + return default; + + int lineNumber = startElement.TryGetProperty("line", out JsonElement lineElement) + && lineElement.TryGetInt32(out int parsedLine) ? parsedLine + 1 : 1; + + int columnNumber = startElement.TryGetProperty("character", out JsonElement characterElement) + && characterElement.TryGetInt32(out int parsedCharacter) ? parsedCharacter + 1 : 1; + + return new LuaDefinitionResponse(uri, lineNumber, columnNumber); + } + + public override void Write(Utf8JsonWriter writer, LuaDefinitionResponse value, JsonSerializerOptions options) + => throw new NotSupportedException(); + + private static bool TryGetStartElement(JsonElement definitionElement, out JsonElement startElement) + { + for (int i = 0; i < RangeProperties.Length; i++) + { + string rangeProperty = RangeProperties[i]; + + if (definitionElement.TryGetProperty(rangeProperty, out JsonElement rangeElement) + && rangeElement.TryGetProperty("start", out startElement) + && startElement.ValueKind == JsonValueKind.Object) + { + return true; + } + } + + startElement = default; + return false; + } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaLanguageServerResponseParser.Navigation.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaLanguageServerResponseParser.Navigation.cs new file mode 100644 index 0000000000..0d1bc492bf --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Navigation/LuaLanguageServerResponseParser.Navigation.cs @@ -0,0 +1,24 @@ +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses a definition location from a LuaLS definition response. + /// + public static LuaDefinitionLocation? ParseDefinitionLocation(LuaDefinitionResponse response) + { + if (string.IsNullOrWhiteSpace(response.Uri) + || !Uri.TryCreate(response.Uri, UriKind.Absolute, out Uri? parsedUri) + || parsedUri?.IsFile != true) + { + return null; + } + + return new LuaDefinitionLocation( + LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), + response.LineNumber, + response.ColumnNumber); + } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/AssemblyInfo.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..37fefc243d --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.Versioning; + +[assembly: SupportedOSPlatform("windows")] diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/InternalsVisibleTo.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/InternalsVisibleTo.cs new file mode 100644 index 0000000000..d34753098b --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Properties/InternalsVisibleTo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("TombLib.Test")] diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs similarity index 72% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs index 8c83a1f5b7..f629b6d0c9 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.Documents.cs @@ -1,15 +1,6 @@ -#nullable enable +namespace TombLib.Scripting.Lua.LanguageServer; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; - -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; - -internal sealed partial class LuaLanguageServerIntellisenseProvider +public sealed partial class LuaLanguageServerIntellisenseProvider { private Task EnqueueDocumentOperationAsync( Func> operation, @@ -26,7 +17,8 @@ private Task EnqueueDocumentOperationAsync( return completionSource.Task; } - private static async Task RunQueuedDocumentOperationAsync(Task previousOperation, + private static async Task RunQueuedDocumentOperationAsync( + Task previousOperation, Func> operation, TaskCompletionSource completionSource, CancellationToken cancellationToken) @@ -57,15 +49,6 @@ private static async Task WaitForQueuedDocumentOperationAsync(Task previousOpera { } } - private Task TrySynchronizeDocumentAsync(string filePath, string content, - bool acquireOpenReference, bool refreshSemanticTokens, CancellationToken cancellationToken) - { - if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) - return Task.FromResult(false); - - return SynchronizeDocumentAsync(normalizedFilePath, content, acquireOpenReference, refreshSemanticTokens, cancellationToken); - } - private async Task SynchronizeDocumentAsync(string filePath, string content, bool acquireOpenReference, bool refreshSemanticTokens, CancellationToken cancellationToken) { @@ -112,18 +95,17 @@ private void InvalidateDocumentSynchronization(string filePath) } public void RenameDocument(string oldFilePath, string newFilePath, string content) - => ObserveBackgroundTask(TryRenameDocumentAsync(oldFilePath, newFilePath, content, CancellationToken.None), "Document rename"); - - private Task TryRenameDocumentAsync(string oldFilePath, string newFilePath, string content, CancellationToken cancellationToken) { if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(oldFilePath, out string normalizedOldFilePath) || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(newFilePath, out string normalizedNewFilePath) || string.Equals(normalizedOldFilePath, normalizedNewFilePath, StringComparison.OrdinalIgnoreCase)) { - return Task.FromResult(false); + return; } - return RenameDocumentAsync(normalizedOldFilePath, normalizedNewFilePath, content, cancellationToken); + ObserveBackgroundTask( + RenameDocumentAsync(normalizedOldFilePath, normalizedNewFilePath, content, CancellationToken.None), + "Document rename"); } private async Task RenameDocumentAsync(string oldFilePath, string newFilePath, string content, CancellationToken cancellationToken) @@ -140,7 +122,10 @@ private async Task RenameDocumentAsync(string oldFilePath, string newFileP if (request is not { } renameRequest) return false; - PublishTrackedDocumentState(renameRequest.RenamedDocument.FilePath); + string filePath = renameRequest.RenamedDocument.FilePath; + RaiseDiagnosticsUpdated(filePath, _documents.GetDiagnostics(filePath)); + RaiseSemanticTokensUpdated(filePath, _documents.GetSemanticTokens(filePath)); + return true; } catch (OperationCanceledException) @@ -208,7 +193,7 @@ private async Task SynchronizeDocumentCoreAsyn if (renameRequest.PreviousDocument is not null) { await _client.SendNotificationAsync("textDocument/didClose", - new { textDocument = new { uri = renameRequest.PreviousDocument.Uri } }, + new LuaDidCloseTextDocumentParams(new LuaTextDocumentIdentifier(renameRequest.PreviousDocument.Uri)), cancellationToken).ConfigureAwait(false); } @@ -255,46 +240,34 @@ private async Task SendDocumentSynchronizationNotificationAsync(LuaDocumentSynch if (request.Kind == LuaDocumentSynchronizationKind.Open) { await _client.SendNotificationAsync("textDocument/didOpen", - new - { - textDocument = new - { - uri = request.Document.Uri, - languageId = "lua", - version = request.Document.Version, - text = request.Document.Content - } - }, cancellationToken).ConfigureAwait(false); + new LuaDidOpenTextDocumentParams( + new LuaDidOpenTextDocumentPayload( + request.Document.Uri, + "lua", + request.Document.Version, + request.Document.Content)), + cancellationToken).ConfigureAwait(false); } else if (request.Kind == LuaDocumentSynchronizationKind.Change) { - object contentChange = _client.TextDocumentSyncKind switch + LuaTextDocumentContentChangePayload contentChange = _client.TextDocumentSyncKind switch { - LuaTextDocumentSyncKind.Incremental when request.ChangeRange is { } changeRange => new - { - range = new - { - start = new { line = changeRange.StartLine, character = changeRange.StartCharacter }, - end = new { line = changeRange.EndLine, character = changeRange.EndCharacter } - }, - text = changeRange.Text - }, - LuaTextDocumentSyncKind.Full => new { text = request.Document.Content }, - LuaTextDocumentSyncKind.Incremental => new { text = request.Document.Content }, + LuaTextDocumentSyncKind.Incremental when request.ChangeRange is { } changeRange => new( + changeRange.Text, + new LuaProtocolRangePayload( + new LuaProtocolNullablePosition(changeRange.StartLine, changeRange.StartCharacter), + new LuaProtocolNullablePosition(changeRange.EndLine, changeRange.EndCharacter))), + LuaTextDocumentSyncKind.Full => new(request.Document.Content), + LuaTextDocumentSyncKind.Incremental => new(request.Document.Content), _ => throw new InvalidOperationException( - "The Lua language server does not support document changes required by TombIDE.") + "The Lua language server does not support document changes required by the Lua IntelliSense provider.") }; await _client.SendNotificationAsync("textDocument/didChange", - new - { - textDocument = new - { - uri = request.Document.Uri, - version = request.Document.Version - }, - contentChanges = new[] { contentChange } - }, cancellationToken).ConfigureAwait(false); + new LuaDidChangeTextDocumentParams( + new LuaVersionedTextDocumentIdentifierPayload(request.Document.Uri, request.Document.Version), + [contentChange]), + cancellationToken).ConfigureAwait(false); } } @@ -317,11 +290,11 @@ await EnqueueDocumentOperationAsync( // Only forward the close notification if the server is already running. // Starting the server just to send didClose would be wasteful and can race with disposal. - if (!_startupSucceeded || !_client.IsReady) + if (document is null || !_startupSucceeded || !_client.IsReady) return false; await _client.SendNotificationAsync("textDocument/didClose", - new { textDocument = new { uri = document.Uri } }, token).ConfigureAwait(false); + new LuaDidCloseTextDocumentParams(new LuaTextDocumentIdentifier(document.Uri)), token).ConfigureAwait(false); return true; }, @@ -333,9 +306,9 @@ await _client.SendNotificationAsync("textDocument/didClose", } } - private void HandleDiagnosticsPublished(JsonElement parameters) + private void HandleDiagnosticsPublished(LuaPublishDiagnosticsParams parameters) { - if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters, out string filePath)) + if (!LuaLanguageServerPathHelper.TryGetFilePath(parameters.Uri, out string filePath)) { Log.Debug("Lua diagnostics could not be matched to a local file path."); return; @@ -361,32 +334,28 @@ private void HandleDiagnosticsPublished(JsonElement parameters) RaiseDiagnosticsUpdated(publishedDiagnostics.FilePath, publishedDiagnostics.Diagnostics); } - private void PublishTrackedDocumentState(string filePath) - { - RaiseDiagnosticsUpdated(filePath, _documents.GetDiagnostics(filePath)); - RaiseSemanticTokensUpdated(filePath, _documents.GetSemanticTokens(filePath)); - } - private static void ObserveBackgroundTask(Task task, string operation) - => _ = ObserveBackgroundTaskAsync(task, operation); - - private static async Task ObserveBackgroundTaskAsync(Task task, string operation) { - try - { - await task.ConfigureAwait(false); - } - catch (OperationCanceledException) - { } - catch (IOException exception) - { - Log.Debug(exception, "Lua language server background operation '{Operation}' failed with a transport error.", operation); - } - catch (ObjectDisposedException) - { } - catch (Exception exception) + _ = ObserveAsync(task, operation); + + static async Task ObserveAsync(Task observedTask, string observedOperation) { - Log.Warn(exception, "Lua language server background operation '{Operation}' failed.", operation); + try + { + await observedTask.ConfigureAwait(false); + } + catch (OperationCanceledException) + { } + catch (IOException exception) + { + Log.Debug(exception, "Lua language server background operation '{Operation}' failed with a transport error.", observedOperation); + } + catch (ObjectDisposedException) + { } + catch (Exception exception) + { + Log.Warn(exception, "Lua language server background operation '{Operation}' failed.", observedOperation); + } } } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs similarity index 63% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs index c0b37ca5f5..302bcb9917 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.Requests.cs @@ -1,15 +1,8 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; -internal sealed partial class LuaLanguageServerIntellisenseProvider +public sealed partial class LuaLanguageServerIntellisenseProvider { /// /// Requests completion items for the specified document position. @@ -24,22 +17,25 @@ internal sealed partial class LuaLanguageServerIntellisenseProvider public async Task> GetCompletionItemsAsync(string filePath, string content, int line, int column, char? triggerCharacter = null, CancellationToken cancellationToken = default) { - return await SendPositionRequestAsync( + return await SendPositionRequestAsync>( filePath, content, line, column, "textDocument/completion", - (textDocument, position) => new - { - textDocument, - position, - context = BuildCompletionContext(triggerCharacter) - }, + (textDocument, position) => new LuaCompletionParams(textDocument, position, BuildCompletionContext(triggerCharacter)), response => { - IReadOnlyList itemElements = LuaLanguageServerResponseParser.ExtractCompletionItems(response); + IReadOnlyList itemPayloads = response?.Items ?? []; - return itemElements.Count > 0 - ? LuaLanguageServerResponseParser.ParseCompletionItems(itemElements, BuildCompletionItemResolveCallback) - : []; + if (itemPayloads.Count == 0) + return []; + + Func>?>? resolveFactory = + _client is not null && _client.SupportsCompletionResolve + ? (unresolvedItem, itemPayload, itemIndex) => + cancellationToken => ResolveCompletionItemAsync(unresolvedItem, itemPayload, itemIndex, cancellationToken) + : null; + + return LuaLanguageServerResponseParser.ParseCompletionItems(itemPayloads, resolveFactory); }, + timeoutValue: null, defaultValue: [], cancellationToken).ConfigureAwait(false); } @@ -56,10 +52,11 @@ public async Task> GetCompletionItemsAsync(stri public Task GetHoverAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { - return SendPositionRequestAsync( + return SendPositionRequestAsync( filePath, content, line, column, "textDocument/hover", - static (textDocument, position) => new { textDocument, position }, + static (textDocument, position) => new LuaTextDocumentPositionParams(textDocument, position), LuaLanguageServerResponseParser.ParseHoverInfo, + timeoutValue: null, defaultValue: null, cancellationToken); } @@ -76,10 +73,11 @@ public async Task> GetCompletionItemsAsync(stri public Task GetDefinitionAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { - return SendPositionRequestAsync( + return SendPositionRequestAsync( filePath, content, line, column, "textDocument/definition", - static (textDocument, position) => new { textDocument, position }, + static (textDocument, position) => new LuaTextDocumentPositionParams(textDocument, position), LuaLanguageServerResponseParser.ParseDefinitionLocation, + timeoutValue: default, defaultValue: null, cancellationToken); } @@ -98,28 +96,27 @@ public async Task> GetReferencesAsync(string { ILuaLanguageServerClient? client = _client; - if (client is null - || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || !await SynchronizeDocumentAsync(normalizedFilePath, content, - acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false) - || !client.SupportsReferences) + if (client is null) + return []; + + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return []; + + if (!await SynchronizeDocumentAsync(normalizedFilePath, content, + acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false)) { return []; } - object textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }; - object position = new { line, character = column }; + if (!client.SupportsReferences) + return []; - JsonElement response = await SendBoundedRequestAsync(client, "textDocument/references", - new - { - textDocument, - position, - context = new - { - includeDeclaration = true - } - }, + var textDocument = new LuaTextDocumentIdentifier(LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath)); + var position = new LuaProtocolPosition(line, column); + + LuaReferenceResponse[]? response = await SendBoundedRequestAsync(client, "textDocument/references", + new LuaReferenceParams(textDocument, position, new LuaReferenceContextPayload(IncludeDeclaration: true)), + timeoutValue: null, cancellationToken).ConfigureAwait(false); return LuaLanguageServerResponseParser.ParseReferenceLocations(response); @@ -143,25 +140,27 @@ public async Task> GetReferencesAsync(string ILuaLanguageServerClient? client = _client; - if (client is null - || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || !await SynchronizeDocumentAsync(normalizedFilePath, content, - acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false) - || !client.SupportsRename) + if (client is null) + return null; + + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return null; + + if (!await SynchronizeDocumentAsync(normalizedFilePath, content, + acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false)) { return null; } - object textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }; - object position = new { line, character = column }; + if (!client.SupportsRename) + return null; - JsonElement response = await SendBoundedRequestAsync(client, "textDocument/rename", - new - { - textDocument, - position, - newName - }, + var textDocument = new LuaTextDocumentIdentifier(LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath)); + var position = new LuaProtocolPosition(line, column); + + LuaWorkspaceEditResponse? response = await SendBoundedRequestAsync(client, "textDocument/rename", + new LuaRenameParams(textDocument, position, newName), + timeoutValue: null, cancellationToken).ConfigureAwait(false); return LuaLanguageServerResponseParser.ParseWorkspaceEdit(response); @@ -178,32 +177,28 @@ public async Task> GetReferencesAsync(string public async Task> FormatDocumentAsync(string filePath, string content, LuaFormattingOptions options, CancellationToken cancellationToken = default) { - ArgumentNullException.ThrowIfNull(options); - ILuaLanguageServerClient? client = _client; - if (client is null - || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) - || !await SynchronizeDocumentAsync(normalizedFilePath, content, - acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false) - || !client.SupportsFormatting) + if (client is null) + return []; + + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return []; + + if (!await SynchronizeDocumentAsync(normalizedFilePath, content, + acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false)) { return []; } - JsonElement response = await SendBoundedRequestAsync(client, "textDocument/formatting", - new - { - textDocument = new - { - uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) - }, - options = new - { - tabSize = options.TabSize, - insertSpaces = options.InsertSpaces - } - }, + if (!client.SupportsFormatting) + return []; + + LuaTextEditPayload[]? response = await SendBoundedRequestAsync(client, "textDocument/formatting", + new LuaDocumentFormattingParams( + new LuaTextDocumentIdentifier(LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath)), + new LuaFormattingOptionsPayload(options.TabSize, options.InsertSpaces)), + timeoutValue: null, cancellationToken).ConfigureAwait(false); return LuaLanguageServerResponseParser.ParseDocumentFormattingEdits(response); @@ -221,41 +216,38 @@ public async Task> FormatDocumentAsync(string filePat public Task GetSignatureHelpAsync(string filePath, string content, int line, int column, CancellationToken cancellationToken = default) { - return SendPositionRequestAsync( + return SendPositionRequestAsync( filePath, content, line, column, "textDocument/signatureHelp", - static (textDocument, position) => new { textDocument, position }, + static (textDocument, position) => new LuaTextDocumentPositionParams(textDocument, position), LuaLanguageServerResponseParser.ParseSignatureHelp, + timeoutValue: null, defaultValue: null, cancellationToken); } - private static object BuildCompletionContext(char? triggerCharacter) + private static LuaCompletionContextPayload BuildCompletionContext(char? triggerCharacter) { return triggerCharacter is null - ? new { triggerKind = 1 } - : new { triggerKind = 2, triggerCharacter = triggerCharacter.ToString() }; - } - - private Func>? BuildCompletionItemResolveCallback(LuaCompletionItem unresolvedItem, JsonElement itemElement, int itemIndex) - { - if (_client is null || !_client.SupportsCompletionResolve) - return null; - - return cancellationToken => ResolveCompletionItemAsync(unresolvedItem, itemElement, itemIndex, cancellationToken); + ? new LuaCompletionContextPayload(TriggerKind: 1) + : new LuaCompletionContextPayload(TriggerKind: 2, triggerCharacter.ToString()); } - private async Task ResolveCompletionItemAsync(LuaCompletionItem unresolvedItem, JsonElement itemElement, int itemIndex, CancellationToken cancellationToken) + private async Task ResolveCompletionItemAsync(LuaCompletionItem unresolvedItem, LuaCompletionItemPayload itemPayload, int itemIndex, CancellationToken cancellationToken) { ILuaLanguageServerClient? client = _client; - if (client is null || !client.SupportsCompletionResolve) + if (client is null) + return unresolvedItem; + + if (!client.SupportsCompletionResolve) return unresolvedItem; try { - JsonElement resolvedItem = await SendBoundedRequestAsync(client, "completionItem/resolve", itemElement, cancellationToken).ConfigureAwait(false); + LuaCompletionItemPayload? resolvedItem = await SendBoundedRequestAsync(client, "completionItem/resolve", itemPayload, + timeoutValue: null, cancellationToken).ConfigureAwait(false); - if (resolvedItem.ValueKind == JsonValueKind.Object) + if (resolvedItem is not null) { LuaCompletionItem? parsedItem = LuaLanguageServerResponseParser.ParseCompletionItem(resolvedItem, itemIndex); @@ -275,54 +267,69 @@ private async Task ResolveCompletionItemAsync(LuaCompletionIt return unresolvedItem; } - private async Task SendPositionRequestAsync( + private async Task SendPositionRequestAsync( string filePath, string content, int line, int column, string method, - Func buildParameters, - Func parseResponse, + Func buildParameters, + Func parseResponse, + TResponse timeoutValue, TResult defaultValue, CancellationToken cancellationToken) { ILuaLanguageServerClient? client = _client; - if (client is null - || !LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath) + if (client is null) + return defaultValue; + + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return defaultValue; + + if ( // Request-driven sync paths (completion / hover / definition / signature) intentionally // skip the semantic-token refresh: typing a single identifier character can otherwise turn // into didChange + completion + semanticTokens/full per keystroke, which is the dominant // performance regression observed during normal editing. UpdateDocument (TextChangedDelayed) // remains the single owner of post-edit semantic-token refresh. - || !await SynchronizeDocumentAsync(normalizedFilePath, content, + !await SynchronizeDocumentAsync(normalizedFilePath, content, acquireOpenReference: false, refreshSemanticTokens: false, cancellationToken).ConfigureAwait(false)) { return defaultValue; } - object textDocument = new { uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath) }; - object position = new { line, character = column }; + var textDocument = new LuaTextDocumentIdentifier(LuaLanguageServerPathHelper.CreateFileUri(normalizedFilePath)); + var position = new LuaProtocolPosition(line, column); - JsonElement response = await SendBoundedRequestAsync(client, method, - buildParameters(textDocument, position), cancellationToken).ConfigureAwait(false); + TResponse response = await SendBoundedRequestAsync(client, method, + buildParameters(textDocument, position), timeoutValue, cancellationToken).ConfigureAwait(false); + + if (response is null) + return defaultValue; return parseResponse(response); } - private async Task SendBoundedRequestAsync(ILuaLanguageServerClient client, string method, object parameters, CancellationToken cancellationToken) + private async Task SendBoundedRequestAsync( + ILuaLanguageServerClient client, + string method, + object parameters, + TResponse timeoutValue, + CancellationToken cancellationToken) { long transportGeneration = client.TransportGeneration; + using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); timeoutCts.CancelAfter(_requestTimeout); try { - JsonElement response = await client.SendRequestAsync(method, parameters, timeoutCts.Token).ConfigureAwait(false); + TResponse response = await client.SendRequestAsync(method, parameters, timeoutCts.Token).ConfigureAwait(false); ResetRequestTimeoutTracking(transportGeneration); return response; } catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) { RecordRequestTimeout(client, method, transportGeneration); - return default; + return timeoutValue; } } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs similarity index 84% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs index dad60413bb..b0d4075f9e 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.SemanticTokens.cs @@ -1,16 +1,8 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text.Json; -using System.Threading; -using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; -internal sealed partial class LuaLanguageServerIntellisenseProvider +public sealed partial class LuaLanguageServerIntellisenseProvider { private void HandleSemanticTokensRefreshRequested() => ObserveBackgroundTask(RefreshTrackedSemanticTokensAsync(CancellationToken.None), "Semantic tokens refresh"); @@ -36,12 +28,15 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc try { LuaSemanticTokensDeltaState deltaState = _documents.GetSemanticTokensDeltaState(document.FilePath); + bool useDelta = _client.SupportsSemanticTokensDelta && deltaState.PreviousResultId is not null && deltaState.PreviousData is not null; - JsonElement response = await SendSemanticTokensRequestAsync(document, deltaState.PreviousResultId, useDelta, effectiveToken).ConfigureAwait(false); - if (response.ValueKind == JsonValueKind.Undefined) + LuaSemanticTokensWireResponse? response = await SendSemanticTokensRequestAsync(document, deltaState.PreviousResultId, useDelta, effectiveToken) + .ConfigureAwait(false); + + if (response is null) return; LuaSemanticTokensDecodeResult decodeResult = DecodeSemanticTokensResponse(response, document, deltaState.PreviousData, useDelta); @@ -50,9 +45,10 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc { _documents.StoreSemanticTokensDeltaState(document.FilePath, null, null); - JsonElement fullResponse = await SendSemanticTokensRequestAsync(document, previousResultId: null, useDelta: false, effectiveToken).ConfigureAwait(false); + LuaSemanticTokensWireResponse? fullResponse = await SendSemanticTokensRequestAsync(document, previousResultId: null, useDelta: false, effectiveToken) + .ConfigureAwait(false); - if (fullResponse.ValueKind == JsonValueKind.Undefined) + if (fullResponse is null) return; decodeResult = DecodeSemanticTokensResponse(fullResponse, document, previousData: null, deltaWasRequested: false); @@ -93,27 +89,27 @@ private async Task RefreshSemanticTokensAsync(LuaDocumentSnapshot document, Canc } } - private Task SendSemanticTokensRequestAsync( + private Task SendSemanticTokensRequestAsync( LuaDocumentSnapshot document, string? previousResultId, bool useDelta, CancellationToken cancellationToken) { if (_client is null) - return Task.FromResult(default(JsonElement)); + return Task.FromResult(null); string method = useDelta ? "textDocument/semanticTokens/full/delta" : "textDocument/semanticTokens/full"; - object parameters = useDelta - ? new { textDocument = new { uri = document.Uri }, previousResultId } - : new { textDocument = new { uri = document.Uri } }; + var parameters = new LuaSemanticTokensParams( + new LuaTextDocumentIdentifier(document.Uri), + useDelta ? previousResultId : null); - return SendBoundedRequestAsync(_client, method, parameters, cancellationToken); + return SendBoundedRequestAsync(_client, method, parameters, timeoutValue: null, cancellationToken); } private LuaSemanticTokensDecodeResult DecodeSemanticTokensResponse( - JsonElement response, LuaDocumentSnapshot document, int[]? previousData, bool deltaWasRequested) + LuaSemanticTokensWireResponse? response, LuaDocumentSnapshot document, int[]? previousData, bool deltaWasRequested) { - if (_client is null) + if (_client is null || response is null) return new LuaSemanticTokensDecodeResult([], null, null, false); if (deltaWasRequested) @@ -128,6 +124,7 @@ private LuaSemanticTokensDecodeResult DecodeSemanticTokensResponse( { IReadOnlyList tokens = LuaLanguageServerSemanticTokensDecoder.Decode( patchedData, document, _client.SemanticTokenTypes, _client.SemanticTokenModifiers); + return new LuaSemanticTokensDecodeResult(tokens, patchedData, delta.ResultId, false); } diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.cs similarity index 89% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.cs index 975e8acdfc..2adf8ad6d7 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/Provider/LuaLanguageServerIntellisenseProvider.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerIntellisenseProvider.cs @@ -1,22 +1,15 @@ -#nullable enable - using NLog; -using System; using System.Collections.Concurrent; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; using TombLib.Scripting.Lua.Objects; using TombLib.Scripting.Lua.Services; using TombLib.Scripting.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Implements the Lua IntelliSense provider by synchronizing editor documents with LuaLS and caching its responses. /// -internal sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider +public sealed partial class LuaLanguageServerIntellisenseProvider : ILuaIntellisenseProvider { private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -164,8 +157,13 @@ public IReadOnlyList GetSemanticTokens(string filePath) /// The local file path. /// The current document content. public void OpenDocument(string filePath, string content) - => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, acquireOpenReference: true, + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return; + + ObserveBackgroundTask(SynchronizeDocumentAsync(normalizedFilePath, content, acquireOpenReference: true, refreshSemanticTokens: true, CancellationToken.None), "Document open"); + } /// /// Pushes updated content for a document that is already tracked by the provider. @@ -173,8 +171,13 @@ public void OpenDocument(string filePath, string content) /// The local file path. /// The updated document content. public void UpdateDocument(string filePath, string content) - => ObserveBackgroundTask(TrySynchronizeDocumentAsync(filePath, content, acquireOpenReference: false, + { + if (!LuaLanguageServerPathHelper.TryNormalizeLocalPath(filePath, out string normalizedFilePath)) + return; + + ObserveBackgroundTask(SynchronizeDocumentAsync(normalizedFilePath, content, acquireOpenReference: false, refreshSemanticTokens: true, CancellationToken.None), "Document change"); + } /// /// Closes a tracked document and releases its server-side state when the last open reference disappears. @@ -221,9 +224,11 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) return true; } - if (_startupSucceeded && !_client.IsReady) + if (!_client.IsReady) { - Log.Info("Lua language server connection dropped, restarting and reopening tracked documents."); + if (_startupSucceeded) + Log.Info("Lua language server connection dropped, restarting and reopening tracked documents."); + documentsToReopen = _documents.PrepareForRestart(); } @@ -241,15 +246,19 @@ private async Task EnsureStartedAsync(CancellationToken cancellationToken) if (_startupSucceeded) { _consecutiveStartupFailures = 0; + ResetRequestTimeoutTracking(_client.TransportGeneration); + _transientStartupFailureReported = false; _permanentStartupFailureReported = false; + EnsureWorkspaceFileWatcherStarted(); } else { // Record repeated failures so IntelliSense eventually stops advertising availability until restart. _consecutiveStartupFailures++; + bool isPermanentFailure = _consecutiveStartupFailures >= HardStartupFailureThreshold; if (isPermanentFailure) @@ -293,7 +302,7 @@ private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, Canc return; // Normalize every path once, drop invalid entries, and track whether any change affects LuaLS configuration. - var changes = new List(batch.Count); + var changes = new List(batch.Count); bool shouldRefreshConfiguration = false; foreach ((string path, FileChangeKind kind) in batch.Entries) @@ -303,11 +312,7 @@ private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, Canc shouldRefreshConfiguration |= IsWorkspaceConfigurationPath(normalizedPath); - changes.Add(new - { - uri = LuaLanguageServerPathHelper.CreateFileUri(normalizedPath), - type = (int)kind - }); + changes.Add(new LuaFileEventPayload(LuaLanguageServerPathHelper.CreateFileUri(normalizedPath), (int)kind)); } if (changes.Count == 0) @@ -319,12 +324,12 @@ private async Task DispatchWorkspaceFileChangesAsync(FileChangeBatch batch, Canc if (shouldRefreshConfiguration) { await _client.SendNotificationAsync("workspace/didChangeConfiguration", - new { settings = LuaLanguageServerSettingsFactory.Create(_workspaceRootDirectoryPath) }, + new LuaDidChangeConfigurationParams(LuaLanguageServerSettingsFactory.Create(_workspaceRootDirectoryPath)), cancellationToken).ConfigureAwait(false); } await _client.SendNotificationAsync("workspace/didChangeWatchedFiles", - new { changes }, cancellationToken).ConfigureAwait(false); + new LuaDidChangeWatchedFilesParams([.. changes]), cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { } @@ -345,6 +350,7 @@ private bool IsWorkspaceConfigurationPath(string normalizedPath) return true; string fileName = Path.GetFileName(normalizedPath); + return string.Equals(fileName, ".luarc.json", StringComparison.OrdinalIgnoreCase) || string.Equals(fileName, ".luarc.jsonc", StringComparison.OrdinalIgnoreCase); } @@ -368,10 +374,10 @@ private void ReportStartupFailure(bool isPermanentFailure) LuaLanguageServerStartupFailure failure = isPermanentFailure ? new LuaLanguageServerStartupFailure( - "The bundled Lua language server failed to start repeatedly and Lua IntelliSense is now disabled until TombIDE is restarted. See the log for technical details.", + "The bundled Lua language server failed to start repeatedly and Lua IntelliSense is now disabled until the application is restarted. See the log for technical details.", true) : new LuaLanguageServerStartupFailure( - "The bundled Lua language server failed to start. Lua IntelliSense will remain unavailable until TombIDE can start the server successfully. TombIDE will retry automatically when Lua IntelliSense is requested again.", + "The bundled Lua language server failed to start. Lua IntelliSense will remain unavailable until the application can start the server successfully. The application will retry automatically when Lua IntelliSense is requested again.", false); RaiseStartupFailed(failure); @@ -383,12 +389,12 @@ private void HandleWorkspaceWatcherFailed(Exception? exception) return; Log.Warn(exception, - "Lua workspace watching is disabled for '{Workspace}'. Open editors will keep working, but external Lua workspace changes will not be forwarded until TombIDE is restarted.", + "Lua workspace watching is disabled for '{Workspace}'. Open editors will keep working, but external Lua workspace changes will not be forwarded until the application is restarted.", _workspaceRootDirectoryPath); RaiseWorkspaceWatcherFailed(new LuaWorkspaceWatcherFailure( "The Lua workspace file watcher encountered an internal error and has been disabled for this session.\n\n" + - "Lua IntelliSense will continue to work for files edited inside TombIDE, but external workspace changes - such as Git pull updates, generated .API files, or .luarc changes - will no longer be forwarded until TombIDE is restarted.")); + "Lua IntelliSense will continue to work for files edited in the editor, but external workspace changes - such as Git pull updates, generated .API files, or .luarc changes - will no longer be forwarded until the application is restarted.")); } private void RaiseDiagnosticsUpdated(string filePath, IReadOnlyList diagnostics) @@ -415,7 +421,7 @@ private void RaiseWorkspaceWatcherFailed(LuaWorkspaceWatcherFailure failure) handler => ((Action)handler)(failure), "Lua workspace-watcher subscriber"); - private void InvokeSubscribersSafely(Delegate? handlers, Action invoke, string subscriberDescription) + private static void InvokeSubscribersSafely(Delegate? handlers, Action invoke, string subscriberDescription) { if (handlers is null) return; @@ -462,6 +468,7 @@ public void Dispose() } CancelAllSemanticTokenRequests(); + _startLock.Dispose(); _client?.Dispose(); } diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerNotificationPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerNotificationPayloads.cs new file mode 100644 index 0000000000..1da4b62582 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerNotificationPayloads.cs @@ -0,0 +1,42 @@ +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the typed payload for a textDocument/didOpen notification. +/// +public readonly record struct LuaDidOpenTextDocumentParams( + [property: JsonPropertyName("textDocument")] LuaDidOpenTextDocumentPayload TextDocument); + +public readonly record struct LuaDidOpenTextDocumentPayload( + [property: JsonPropertyName("uri")] string Uri, + [property: JsonPropertyName("languageId")] string LanguageId, + [property: JsonPropertyName("version")] int Version, + [property: JsonPropertyName("text")] string Text); + +public readonly record struct LuaVersionedTextDocumentIdentifierPayload( + [property: JsonPropertyName("uri")] string Uri, + [property: JsonPropertyName("version")] int Version); + +public readonly record struct LuaDidChangeTextDocumentParams( + [property: JsonPropertyName("textDocument")] LuaVersionedTextDocumentIdentifierPayload TextDocument, + [property: JsonPropertyName("contentChanges")] LuaTextDocumentContentChangePayload[] ContentChanges); + +public readonly record struct LuaTextDocumentContentChangePayload( + [property: JsonPropertyName("text")] string Text, + [property: JsonPropertyName("range")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + LuaProtocolRangePayload? Range = null); + +public readonly record struct LuaDidCloseTextDocumentParams( + [property: JsonPropertyName("textDocument")] LuaTextDocumentIdentifier TextDocument); + +public readonly record struct LuaDidChangeConfigurationParams( + [property: JsonPropertyName("settings")] object Settings); + +public readonly record struct LuaDidChangeWatchedFilesParams( + [property: JsonPropertyName("changes")] LuaFileEventPayload[] Changes); + +public readonly record struct LuaFileEventPayload( + [property: JsonPropertyName("uri")] string Uri, + [property: JsonPropertyName("type")] int Type); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerRequestPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerRequestPayloads.cs new file mode 100644 index 0000000000..aaa5a6445f --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Provider/LuaLanguageServerRequestPayloads.cs @@ -0,0 +1,55 @@ +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public readonly record struct LuaTextDocumentIdentifier( + [property: JsonPropertyName("uri")] string Uri); + +public readonly record struct LuaProtocolPosition( + [property: JsonPropertyName("line")] int Line, + [property: JsonPropertyName("character")] int Character); + +/// +/// Represents a text-document request payload that targets a specific position. +/// +public readonly record struct LuaTextDocumentPositionParams( + [property: JsonPropertyName("textDocument")] LuaTextDocumentIdentifier TextDocument, + [property: JsonPropertyName("position")] LuaProtocolPosition Position); + +public readonly record struct LuaCompletionContextPayload( + [property: JsonPropertyName("triggerKind")] int TriggerKind, + [property: JsonPropertyName("triggerCharacter")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? TriggerCharacter = null); + +public readonly record struct LuaCompletionParams( + [property: JsonPropertyName("textDocument")] LuaTextDocumentIdentifier TextDocument, + [property: JsonPropertyName("position")] LuaProtocolPosition Position, + [property: JsonPropertyName("context")] LuaCompletionContextPayload Context); + +public readonly record struct LuaReferenceContextPayload( + [property: JsonPropertyName("includeDeclaration")] bool IncludeDeclaration); + +public readonly record struct LuaReferenceParams( + [property: JsonPropertyName("textDocument")] LuaTextDocumentIdentifier TextDocument, + [property: JsonPropertyName("position")] LuaProtocolPosition Position, + [property: JsonPropertyName("context")] LuaReferenceContextPayload Context); + +public readonly record struct LuaRenameParams( + [property: JsonPropertyName("textDocument")] LuaTextDocumentIdentifier TextDocument, + [property: JsonPropertyName("position")] LuaProtocolPosition Position, + [property: JsonPropertyName("newName")] string NewName); + +public readonly record struct LuaFormattingOptionsPayload( + [property: JsonPropertyName("tabSize")] int TabSize, + [property: JsonPropertyName("insertSpaces")] bool InsertSpaces); + +public readonly record struct LuaDocumentFormattingParams( + [property: JsonPropertyName("textDocument")] LuaTextDocumentIdentifier TextDocument, + [property: JsonPropertyName("options")] LuaFormattingOptionsPayload Options); + +public readonly record struct LuaSemanticTokensParams( + [property: JsonPropertyName("textDocument")] LuaTextDocumentIdentifier TextDocument, + [property: JsonPropertyName("previousResultId")] + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + string? PreviousResultId = null); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaLanguageServerResponseParser.References.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaLanguageServerResponseParser.References.cs new file mode 100644 index 0000000000..853582dd3e --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaLanguageServerResponseParser.References.cs @@ -0,0 +1,36 @@ +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses reference locations from a LuaLS references response. + /// + public static IReadOnlyList ParseReferenceLocations(IReadOnlyList? response) + { + if (response is not { Count: > 0 }) + return []; + + var locations = new List(); + + for (int i = 0; i < response.Count; i++) + { + LuaReferenceResponse referenceElement = response[i]; + + if (string.IsNullOrWhiteSpace(referenceElement.Uri)) + continue; + + if (!Uri.TryCreate(referenceElement.Uri, UriKind.Absolute, out Uri? parsedUri) + || parsedUri?.IsFile != true + || !TryParseDocumentRange(referenceElement.Range, out LuaDocumentRange? range)) + { + continue; + } + + locations.Add(new LuaReferenceLocation(LuaLanguageServerPathHelper.NormalizeLocalPath(parsedUri), range)); + } + + return locations; + } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaReferencePayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaReferencePayloads.cs new file mode 100644 index 0000000000..c138b48ac6 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/References/LuaReferencePayloads.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents a single typed reference location returned by LuaLS. +/// +public sealed record LuaReferenceResponse +{ + [JsonPropertyName("uri")] + public string? Uri { get; init; } + + [JsonPropertyName("range")] + public LuaProtocolRangePayload? Range { get; init; } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/Rename/LuaLanguageServerResponseParser.Rename.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/Rename/LuaLanguageServerResponseParser.Rename.cs new file mode 100644 index 0000000000..66713bccb3 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/Rename/LuaLanguageServerResponseParser.Rename.cs @@ -0,0 +1,106 @@ +using System.Diagnostics.CodeAnalysis; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses a workspace edit from a LuaLS rename response. + /// + public static LuaWorkspaceEdit? ParseWorkspaceEdit(LuaWorkspaceEditResponse? response) + { + if (response is null) + return null; + + var editsByFile = new Dictionary>(StringComparer.OrdinalIgnoreCase); + + ParseChangeMap(response.Value.Changes, editsByFile); + ParseDocumentChanges(response.Value.DocumentChanges, editsByFile); + + if (editsByFile.Count == 0) + return null; + + var documentEdits = new List(editsByFile.Count); + + foreach ((string filePath, List textEdits) in editsByFile) + { + if (textEdits.Count == 0) + continue; + + documentEdits.Add(new LuaDocumentEdit(filePath, textEdits)); + } + + return documentEdits.Count == 0 + ? null + : new LuaWorkspaceEdit(documentEdits); + } + + private static void ParseChangeMap(IReadOnlyDictionary? changes, + Dictionary> editsByFile) + { + if (changes is null) + return; + + foreach ((string uri, LuaTextEditPayload[]? edits) in changes) + { + if (!LuaLanguageServerPathHelper.TryGetFilePath(uri, out string filePath)) + continue; + + List textEdits = GetOrCreateTextEditBucket(editsByFile, filePath); + AppendTextEdits(edits, textEdits); + } + } + + private static void ParseDocumentChanges(IReadOnlyList? documentChanges, + Dictionary> editsByFile) + { + if (documentChanges is null) + return; + + for (int i = 0; i < documentChanges.Count; i++) + { + LuaWorkspaceDocumentChangePayload documentChange = documentChanges[i]; + + if (!LuaLanguageServerPathHelper.TryGetFilePath(documentChange.TextDocument?.Uri, out string filePath)) + continue; + + List textEdits = GetOrCreateTextEditBucket(editsByFile, filePath); + AppendTextEdits(documentChange.Edits, textEdits); + } + } + + private static void AppendTextEdits(IReadOnlyList? edits, List textEdits) + { + if (edits is null) + return; + + for (int i = 0; i < edits.Count; i++) + { + if (TryParseTextEdit(edits[i], out LuaTextEdit? textEdit)) + textEdits.Add(textEdit); + } + } + + private static bool TryParseTextEdit(LuaTextEditPayload edit, [NotNullWhen(true)] out LuaTextEdit? textEdit) + { + textEdit = null; + + if (!TryParseDocumentRange(edit.Range, out LuaDocumentRange? range)) + return false; + + textEdit = new LuaTextEdit(range, edit.NewText ?? string.Empty); + return true; + } + + private static List GetOrCreateTextEditBucket(Dictionary> editsByFile, string filePath) + { + if (!editsByFile.TryGetValue(filePath, out List? textEdits)) + { + textEdits = []; + editsByFile[filePath] = textEdits; + } + + return textEdits; + } +} diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs similarity index 71% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs index e043e46ad5..691ed206d2 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaLanguageServerSemanticTokensDeltaParser.cs @@ -1,11 +1,6 @@ -#nullable enable - -using System; -using System.Collections.Generic; -using System.Text.Json; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Result of a `textDocument/semanticTokens/full/delta` response: either the server returned a full @@ -15,7 +10,7 @@ namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; /// The result id that can seed the next delta request. /// The full semantic-token integer stream, when provided. /// The incremental edits, when provided instead of . -internal readonly record struct LuaSemanticTokensDeltaResponse( +public readonly record struct LuaSemanticTokensDeltaResponse( string? ResultId, int[]? Data, IReadOnlyList? Edits); @@ -26,50 +21,40 @@ internal readonly record struct LuaSemanticTokensDeltaResponse( /// The zero-based start offset within the integer stream. /// The number of integers to remove. /// The replacement integers to insert. -internal readonly record struct LuaSemanticTokensEdit(int Start, int DeleteCount, int[] Data); +public readonly record struct LuaSemanticTokensEdit(int Start, int DeleteCount, int[] Data); /// /// Parses LuaLS semantic-token delta responses and applies them to the cached token stream. /// -internal static class LuaLanguageServerSemanticTokensDeltaParser +public static class LuaLanguageServerSemanticTokensDeltaParser { /// /// Parses a semantic-token response that may contain either a full token stream or incremental edits. /// - /// The raw JSON response payload. + /// The typed response payload. /// The parsed semantic-token delta response. - public static LuaSemanticTokensDeltaResponse Parse(JsonElement response) + public static LuaSemanticTokensDeltaResponse Parse(LuaSemanticTokensWireResponse? response) { - string? resultId = response.TryGetProperty("resultId", out JsonElement resultIdElement) - && resultIdElement.ValueKind == JsonValueKind.String - ? resultIdElement.GetString() - : null; + if (response is not { } payload) + return new LuaSemanticTokensDeltaResponse(ResultId: null, Data: null, Edits: null); - if (response.TryGetProperty("data", out JsonElement dataElement) && dataElement.ValueKind == JsonValueKind.Array) - return new LuaSemanticTokensDeltaResponse(resultId, ReadIntArray(dataElement), Edits: null); + if (payload.Data is { } data) + return new LuaSemanticTokensDeltaResponse(payload.ResultId, data, Edits: null); - if (response.TryGetProperty("edits", out JsonElement editsElement) && editsElement.ValueKind == JsonValueKind.Array) + if (payload.Edits is { } editsPayload) { - var edits = new List(editsElement.GetArrayLength()); + var edits = new List(editsPayload.Length); - foreach (JsonElement editElement in editsElement.EnumerateArray()) + for (int i = 0; i < editsPayload.Length; i++) { - if (editElement.ValueKind != JsonValueKind.Object) - continue; - - int start = editElement.TryGetProperty("start", out JsonElement startElement) && startElement.TryGetInt32(out int parsedStart) ? parsedStart : 0; - int deleteCount = editElement.TryGetProperty("deleteCount", out JsonElement deleteCountElement) && deleteCountElement.TryGetInt32(out int parsedDeleteCount) ? parsedDeleteCount : 0; - int[] data = editElement.TryGetProperty("data", out JsonElement editDataElement) && editDataElement.ValueKind == JsonValueKind.Array - ? ReadIntArray(editDataElement) - : []; - - edits.Add(new LuaSemanticTokensEdit(start, deleteCount, data)); + LuaSemanticTokensEditPayload edit = editsPayload[i]; + edits.Add(new LuaSemanticTokensEdit(edit.Start ?? 0, edit.DeleteCount ?? 0, edit.Data ?? [])); } - return new LuaSemanticTokensDeltaResponse(resultId, Data: null, edits); + return new LuaSemanticTokensDeltaResponse(payload.ResultId, Data: null, edits); } - return new LuaSemanticTokensDeltaResponse(resultId, Data: null, Edits: null); + return new LuaSemanticTokensDeltaResponse(payload.ResultId, Data: null, Edits: null); } /// @@ -79,9 +64,6 @@ public static LuaSemanticTokensDeltaResponse Parse(JsonElement response) /// public static int[]? ApplyEdits(int[] previousData, IReadOnlyList edits) { - ArgumentNullException.ThrowIfNull(previousData); - ArgumentNullException.ThrowIfNull(edits); - // LSP requires edits to be sorted by ascending start; we re-sort defensively in case the server // or our own caching layer reorders them. Edits are then applied left-to-right with a running // source/destination cursor so the resulting integer stream stays consistent regardless of @@ -135,24 +117,13 @@ public static LuaSemanticTokensDeltaResponse Parse(JsonElement response) return destinationIndex == newLength ? result : null; } - - private static int[] ReadIntArray(JsonElement arrayElement) - { - int[] data = new int[arrayElement.GetArrayLength()]; - int index = 0; - - foreach (JsonElement value in arrayElement.EnumerateArray()) - data[index++] = value.TryGetInt32(out int parsed) ? parsed : 0; - - return data; - } } /// /// Decodes a raw LuaLS semantic-token integer stream (already cached on the client) into the typed /// list expected by the editor's colorizer. /// -internal static class LuaLanguageServerSemanticTokensDecoder +public static class LuaLanguageServerSemanticTokensDecoder { private static readonly IReadOnlyList EmptyModifiers = []; diff --git a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDecodeResult.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensDecodeResult.cs similarity index 55% rename from TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDecodeResult.cs rename to TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensDecodeResult.cs index 9a647e26d3..0b78983f26 100644 --- a/TombIDE/TombIDE.ScriptingStudio/Services/LuaIntellisense/SemanticTokens/LuaSemanticTokensDecodeResult.cs +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensDecodeResult.cs @@ -1,15 +1,12 @@ -#nullable enable - -using System.Collections.Generic; using TombLib.Scripting.Lua.Objects; -namespace TombIDE.ScriptingStudio.Services.LuaIntellisense; +namespace TombLib.Scripting.Lua.LanguageServer; /// /// Represents the decoded semantic tokens payload and whether the caller should retry with a full refresh. /// -internal readonly record struct LuaSemanticTokensDecodeResult( +public readonly record struct LuaSemanticTokensDecodeResult( IReadOnlyList Tokens, int[]? Data, string? ResultId, - bool RetryWithFullRefresh); \ No newline at end of file + bool RetryWithFullRefresh); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensDeltaState.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensDeltaState.cs new file mode 100644 index 0000000000..2d55b396c8 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensDeltaState.cs @@ -0,0 +1,6 @@ +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the cached semantic-tokens delta state used for incremental refresh requests. +/// +public readonly record struct LuaSemanticTokensDeltaState(string? PreviousResultId, int[]? PreviousData); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensPayloads.cs new file mode 100644 index 0000000000..2848dc0175 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/SemanticTokens/LuaSemanticTokensPayloads.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the typed top-level semantic-token response for both full and delta results. +/// +public readonly record struct LuaSemanticTokensWireResponse( + [property: JsonPropertyName("resultId")] string? ResultId, + [property: JsonPropertyName("data")] int[]? Data, + [property: JsonPropertyName("edits")] LuaSemanticTokensEditPayload[]? Edits); + +public readonly record struct LuaSemanticTokensEditPayload( + [property: JsonPropertyName("start")] int? Start, + [property: JsonPropertyName("deleteCount")] int? DeleteCount, + [property: JsonPropertyName("data")] int[]? Data); diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs new file mode 100644 index 0000000000..7a16d979cd --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaLanguageServerResponseParser.SignatureHelp.cs @@ -0,0 +1,95 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using TombLib.Scripting.Lua.Objects; + +namespace TombLib.Scripting.Lua.LanguageServer; + +public static partial class LuaLanguageServerResponseParser +{ + /// + /// Parses signature help metadata from a LuaLS signature-help response. + /// + public static LuaSignatureInfo? ParseSignatureHelp(LuaSignatureHelpResponse? response) + { + if (response?.Signatures is not { Length: > 0 } signatures) + return null; + + int activeSignature = response.ActiveSignature is int parsedActiveSignature + ? Math.Clamp(parsedActiveSignature, 0, signatures.Length - 1) + : 0; + + LuaSignatureHelpSignaturePayload signatureElement = signatures[activeSignature]; + + if (string.IsNullOrWhiteSpace(signatureElement.Label)) + return null; + + string label = signatureElement.Label; + + string? documentation = signatureElement.Documentation.ValueKind != JsonValueKind.Undefined + ? ExtractMarkupText(signatureElement.Documentation) + : null; + + int activeParameter = ResolveActiveParameter(response, signatureElement); + + var parameters = new List(); + + if (signatureElement.Parameters is { Length: > 0 } parametersElement) + { + for (int i = 0; i < parametersElement.Length; i++) + { + LuaSignatureHelpParameterPayload paramElement = parametersElement[i]; + + string? parameterLabel = paramElement.Label.ValueKind == JsonValueKind.String + ? paramElement.Label.GetString() + : TryExtractParameterLabel(label, paramElement.Label, out string? extractedLabel) + ? extractedLabel + : null; + + string? parameterDocumentation = paramElement.Documentation.ValueKind != JsonValueKind.Undefined + ? ExtractMarkupText(paramElement.Documentation) + : null; + + parameters.Add(new LuaParameterInfo(parameterLabel ?? string.Empty, parameterDocumentation)); + } + } + + return new LuaSignatureInfo(label, documentation, parameters, activeParameter); + } + + private static int ResolveActiveParameter(LuaSignatureHelpResponse response, LuaSignatureHelpSignaturePayload signatureElement) + { + if (response.ActiveParameter is int responseActiveParameter) + return Math.Max(0, responseActiveParameter); + + if (signatureElement.ActiveParameter is int signatureActiveParameter) + return Math.Max(0, signatureActiveParameter); + + return 0; + } + + private static bool TryExtractParameterLabel(string signatureLabel, JsonElement parameterLabelElement, + [NotNullWhen(true)] out string? parameterLabel) + { + parameterLabel = null; + + if (string.IsNullOrEmpty(signatureLabel) || parameterLabelElement.ValueKind != JsonValueKind.Array) + return false; + + JsonElement.ArrayEnumerator labelParts = parameterLabelElement.EnumerateArray(); + + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int startIndex)) + return false; + + if (!labelParts.MoveNext() || !labelParts.Current.TryGetInt32(out int endIndex)) + return false; + + startIndex = Math.Max(0, Math.Min(startIndex, signatureLabel.Length)); + endIndex = Math.Max(startIndex, Math.Min(endIndex, signatureLabel.Length)); + + if (endIndex <= startIndex) + return false; + + parameterLabel = signatureLabel[startIndex..endIndex]; + return true; + } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaSignatureHelpPayloads.cs b/TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaSignatureHelpPayloads.cs new file mode 100644 index 0000000000..2037085e11 --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/SignatureHelp/LuaSignatureHelpPayloads.cs @@ -0,0 +1,43 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace TombLib.Scripting.Lua.LanguageServer; + +/// +/// Represents the typed top-level signature-help payload returned by LuaLS. +/// +public sealed record LuaSignatureHelpResponse +{ + [JsonPropertyName("activeSignature")] + public int? ActiveSignature { get; init; } + + [JsonPropertyName("activeParameter")] + public int? ActiveParameter { get; init; } + + [JsonPropertyName("signatures")] + public LuaSignatureHelpSignaturePayload[]? Signatures { get; init; } +} + +public sealed record LuaSignatureHelpSignaturePayload +{ + [JsonPropertyName("label")] + public string? Label { get; init; } + + [JsonPropertyName("documentation")] + public JsonElement Documentation { get; init; } + + [JsonPropertyName("activeParameter")] + public int? ActiveParameter { get; init; } + + [JsonPropertyName("parameters")] + public LuaSignatureHelpParameterPayload[]? Parameters { get; init; } +} + +public sealed record LuaSignatureHelpParameterPayload +{ + [JsonPropertyName("label")] + public JsonElement Label { get; init; } + + [JsonPropertyName("documentation")] + public JsonElement Documentation { get; init; } +} diff --git a/TombLib/TombLib.Scripting.Lua.LanguageServer/TombLib.Scripting.Lua.LanguageServer.csproj b/TombLib/TombLib.Scripting.Lua.LanguageServer/TombLib.Scripting.Lua.LanguageServer.csproj new file mode 100644 index 0000000000..1411600dcd --- /dev/null +++ b/TombLib/TombLib.Scripting.Lua.LanguageServer/TombLib.Scripting.Lua.LanguageServer.csproj @@ -0,0 +1,19 @@ + + + + false + enable + enable + + + + + + + + + + + + + diff --git a/TombLib/TombLib.Scripting.Lua/README.md b/TombLib/TombLib.Scripting.Lua/README.md deleted file mode 100644 index f404c735ca..0000000000 --- a/TombLib/TombLib.Scripting.Lua/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Lua Editor Ownership Notes - -This note is a phase 0 maintainer map for the current Lua editor layout. It is intentionally short and should be updated as cleanup work lands. - -## Current ownership - -- `LuaEditor.cs`: public control surface, composition root, theme application, syntax-highlighting setup, and provider hookup. -- `LuaEditor.Intellisense.cs`: event wiring, trigger routing, document/request generation invalidation, unload cleanup, and shared editor-side request helpers. -- `Editor/Completion/LuaCompletionController.cs`: editor-facing completion entry points, debounce scheduling, popup lifecycle, completion tooltip resolve flow, query-offset calculation, width measurement, and AvalonEdit popup integration details. -- `Editor/Hover/LuaHoverController.cs`: editor hover entry points, hover request cancellation, hover eligibility checks, tooltip rendering, and hover versus diagnostic tooltip selection. -- `Editor/Navigation/LuaDefinitionNavigationController.cs`: F12 and Ctrl+Click definition navigation flow and definition-request cancellation state. -- `Editor/SignatureHelp/LuaSignatureHelpController.cs`: editor-facing signature help entry points, signature popup UI, refresh timer, pending-request state, popup positioning, and request flow. -- `LuaEditor.Navigation.cs`: keyboard and mouse navigation event handling plus the public navigation entry point. -- `LuaEditor.SemanticHighlighting.cs`: semantic-token subscriptions, token application, and editor-side highlighting refresh. -- `Utils/`: editor-local rules and pure helpers such as line parsing, indentation, and hover/completion/definition interaction guards. -- `Services/ILuaIntellisenseProvider.cs`: editor-facing contract for the Lua language-service backend. - -## Extraction naming - -- Use `Controller` for new stateful editor-owned feature workflows. -- Reserve `Coordinator` for provider-side workflows that own document queues, background refresh, or restart-sensitive state. -- Keep `Service` for stable external integration surfaces or shared utilities that already represent a service boundary. - -## Cleanup guardrails - -- Keep `LuaEditor` as the public control and composition root. -- Keep partials only when the state still clearly belongs to `LuaEditor` itself. -- Prefer moving real feature state and workflow into a named owner instead of spreading it across another partial. \ No newline at end of file diff --git a/TombLib/TombLib.Test/GlobalUsings.LuaLanguageServer.cs b/TombLib/TombLib.Test/GlobalUsings.LuaLanguageServer.cs new file mode 100644 index 0000000000..144beb6b29 --- /dev/null +++ b/TombLib/TombLib.Test/GlobalUsings.LuaLanguageServer.cs @@ -0,0 +1 @@ +global using TombLib.Scripting.Lua.LanguageServer; \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs b/TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs index ca2d3f14d2..62a2be4e95 100644 --- a/TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs +++ b/TombLib/TombLib.Test/LuaIntellisenseDocumentManagerTests.cs @@ -27,6 +27,22 @@ public void Rename_ReturnsNullAndPreservesTrackedDocuments_WhenDestinationIsAlre Assert.AreEqual(1, destinationDocument.Version); Assert.IsTrue(manager.TryClose(oldFilePath, out _)); Assert.IsTrue(manager.TryClose(newFilePath, out LuaDocumentSnapshot? closedDestinationDocument)); + Assert.IsNotNull(closedDestinationDocument); Assert.AreEqual("return 2", closedDestinationDocument.Content); } + + [TestMethod] + public void TryClose_RemovesTrackedDocumentWhileRestartReplayIsPending() + { + var manager = new LuaIntellisenseDocumentManager(); + const string filePath = @"C:\Workspace\Scripts\pending.lua"; + + manager.Synchronize(filePath, "return 1", acquireOpenReference: true); + IReadOnlyList documentsToReopen = manager.PrepareForRestart(); + + Assert.AreEqual(1, documentsToReopen.Count); + Assert.IsTrue(manager.TryClose(filePath, out LuaDocumentSnapshot? closingDocument)); + Assert.IsNull(closingDocument); + Assert.IsNull(manager.GetDocumentSnapshot(filePath)); + } } \ No newline at end of file diff --git a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs index c997787e21..a07961af7d 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerClientTests.cs @@ -1,10 +1,9 @@ -using System.Collections.Concurrent; -using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Text; using System.Text.Json; +using StreamJsonRpc; using TombIDE.ScriptingStudio.Services.LuaIntellisense; namespace TombLib.Test; @@ -17,16 +16,16 @@ public void CaptureServerCapabilities_UsesFullTextSyncWhenServerAdvertisesFullSy { using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - InvokePrivateMethod(client, "CaptureServerCapabilities", JsonSerializer.SerializeToElement(new - { - capabilities = new + InvokePrivateMethod(client, "CaptureServerCapabilities", DeserializeInitializeResponse( + """ { - textDocumentSync = new - { - change = 1 - } + "capabilities": { + "textDocumentSync": { + "change": 1 + } + } } - })); + """)); Assert.AreEqual(LuaTextDocumentSyncKind.Full, client.TextDocumentSyncKind); } @@ -37,13 +36,14 @@ public void CaptureServerCapabilities_RejectsMissingDocumentChangeSupport() using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); TargetInvocationException exception = Assert.ThrowsException(() => - InvokePrivateMethod(client, "CaptureServerCapabilities", JsonSerializer.SerializeToElement(new - { - capabilities = new + InvokePrivateMethod(client, "CaptureServerCapabilities", DeserializeInitializeResponse( + """ { - textDocumentSync = 0 + "capabilities": { + "textDocumentSync": {} + } } - }))); + """))); Assert.IsInstanceOfType(exception.InnerException, typeof(NotSupportedException)); } @@ -53,28 +53,57 @@ public void CaptureServerCapabilities_RecognizesReferenceRenameAndFormattingProv { using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - InvokePrivateMethod(client, "CaptureServerCapabilities", JsonSerializer.SerializeToElement(new - { - capabilities = new + InvokePrivateMethod(client, "CaptureServerCapabilities", DeserializeInitializeResponse( + """ { - referencesProvider = new { }, - renameProvider = new { prepareProvider = true }, - documentFormattingProvider = true + "capabilities": { + "referencesProvider": {}, + "renameProvider": { "prepareProvider": true }, + "documentFormattingProvider": true + } } - })); + """)); Assert.IsTrue(client.SupportsReferences); Assert.IsTrue(client.SupportsRename); Assert.IsTrue(client.SupportsFormatting); } + [TestMethod] + public void CaptureServerCapabilities_RecognizesSemanticTokensLegendAndDeltaSupport() + { + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); + + InvokePrivateMethod(client, "CaptureServerCapabilities", DeserializeInitializeResponse( + """ + { + "capabilities": { + "semanticTokensProvider": { + "full": { + "delta": true + }, + "legend": { + "tokenTypes": ["function", "variable"], + "tokenModifiers": ["declaration"] + } + } + } + } + """)); + + Assert.IsTrue(client.SupportsSemanticTokensDelta); + CollectionAssert.AreEqual(new[] { "function", "variable" }, client.SemanticTokenTypes.ToArray()); + CollectionAssert.AreEqual(new[] { "declaration" }, client.SemanticTokenModifiers.ToArray()); + } + [TestMethod] public void Dispose_WritesGracefulShutdownMessages() { using Process process = StartDisposableProcess(); + using var inputStream = new PendingReadStream(); using var outputStream = new RecordingStream(); using var client = new LuaLanguageServerClient(@"C:\Workspace", process.StartInfo.FileName, static () => new { }); - object session = CreateTransportSession(1, process, Stream.Null, outputStream); + object session = CreateTransportSession(client, 1, process, inputStream, outputStream, startListening: true); SetActiveSession(client, session); @@ -87,26 +116,19 @@ public void Dispose_WritesGracefulShutdownMessages() } [TestMethod] - public async Task HandleServerRequestAsync_SemanticTokensRefresh_AcknowledgesAndRaisesEvent() + public async Task HandleSemanticTokensRefreshRequestAsync_RaisesEventAndReturnsNull() { - await using var outputStream = new RecordingStream(); using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - object session = CreateTransportSession(1, process: null, Stream.Null, outputStream); bool refreshRequested = false; + object rpcTarget = CreateRpcTarget(client); + client.SemanticTokensRefreshRequested += () => refreshRequested = true; - await InvokePrivateTaskAsync(client, "HandleServerRequestAsync", - session, - JsonSerializer.SerializeToElement(7L), - "workspace/semanticTokens/refresh", - default(JsonElement)).ConfigureAwait(false); - - string writtenPayload = outputStream.GetWrittenText(); + object? result = await InvokePrivateTaskAsync(rpcTarget, "RefreshSemanticTokensAsync").ConfigureAwait(false); Assert.IsTrue(refreshRequested); - Assert.IsTrue(writtenPayload.Contains("\"id\":7", StringComparison.Ordinal), writtenPayload); - Assert.IsTrue(writtenPayload.Contains("\"result\":null", StringComparison.Ordinal), writtenPayload); + Assert.IsNull(result); } [TestMethod] @@ -119,12 +141,12 @@ public async Task PumpDiagnosticsAsync_CoalescesQueuedDiagnosticsByFile() client.DiagnosticsPublished += parameters => { publishedCount++; - lastMessage = parameters.GetProperty("diagnostics")[0].GetProperty("message").GetString(); + lastMessage = parameters.Diagnostics?[0].Message; CancelLifetime(client); }; - InvokePrivateMethod(client, "RaiseDiagnosticsPublished", CreateDiagnosticsParameters("file:///C:/Workspace/test.lua", "Stale warning.")); - InvokePrivateMethod(client, "RaiseDiagnosticsPublished", CreateDiagnosticsParameters("file:///C:/Workspace/test.lua", "Current warning.")); + InvokePrivateMethod(client, "RaiseDiagnosticsPublished", 0L, CreateDiagnosticsParameters("file:///C:/Workspace/test.lua", "Stale warning.")); + InvokePrivateMethod(client, "RaiseDiagnosticsPublished", 0L, CreateDiagnosticsParameters("file:///C:/Workspace/test.lua", "Current warning.")); await InvokePrivateTaskAsync(client, "PumpDiagnosticsAsync").ConfigureAwait(false); @@ -133,89 +155,80 @@ public async Task PumpDiagnosticsAsync_CoalescesQueuedDiagnosticsByFile() } [TestMethod] - public async Task ReadHeadersAndPayloadAsync_ReadsChunkedFrameAcrossBoundaries() + public async Task PumpDiagnosticsAsync_DropsQueuedDiagnosticsFromInactiveTransportGeneration() { using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - string payloadJson = "{\"jsonrpc\":\"2.0\",\"id\":1,\"result\":{\"value\":42}}"; - byte[] frame = CreateLspFrame(payloadJson); - object session = CreateTransportSession(1, process: null, new ChunkedReadStream(SplitBytes(frame, 5, 7, 11, 3)), Stream.Null); - - int? contentLength = await InvokePrivateTaskAsync(client, "ReadHeadersAsync", session).ConfigureAwait(false); - byte[]? payload = await InvokePrivateTaskAsync(client, "ReadPayloadAsync", session, contentLength!.Value).ConfigureAwait(false); - - Assert.AreEqual(Encoding.UTF8.GetByteCount(payloadJson), contentLength); - Assert.IsNotNull(payload); - Assert.AreEqual(payloadJson, Encoding.UTF8.GetString(payload)); - } + object oldSession = CreateTransportSession(client, 1, process: null, Stream.Null, Stream.Null); + object newSession = CreateTransportSession(client, 2, process: null, Stream.Null, Stream.Null); + int publishedCount = 0; + string? lastMessage = null; - [TestMethod] - public async Task ReadLoopAsync_HandlesChunkedSemanticTokensRefreshRequest() - { - await using var outputStream = new RecordingStream(); - using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - bool refreshRequested = false; - byte[] frame = CreateLspFrame("{\"jsonrpc\":\"2.0\",\"id\":9,\"method\":\"workspace/semanticTokens/refresh\"}"); - object session = CreateTransportSession(1, process: null, new ChunkedReadStream(SplitBytes(frame, 4, 9, 6, 13)), outputStream); + SetActiveSession(client, newSession); - client.SemanticTokensRefreshRequested += () => refreshRequested = true; + client.DiagnosticsPublished += parameters => + { + publishedCount++; + lastMessage = parameters.Diagnostics?[0].Message; + CancelLifetime(client); + }; - await InvokePrivateTaskAsync(client, "ReadLoopAsync", session).ConfigureAwait(false); + InvokePrivateMethod(client, "RaiseDiagnosticsPublished", GetTransportGeneration(oldSession), + CreateDiagnosticsParameters("file:///C:/Workspace/stale.lua", "Stale warning.")); + InvokePrivateMethod(client, "RaiseDiagnosticsPublished", GetTransportGeneration(newSession), + CreateDiagnosticsParameters("file:///C:/Workspace/current.lua", "Current warning.")); - string writtenPayload = outputStream.GetWrittenText(); + await InvokePrivateTaskAsync(client, "PumpDiagnosticsAsync").ConfigureAwait(false); - Assert.IsTrue(refreshRequested); - Assert.IsTrue(writtenPayload.Contains("\"id\":9", StringComparison.Ordinal), writtenPayload); - Assert.IsTrue(writtenPayload.Contains("\"result\":null", StringComparison.Ordinal), writtenPayload); + Assert.AreEqual(1, publishedCount); + Assert.AreEqual("Current warning.", lastMessage); } [TestMethod] - public async Task ReadLoopAsync_FailsPendingRequestsWhenConnectionCloses() + public void BuildConfigurationResponse_ReturnsRequestedLuaSections() { - using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - var pendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - object session = CreateTransportSession(1, process: null, new ChunkedReadStream(), Stream.Null); - - GetPendingRequests(session).TryAdd(42, pendingRequest); + using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new + { + Lua = new + { + runtime = new + { + version = "Lua 5.4" + } + } + }); - await InvokePrivateTaskAsync(client, "ReadLoopAsync", session).ConfigureAwait(false); + object[] response = (object[])InvokePrivateMethodWithReturn(client, "BuildConfigurationResponse", + new LuaWorkspaceConfigurationParams( + [ + new LuaWorkspaceConfigurationItem("Lua"), + new LuaWorkspaceConfigurationItem("Lua.runtime") + ])); - await Assert.ThrowsExceptionAsync(() => pendingRequest.Task).ConfigureAwait(false); + Assert.AreEqual(2, response.Length); + Assert.AreEqual("Lua 5.4", JsonSerializer.SerializeToElement(response[1]).GetProperty("version").GetString()); } [TestMethod] - public async Task ReadLoopAsync_CompletesPendingRequestFromChunkedResponse() + public void JsonRpc_Disconnected_OldTransportGenerationDoesNotAffectActiveSession() { using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - var pendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - byte[] frame = CreateLspFrame("{\"jsonrpc\":\"2.0\",\"id\":42,\"result\":{\"label\":\"ok\"}}"); - object session = CreateTransportSession(1, process: null, new ChunkedReadStream(SplitBytes(frame, 6, 8, 5, 9)), Stream.Null); + object oldSession = CreateTransportSession(client, 1, process: null, Stream.Null, Stream.Null); + object newSession = CreateTransportSession(client, 2, process: null, Stream.Null, Stream.Null); - GetPendingRequests(session).TryAdd(42, pendingRequest); - - await InvokePrivateTaskAsync(client, "ReadLoopAsync", session).ConfigureAwait(false); - - JsonElement result = await pendingRequest.Task.ConfigureAwait(false); + SetActiveSession(client, newSession); + SetPrivateField(client, "_isReady", true); - Assert.AreEqual("ok", result.GetProperty("label").GetString()); - } + InvokePrivateMethod(client, "JsonRpc_Disconnected", + oldSession, + new JsonRpcDisconnectedEventArgs("old transport closed", DisconnectedReason.LocallyDisposed)); - [TestMethod] - public async Task ReadLoopAsync_OldTransportGenerationDoesNotFailActiveSessionRequests() - { - using var client = new LuaLanguageServerClient(@"C:\Workspace", "lua-language-server.exe", static () => new { }); - object oldSession = CreateTransportSession(1, process: null, new ChunkedReadStream(), Stream.Null); - object newSession = CreateTransportSession(2, process: null, new ChunkedReadStream(), Stream.Null); - var oldPendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - var newPendingRequest = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + Assert.IsTrue(client.IsReady); - GetPendingRequests(oldSession).TryAdd(41, oldPendingRequest); - GetPendingRequests(newSession).TryAdd(42, newPendingRequest); - SetActiveSession(client, newSession); + InvokePrivateMethod(client, "JsonRpc_Disconnected", + newSession, + new JsonRpcDisconnectedEventArgs("active transport closed", DisconnectedReason.LocallyDisposed)); - await InvokePrivateTaskAsync(client, "ReadLoopAsync", oldSession).ConfigureAwait(false); - - await Assert.ThrowsExceptionAsync(() => oldPendingRequest.Task).ConfigureAwait(false); - Assert.IsFalse(newPendingRequest.Task.IsCompleted); + Assert.IsFalse(client.IsReady); } private static Process StartDisposableProcess() @@ -243,7 +256,7 @@ private static void SetPrivateField(object instance, string fieldName, object? v field.SetValue(instance, value); } - private static object CreateTransportSession(long generation, Process? process, Stream inputStream, Stream outputStream) + private static object CreateTransportSession(LuaLanguageServerClient client, long generation, Process? process, Stream inputStream, Stream outputStream, bool startListening = false) { Type sessionType = typeof(LuaLanguageServerClient).GetNestedType("LuaLanguageServerTransportSession", BindingFlags.NonPublic) ?? throw new InvalidOperationException("Nested type 'LuaLanguageServerTransportSession' was not found."); @@ -255,7 +268,52 @@ private static object CreateTransportSession(long generation, Process? process, modifiers: null) ?? throw new InvalidOperationException("Lua transport session constructor was not found."); - return constructor.Invoke([generation, process, inputStream, outputStream]); + object session = constructor.Invoke([generation, process, inputStream, outputStream]); + object messageHandler = InvokePrivateStaticMethodWithReturn(typeof(LuaLanguageServerClient), "CreateMessageHandler", outputStream, inputStream); + object rpcTarget = CreateRpcTarget(client); + + SetSessionProperty(session, "MessageHandler", messageHandler); + SetSessionProperty(session, "RpcTarget", rpcTarget); + object jsonRpc = InvokePrivateMethodWithReturn(client, "CreateJsonRpc", session); + SetSessionProperty(session, "JsonRpc", jsonRpc); + SetSessionProperty(session, "RpcCompletionTask", GetPropertyValue(jsonRpc, "Completion")); + + if (startListening) + ((JsonRpc)jsonRpc).StartListening(); + + return session; + } + + private static object CreateRpcTarget(LuaLanguageServerClient client, long generation = 0) + { + Type targetType = typeof(LuaLanguageServerClient).GetNestedType("LuaLanguageServerClientRpcTarget", BindingFlags.NonPublic) + ?? throw new InvalidOperationException("Nested type 'LuaLanguageServerClientRpcTarget' was not found."); + + ConstructorInfo constructor = targetType.GetConstructor( + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, + binder: null, + [typeof(LuaLanguageServerClient), typeof(long)], + modifiers: null) + ?? throw new InvalidOperationException("Lua RPC target constructor was not found."); + + return constructor.Invoke([client, generation]); + } + + private static object GetPropertyValue(object instance, string propertyName) + { + PropertyInfo property = instance.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Property '{propertyName}' was not found."); + + return property.GetValue(instance) + ?? throw new InvalidOperationException($"Property '{propertyName}' returned null."); + } + + private static void SetSessionProperty(object session, string propertyName, object? value) + { + PropertyInfo property = session.GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Transport session property '{propertyName}' was not found."); + + property.SetValue(session, value); } private static void SetActiveSession(LuaLanguageServerClient client, object session) @@ -281,45 +339,65 @@ private static void InvokePrivateMethod(object instance, string methodName, para method.Invoke(instance, parameters); } - private static async Task InvokePrivateTaskAsync(object instance, string methodName, params object?[] parameters) + private static object InvokePrivateMethodWithReturn(object instance, string methodName, params object?[] parameters) { MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new InvalidOperationException($"Private method '{methodName}' was not found."); + return method.Invoke(instance, parameters) + ?? throw new InvalidOperationException($"Private method '{methodName}' returned null."); + } + + private static object InvokePrivateStaticMethodWithReturn(Type type, string methodName, params object?[] parameters) + { + MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Private static method '{methodName}' was not found."); + + return method.Invoke(obj: null, parameters) + ?? throw new InvalidOperationException($"Private static method '{methodName}' returned null."); + } + + private static async Task InvokePrivateTaskAsync(object instance, string methodName, params object?[] parameters) + { + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Method '{methodName}' was not found."); + Task task = (Task)(method.Invoke(instance, parameters) - ?? throw new InvalidOperationException($"Private method '{methodName}' returned null instead of a Task.")); + ?? throw new InvalidOperationException($"Method '{methodName}' returned null instead of a Task.")); await task.ConfigureAwait(false); } private static async Task InvokePrivateTaskAsync(object instance, string methodName, params object?[] parameters) { - MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic) - ?? throw new InvalidOperationException($"Private method '{methodName}' was not found."); + MethodInfo method = instance.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + ?? throw new InvalidOperationException($"Method '{methodName}' was not found."); Task task = (Task)(method.Invoke(instance, parameters) - ?? throw new InvalidOperationException($"Private method '{methodName}' returned null instead of a Task.")); + ?? throw new InvalidOperationException($"Method '{methodName}' returned null instead of a Task.")); return await task.ConfigureAwait(false); } - private static JsonElement CreateDiagnosticsParameters(string uri, string message) - => JsonSerializer.SerializeToElement(new - { + private static LuaInitializeResponse DeserializeInitializeResponse(string json) + => JsonSerializer.Deserialize(json) + ?? throw new InvalidOperationException("Failed to deserialize the Lua initialize response test payload."); + + private static LuaPublishDiagnosticsParams CreateDiagnosticsParameters(string uri, string message) + => new( uri, - diagnostics = new[] - { - new - { - message, - range = new - { - start = new { line = 0, character = 0 }, - end = new { line = 0, character = 1 } - } - } - } - }); + Version: null, + Diagnostics: + [ + new LuaDiagnosticPayload( + new LuaProtocolRangePayload( + new LuaProtocolNullablePosition(0, 0), + new LuaProtocolNullablePosition(0, 1)), + Severity: null, + Message: message, + Source: null, + Code: null) + ]); private static void CancelLifetime(LuaLanguageServerClient client) { @@ -329,54 +407,6 @@ private static void CancelLifetime(LuaLanguageServerClient client) ((CancellationTokenSource)field.GetValue(client)!).Cancel(); } - private static ConcurrentDictionary> GetPendingRequests(object session) - { - PropertyInfo property = session.GetType().GetProperty("PendingRequests", BindingFlags.Instance | BindingFlags.Public) - ?? throw new InvalidOperationException("Transport session property 'PendingRequests' was not found."); - - return (ConcurrentDictionary>)(property.GetValue(session) - ?? throw new InvalidOperationException("Transport session pending request map was null.")); - } - - private static byte[] CreateLspFrame(string json) - { - byte[] payload = Encoding.UTF8.GetBytes(json); - byte[] header = Encoding.ASCII.GetBytes($"Content-Length: {payload.Length}\r\n\r\n"); - byte[] frame = new byte[header.Length + payload.Length]; - - Buffer.BlockCopy(header, 0, frame, 0, header.Length); - Buffer.BlockCopy(payload, 0, frame, header.Length, payload.Length); - return frame; - } - - private static byte[][] SplitBytes(byte[] source, params int[] chunkLengths) - { - var chunks = new List(); - int offset = 0; - - for (int i = 0; i < chunkLengths.Length && offset < source.Length; i++) - { - int length = Math.Min(chunkLengths[i], source.Length - offset); - - if (length <= 0) - continue; - - byte[] chunk = new byte[length]; - Buffer.BlockCopy(source, offset, chunk, 0, length); - chunks.Add(chunk); - offset += length; - } - - if (offset < source.Length) - { - byte[] remainder = new byte[source.Length - offset]; - Buffer.BlockCopy(source, offset, remainder, 0, remainder.Length); - chunks.Add(remainder); - } - - return [.. chunks]; - } - private sealed class RecordingStream : Stream { private readonly MemoryStream _innerStream = new(); @@ -425,16 +455,13 @@ protected override void Dispose(bool disposing) } } - private sealed class ChunkedReadStream(params byte[][] chunks) : Stream + private sealed class PendingReadStream : Stream { - private readonly IReadOnlyList _chunks = chunks; - private int _chunkIndex; - private int _chunkOffset; - public override bool CanRead => true; public override bool CanSeek => false; public override bool CanWrite => false; public override long Length => throw new NotSupportedException(); + public override long Position { get => throw new NotSupportedException(); @@ -442,29 +469,18 @@ public override long Position } public override int Read(byte[] buffer, int offset, int count) - => ReadAsync(buffer.AsMemory(offset, count)).GetAwaiter().GetResult(); + => throw new NotSupportedException(); - public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); - - if (_chunkIndex >= _chunks.Count) - return ValueTask.FromResult(0); - - byte[] chunk = _chunks[_chunkIndex]; - int bytesAvailable = chunk.Length - _chunkOffset; - int bytesToCopy = Math.Min(buffer.Length, bytesAvailable); - - chunk.AsMemory(_chunkOffset, bytesToCopy).CopyTo(buffer); - _chunkOffset += bytesToCopy; - - if (_chunkOffset >= chunk.Length) + try { - _chunkIndex++; - _chunkOffset = 0; + await Task.Delay(Timeout.InfiniteTimeSpan, cancellationToken).ConfigureAwait(false); } + catch (OperationCanceledException) + { } - return ValueTask.FromResult(bytesToCopy); + return 0; } public override void Flush() @@ -479,4 +495,5 @@ public override void SetLength(long value) public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); } + } diff --git a/TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs index 311bc430b1..dcbe04dc3f 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerDiagnosticsParserTests.cs @@ -1,4 +1,3 @@ -using System.Text.Json; using TombIDE.ScriptingStudio.Services.LuaIntellisense; namespace TombLib.Test; @@ -46,22 +45,19 @@ public void TryParse_PreservesZeroWidthDiagnosticOnTrailingEmptyLineByAnchoringT Assert.AreEqual(publishedDiagnostics.Diagnostics[0].StartOffset + 1, publishedDiagnostics.Diagnostics[0].EndOffset); } - private static JsonElement CreateDiagnostics(int line, int startCharacter, int endLine, int endCharacter) - => JsonSerializer.SerializeToElement(new - { - version = 1, - diagnostics = new[] - { - new - { - severity = 1, - message = "Syntax error.", - range = new - { - start = new { line, character = startCharacter }, - end = new { line = endLine, character = endCharacter } - } - } - } - }); + private static LuaPublishDiagnosticsParams CreateDiagnostics(int line, int startCharacter, int endLine, int endCharacter) + => new( + Uri: null, + Version: 1, + Diagnostics: + [ + new LuaDiagnosticPayload( + new LuaProtocolRangePayload( + new LuaProtocolNullablePosition(line, startCharacter), + new LuaProtocolNullablePosition(endLine, endCharacter)), + 1, + "Syntax error.", + null, + null) + ]); } diff --git a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs index 8c4e90cf18..58392fda1a 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerIntellisenseProviderTests.cs @@ -1,3 +1,4 @@ +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Text.Json; using TombIDE.ScriptingStudio.Services.LuaIntellisense; @@ -9,6 +10,29 @@ namespace TombLib.Test; [TestClass] public class LuaLanguageServerIntellisenseProviderTests { + [TestMethod] + public async Task OpenDocument_SendsDidOpenPayloadWithLuaLanguageAndVersion() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(filePath, content); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 1, TimeSpan.FromSeconds(1))); + + JsonElement parameters = client.GetLastNotificationParameters("textDocument/didOpen"); + JsonElement textDocument = parameters.GetProperty("textDocument"); + + Assert.AreEqual(new Uri(filePath).AbsoluteUri, textDocument.GetProperty("uri").GetString()); + Assert.AreEqual("lua", textDocument.GetProperty("languageId").GetString()); + Assert.AreEqual(1, textDocument.GetProperty("version").GetInt32()); + Assert.AreEqual(content, textDocument.GetProperty("text").GetString()); + } + [TestMethod] public async Task GetCompletionItemsAsync_ResolvesCompletionItemDetailsWhenServerSupportsResolve() { @@ -105,6 +129,30 @@ public async Task GetCompletionItemsAsync_ResolvePreservesOriginalInsertionMetad Assert.AreEqual("Spawn docs.", resolvedItem.Description); } + [TestMethod] + public async Task GetCompletionItemsAsync_WithTriggerCharacter_PassesCompletionContext() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + CompletionResponse = JsonSerializer.SerializeToElement(new { items = Array.Empty() }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + IReadOnlyList items = await provider.GetCompletionItemsAsync(filePath, "spawn.", 0, 6, '.'); + JsonElement parameters = client.GetLastRequestParameters("textDocument/completion"); + + Assert.AreEqual(0, items.Count); + Assert.AreEqual(new Uri(filePath).AbsoluteUri, parameters.GetProperty("textDocument").GetProperty("uri").GetString()); + Assert.AreEqual(0, parameters.GetProperty("position").GetProperty("line").GetInt32()); + Assert.AreEqual(6, parameters.GetProperty("position").GetProperty("character").GetInt32()); + Assert.AreEqual(2, parameters.GetProperty("context").GetProperty("triggerKind").GetInt32()); + Assert.AreEqual(".", parameters.GetProperty("context").GetProperty("triggerCharacter").GetString()); + } + [TestMethod] public async Task FormatDocumentAsync_ReturnsFormattingEditsAndPassesEditorOptions() { @@ -148,6 +196,77 @@ public async Task FormatDocumentAsync_ReturnsFormattingEditsAndPassesEditorOptio client.GetSentMethodNames()); } + [TestMethod] + public async Task RenameSymbolAsync_ReturnsWorkspaceEditFromTypedResponse() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = target\r\nprint(target)"; + string secondPath = Path.GetFullPath(@"C:\Workspace\Scripts\other.lua"); + + using var client = new FakeLuaLanguageServerClient + { + SupportsRename = true, + RenameResponse = JsonSerializer.SerializeToElement(new + { + changes = new Dictionary + { + [new Uri(filePath).AbsoluteUri] = + [ + new + { + range = new + { + start = new { line = 0, character = 14 }, + end = new { line = 0, character = 20 } + }, + newText = "renamed" + } + ] + }, + documentChanges = new object[] + { + new + { + textDocument = new { uri = new Uri(secondPath).AbsoluteUri }, + edits = new object[] + { + new + { + range = new + { + start = new { line = 1, character = 6 }, + end = new { line = 1, character = 12 } + }, + newText = "renamed" + } + } + } + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + LuaWorkspaceEdit? workspaceEdit = await provider.RenameSymbolAsync(filePath, content, 0, 14, "renamed"); + + Assert.IsNotNull(workspaceEdit); + Assert.AreEqual(2, workspaceEdit.DocumentEdits.Count); + Assert.AreEqual(filePath, workspaceEdit.DocumentEdits[0].FilePath); + Assert.AreEqual("renamed", workspaceEdit.DocumentEdits[0].TextEdits[0].NewText); + Assert.AreEqual(secondPath, workspaceEdit.DocumentEdits[1].FilePath); + Assert.AreEqual("renamed", workspaceEdit.DocumentEdits[1].TextEdits[0].NewText); + + JsonElement parameters = client.GetLastRequestParameters("textDocument/rename"); + + Assert.AreEqual(new Uri(filePath).AbsoluteUri, parameters.GetProperty("textDocument").GetProperty("uri").GetString()); + Assert.AreEqual("renamed", parameters.GetProperty("newName").GetString()); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/rename" }, + client.GetSentMethodNames()); + } + [TestMethod] public async Task FormatDocumentAsync_ReturnsEmptyWhenFormattingIsUnsupported() { @@ -239,6 +358,175 @@ public async Task GetHoverAsync_RaisesTransientAndPermanentStartupFailuresOnceEa Assert.AreEqual(3, client.StartCallCount); } + [TestMethod] + public async Task GetHoverAsync_ReturnsParsedHoverInfoFromTypedResponse() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + HoverResponse = JsonSerializer.SerializeToElement(new + { + contents = new + { + kind = "markdown", + value = "Hover docs." + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + LuaHoverInfo? hover = await provider.GetHoverAsync(filePath, content, 0, 0); + + Assert.IsNotNull(hover); + Assert.AreEqual("Hover docs.", hover.Content); + Assert.IsTrue(hover.IsMarkdown); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/hover" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task GetDefinitionAsync_ReturnsParsedDefinitionLocationFromTypedResponse() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + string targetPath = Path.GetFullPath(@"C:\Workspace\Scripts\definitions.lua"); + + using var client = new FakeLuaLanguageServerClient + { + DefinitionResponse = JsonSerializer.SerializeToElement(new + { + uri = new Uri(targetPath).AbsoluteUri, + range = new + { + start = new { line = 4, character = 2 }, + end = new { line = 4, character = 7 } + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + LuaDefinitionLocation? definition = await provider.GetDefinitionAsync(filePath, "value", 0, 0); + + Assert.IsNotNull(definition); + Assert.AreEqual(targetPath, definition.FilePath); + Assert.AreEqual(5, definition.LineNumber); + Assert.AreEqual(3, definition.ColumnNumber); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/definition" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task GetReferencesAsync_ReturnsParsedReferenceLocationsFromTypedResponse() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + string targetPath = Path.GetFullPath(@"C:\Workspace\Scripts\references.lua"); + + using var client = new FakeLuaLanguageServerClient + { + ReferencesResponse = JsonSerializer.SerializeToElement(new object[] + { + new + { + uri = new Uri(targetPath).AbsoluteUri, + range = new + { + start = new { line = 2, character = 4 }, + end = new { line = 2, character = 9 } + } + }, + new + { + uri = "https://example.com/not-a-file.lua", + range = new + { + start = new { line = 0, character = 0 }, + end = new { line = 0, character = 1 } + } + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + IReadOnlyList references = await provider.GetReferencesAsync(filePath, "value", 0, 0); + + Assert.AreEqual(1, references.Count); + Assert.AreEqual(targetPath, references[0].FilePath); + Assert.AreEqual(3, references[0].Range.StartLineNumber); + Assert.AreEqual(5, references[0].Range.StartColumnNumber); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/references" }, + client.GetSentMethodNames()); + } + + [TestMethod] + public async Task GetSignatureHelpAsync_ReturnsParsedSignatureHelpFromTypedResponse() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient + { + SignatureHelpResponse = JsonSerializer.SerializeToElement(new + { + activeSignature = 0, + activeParameter = 1, + signatures = new[] + { + new + { + label = "spawn(room, objectName)", + documentation = new + { + kind = "markdown", + value = "Spawns an object." + }, + parameters = new object[] + { + new + { + label = new[] { 6, 10 }, + documentation = "Room id." + }, + new + { + label = new[] { 12, 22 }, + documentation = "Object name." + } + } + } + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + LuaSignatureInfo? signature = await provider.GetSignatureHelpAsync(filePath, "spawn(", 0, 6); + + Assert.IsNotNull(signature); + Assert.AreEqual("spawn(room, objectName)", signature.Label); + Assert.AreEqual("Spawns an object.", signature.Documentation); + Assert.AreEqual(1, signature.ActiveParameter); + Assert.AreEqual(2, signature.Parameters.Count); + Assert.AreEqual("objectName", signature.Parameters[1].Label); + Assert.AreEqual("Object name.", signature.Parameters[1].Documentation); + + CollectionAssert.AreEqual( + new[] { "textDocument/didOpen", "textDocument/signatureHelp" }, + client.GetSentMethodNames()); + } + [TestMethod] public async Task RenameDocument_MovesDiagnosticsAndSemanticTokensToNewPath() { @@ -538,6 +826,63 @@ public async Task GetHoverAsync_ReplaysTrackedDocumentsAfterLanguageServerRestar Assert.AreEqual(2, client.StartCallCount); } + [TestMethod] + public async Task GetHoverAsync_ReplaysUntouchedTrackedDocumentsAfterFailedRestartRetry() + { + const string workspaceRoot = @"C:\Workspace"; + const string firstFilePath = @"C:\Workspace\Scripts\first.lua"; + const string secondFilePath = @"C:\Workspace\Scripts\second.lua"; + const string firstContent = "local first = 1"; + const string secondContent = "local second = 2"; + + using var client = new FakeLuaLanguageServerClient + { + HoverResponse = JsonSerializer.SerializeToElement(new + { + contents = new + { + kind = "markdown", + value = "Hover docs." + } + }) + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(firstFilePath, firstContent); + provider.OpenDocument(secondFilePath, secondContent); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 2, TimeSpan.FromSeconds(1))); + Assert.AreEqual(1, client.StartCallCount); + + client.IsReady = false; + client.StartResult = false; + + LuaHoverInfo? failedHover = await provider.GetHoverAsync(firstFilePath, firstContent, 0, 0); + + Assert.IsNull(failedHover); + Assert.AreEqual(2, client.StartCallCount); + + client.StartResult = true; + + LuaHoverInfo? recoveredHover = await provider.GetHoverAsync(firstFilePath, firstContent, 0, 0); + + Assert.IsNotNull(recoveredHover); + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 4, TimeSpan.FromSeconds(1))); + Assert.AreEqual(3, client.StartCallCount); + + CollectionAssert.AreEqual( + new[] + { + "textDocument/didOpen", + "textDocument/didOpen", + "textDocument/didOpen", + "textDocument/didOpen", + "textDocument/hover" + }, + client.GetSentMethodNames()); + } + [TestMethod] public async Task DiagnosticsPublished_IgnoresVersionMismatchAndStoresMatchingVersion() { @@ -680,6 +1025,25 @@ public async Task CloseDocument_WaitsForQueuedOpenNotificationToFinish() client.GetSentMethodNames()); } + [TestMethod] + public async Task CloseDocument_SendsDidClosePayloadWithDocumentUri() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + + using var client = new FakeLuaLanguageServerClient(); + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(filePath, "local value = 1"); + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didOpen", 1, TimeSpan.FromSeconds(1))); + + provider.CloseDocument(filePath); + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/didClose", 1, TimeSpan.FromSeconds(1))); + + JsonElement parameters = client.GetLastNotificationParameters("textDocument/didClose"); + Assert.AreEqual(new Uri(filePath).AbsoluteUri, parameters.GetProperty("textDocument").GetProperty("uri").GetString()); + } + [TestMethod] public async Task GetHoverAsync_RetriesWorkspaceWatcherStartAfterWorkspaceDirectoryAppears() { @@ -785,6 +1149,30 @@ public async Task SemanticTokensRefreshRequested_RefreshesTrackedDocuments() client.GetSentMethodNames()); } + [TestMethod] + public async Task OpenDocument_SemanticTokensFullRequest_OmitsPreviousResultId() + { + const string workspaceRoot = @"C:\Workspace"; + const string filePath = @"C:\Workspace\Scripts\test.lua"; + const string content = "local value = 1"; + + using var client = new FakeLuaLanguageServerClient + { + SemanticTokenTypes = ["variable"] + }; + + using var provider = new LuaLanguageServerIntellisenseProvider(workspaceRoot, client); + + provider.OpenDocument(filePath, content); + + Assert.IsTrue(await client.WaitForMethodCountAsync("textDocument/semanticTokens/full", 1, TimeSpan.FromSeconds(1))); + + JsonElement parameters = client.GetLastRequestParameters("textDocument/semanticTokens/full"); + + Assert.AreEqual(new Uri(filePath).AbsoluteUri, parameters.GetProperty("textDocument").GetProperty("uri").GetString()); + Assert.IsFalse(parameters.TryGetProperty("previousResultId", out _)); + } + [TestMethod] public async Task SemanticTokensRefreshRequested_FallsBackToFullRefreshAfterInvalidDelta() { @@ -857,25 +1245,20 @@ public async Task SemanticTokensRefreshRequested_FallsBackToFullRefreshAfterInva client.GetSentMethodNames()); } - private static JsonElement CreateDiagnostics(string filePath, int version, int startCharacter, int endCharacter, string message) - => JsonSerializer.SerializeToElement(new - { - uri = new Uri(filePath).AbsoluteUri, + private static LuaPublishDiagnosticsParams CreateDiagnostics(string filePath, int version, int startCharacter, int endCharacter, string message) + => new( + new Uri(filePath).AbsoluteUri, version, - diagnostics = new[] - { - new - { - severity = 2, + [ + new LuaDiagnosticPayload( + new LuaProtocolRangePayload( + new LuaProtocolNullablePosition(0, startCharacter), + new LuaProtocolNullablePosition(0, endCharacter)), + 2, message, - range = new - { - start = new { line = 0, character = startCharacter }, - end = new { line = 0, character = endCharacter } - } - } - } - }); + null, + null) + ]); private static LuaWorkspaceFileWatcher? GetWorkspaceWatcher(LuaLanguageServerIntellisenseProvider provider) { @@ -913,8 +1296,12 @@ private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient public bool StartResult { get; set; } = true; public JsonElement CompletionResponse { get; set; } public JsonElement CompletionResolveResponse { get; set; } + public JsonElement DefinitionResponse { get; set; } public JsonElement FormattingResponse { get; set; } public JsonElement HoverResponse { get; set; } + public JsonElement ReferencesResponse { get; set; } + public JsonElement RenameResponse { get; set; } + public JsonElement SignatureHelpResponse { get; set; } public LuaTextDocumentSyncKind TextDocumentSyncKind { get; set; } = LuaTextDocumentSyncKind.Incremental; public IReadOnlyList SemanticTokenTypes { get; set; } = []; public IReadOnlyList SemanticTokenModifiers { get; set; } = []; @@ -930,7 +1317,7 @@ private sealed class FakeLuaLanguageServerClient : ILuaLanguageServerClient public bool ThrowIOExceptionOnNextDidChange { get; set; } public List StartCancellationTokenCanBeCanceled { get; } = []; - public event Action? DiagnosticsPublished; + public event Action? DiagnosticsPublished; public event Action? SemanticTokensRefreshRequested; @@ -984,41 +1371,46 @@ public Task SendNotificationAsync(string method, object parameters, Cancellation return Task.CompletedTask; } - public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) + public Task SendRequestAsync(string method, object parameters, CancellationToken cancellationToken) { - lock (_syncRoot) - { - _sentMethodNames.Add(method); - _sentRequests.Add((method, JsonSerializer.SerializeToElement(parameters))); - } + RecordRequest(method, parameters); if (method == "textDocument/hover") { if (TimedOutHoverRequestsRemaining > 0) { TimedOutHoverRequestsRemaining--; - return WaitForCancellationAsync(cancellationToken); + return WaitForCancellationAsync(cancellationToken); } if (HoverResponse.ValueKind != JsonValueKind.Undefined) - return Task.FromResult(HoverResponse); + return DeserializeResponseAsync(HoverResponse); } if (method == "textDocument/completion" && CompletionResponse.ValueKind != JsonValueKind.Undefined) - return Task.FromResult(CompletionResponse); + return DeserializeResponseAsync(CompletionResponse); if (method == "completionItem/resolve" && CompletionResolveResponse.ValueKind != JsonValueKind.Undefined) - return Task.FromResult(CompletionResolveResponse); + return DeserializeResponseAsync(CompletionResolveResponse); + + if (method == "textDocument/definition" && DefinitionResponse.ValueKind != JsonValueKind.Undefined) + return DeserializeResponseAsync(DefinitionResponse); + + if (method == "textDocument/references" && ReferencesResponse.ValueKind != JsonValueKind.Undefined) + return DeserializeResponseAsync(ReferencesResponse); + + if (method == "textDocument/rename" && RenameResponse.ValueKind != JsonValueKind.Undefined) + return DeserializeResponseAsync(RenameResponse); if (method == "textDocument/formatting" && FormattingResponse.ValueKind != JsonValueKind.Undefined) - return Task.FromResult(FormattingResponse); + return DeserializeResponseAsync(FormattingResponse); if (method == "textDocument/semanticTokens/full/delta") { if (_semanticTokensDeltaResponses.Count > 0) - return Task.FromResult(_semanticTokensDeltaResponses.Dequeue()); + return DeserializeResponseAsync(_semanticTokensDeltaResponses.Dequeue()); - return Task.FromResult(JsonSerializer.SerializeToElement(new + return DeserializeResponseAsync(JsonSerializer.SerializeToElement(new { edits = Array.Empty(), resultId = "tokens-delta" @@ -1028,16 +1420,22 @@ public Task SendRequestAsync(string method, object parameters, Canc if (method == "textDocument/semanticTokens/full") { if (_semanticTokensFullResponses.Count > 0) - return Task.FromResult(_semanticTokensFullResponses.Dequeue()); + return DeserializeResponseAsync(_semanticTokensFullResponses.Dequeue()); - return Task.FromResult(JsonSerializer.SerializeToElement(new + return DeserializeResponseAsync(JsonSerializer.SerializeToElement(new { data = new[] { 0, 6, 5, 0, 0 }, resultId = "tokens-1" })); } - return Task.FromResult(JsonSerializer.SerializeToElement(new { })); + if (method == "textDocument/signatureHelp" && SignatureHelpResponse.ValueKind != JsonValueKind.Undefined) + return DeserializeResponseAsync(SignatureHelpResponse); + + if (typeof(TResult) == typeof(JsonElement)) + return Task.FromResult((TResult)(object)JsonSerializer.SerializeToElement(new { })); + + return Task.FromResult(CreateDefaultResponse()); } public string[] GetSentMethodNames() @@ -1108,7 +1506,7 @@ public async Task WaitForMethodCountAsync(string method, int expectedCount return GetSentMethodCount(method) >= expectedCount; } - public void PublishDiagnostics(JsonElement parameters) + public void PublishDiagnostics(LuaPublishDiagnosticsParams parameters) => DiagnosticsPublished?.Invoke(parameters); public void PublishSemanticTokensRefreshRequested() @@ -1136,12 +1534,43 @@ private int GetSentMethodCount(string method) return count; } + private void RecordRequest(string method, object parameters) + { + lock (_syncRoot) + { + _sentMethodNames.Add(method); + _sentRequests.Add((method, JsonSerializer.SerializeToElement(parameters))); + } + } + + private static Task DeserializeResponseAsync(JsonElement response) + { + if (typeof(TResult) == typeof(JsonElement)) + return Task.FromResult((TResult)(object)response); + + return Task.FromResult(DeserializeResponse(response)); + } + + [return: MaybeNull] + private static TResult DeserializeResponse(JsonElement response) + => JsonSerializer.Deserialize(response.GetRawText()); + + [return: MaybeNull] + private static TResult CreateDefaultResponse() + => default; + private static async Task WaitForCancellationAsync(CancellationToken cancellationToken) { await Task.Delay(Timeout.InfiniteTimeSpan, cancellationToken).ConfigureAwait(false); return default; } + private static async Task WaitForCancellationAsync(CancellationToken cancellationToken) + { + await Task.Delay(Timeout.InfiniteTimeSpan, cancellationToken).ConfigureAwait(false); + return CreateDefaultResponse(); + } + public void Dispose() { } } diff --git a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs index 166d733dc3..1d38cf07db 100644 --- a/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs +++ b/TombLib/TombLib.Test/LuaLanguageServerResponseParserTests.cs @@ -10,8 +10,8 @@ public class LuaLanguageServerResponseParserTests [TestMethod] public void ParseCompletionItem_AddsLocalAndUpvaluePriorityBonuses() { - JsonElement baselineElement = CreateCompletionItem("baseline", kind: 6, detail: "variable", documentation: "plain text"); - JsonElement boostedElement = CreateCompletionItem("boosted", kind: 6, detail: "local variable", documentation: "upvalue"); + LuaCompletionItemPayload baselineElement = CreateCompletionItem("baseline", kind: 6, detail: "variable", documentation: "plain text"); + LuaCompletionItemPayload boostedElement = CreateCompletionItem("boosted", kind: 6, detail: "local variable", documentation: "upvalue"); LuaCompletionItem? baselineItem = LuaLanguageServerResponseParser.ParseCompletionItem(baselineElement, 0); LuaCompletionItem? boostedItem = LuaLanguageServerResponseParser.ParseCompletionItem(boostedElement, 0); @@ -24,7 +24,7 @@ public void ParseCompletionItem_AddsLocalAndUpvaluePriorityBonuses() [TestMethod] public void ParseCompletionItem_UsesParameterIconWhenDetailContainsParameter() { - JsonElement itemElement = CreateCompletionItem("arg", kind: 6, detail: "parameter", documentation: null); + LuaCompletionItemPayload itemElement = CreateCompletionItem("arg", kind: 6, detail: "parameter", documentation: null); LuaCompletionItem? item = LuaLanguageServerResponseParser.ParseCompletionItem(itemElement, 0); @@ -35,7 +35,7 @@ public void ParseCompletionItem_UsesParameterIconWhenDetailContainsParameter() [TestMethod] public void ParseCompletionItem_ParsesTextEditRange() { - JsonElement itemElement = JsonSerializer.SerializeToElement(new + LuaCompletionItemPayload itemElement = DeserializeCompletionItemPayload(new { label = "print", kind = 3, @@ -63,7 +63,7 @@ public void ParseCompletionItem_ParsesTextEditRange() [TestMethod] public void ParseCompletionItem_ParsesInsertReplaceEditRanges() { - JsonElement itemElement = JsonSerializer.SerializeToElement(new + LuaCompletionItemPayload itemElement = DeserializeCompletionItemPayload(new { label = "print", kind = 3, @@ -97,7 +97,7 @@ public void ParseCompletionItem_ParsesInsertReplaceEditRanges() [TestMethod] public void ParseCompletionItem_StripsSnippetAndPreservesFinalCaretOffset() { - JsonElement itemElement = JsonSerializer.SerializeToElement(new + LuaCompletionItemPayload itemElement = DeserializeCompletionItemPayload(new { label = "if", kind = 15, @@ -115,7 +115,7 @@ public void ParseCompletionItem_StripsSnippetAndPreservesFinalCaretOffset() [TestMethod] public void ParseCompletionItem_PreservesUnknownSnippetPlaceholdersAndPlacesCaretAfterDefaultText() { - JsonElement itemElement = JsonSerializer.SerializeToElement(new + LuaCompletionItemPayload itemElement = DeserializeCompletionItemPayload(new { label = "call", kind = 3, @@ -154,7 +154,7 @@ public void ParseDefinitionLocation_UsesFirstEntryFromMultiLocationResponse() string secondPath = Path.GetFullPath(@"C:\Workspace\Scripts\second.lua"); LuaDefinitionLocation? location = LuaLanguageServerResponseParser.ParseDefinitionLocation( - JsonSerializer.SerializeToElement(new object[] + DeserializeDefinitionResponse(new object[] { new { @@ -188,7 +188,7 @@ public void ParseDefinitionLocation_UsesTargetSelectionRangeFromLocationLink() string targetPath = Path.GetFullPath(@"C:\Workspace\Scripts\linked.lua"); LuaDefinitionLocation? location = LuaLanguageServerResponseParser.ParseDefinitionLocation( - JsonSerializer.SerializeToElement(new + DeserializeDefinitionResponse(new { targetUri = new Uri(targetPath).AbsoluteUri, targetSelectionRange = new @@ -210,7 +210,7 @@ public void ParseReferenceLocations_ParsesFileReferenceRanges() string targetPath = Path.GetFullPath(@"C:\Workspace\Scripts\references.lua"); IReadOnlyList locations = LuaLanguageServerResponseParser.ParseReferenceLocations( - JsonSerializer.SerializeToElement(new object[] + DeserializeReferenceResponse(new object[] { new { @@ -247,7 +247,7 @@ public void ParseWorkspaceEdit_MergesChangeMapAndDocumentChanges() string secondPath = Path.GetFullPath(@"C:\Workspace\Scripts\second.lua"); LuaWorkspaceEdit? workspaceEdit = LuaLanguageServerResponseParser.ParseWorkspaceEdit( - JsonSerializer.SerializeToElement(new + DeserializeWorkspaceEditResponse(new { changes = new Dictionary { @@ -297,7 +297,7 @@ [new Uri(firstPath).AbsoluteUri] = public void ParseDocumentFormattingEdits_ParsesFormattingTextEdits() { IReadOnlyList textEdits = LuaLanguageServerResponseParser.ParseDocumentFormattingEdits( - JsonSerializer.SerializeToElement(new object[] + DeserializeTextEdits(new object[] { new { @@ -331,7 +331,7 @@ public void ParseDocumentFormattingEdits_ParsesFormattingTextEdits() public void ParseSignatureHelp_UsesParameterLabelOffsetsAndActiveParameter() { LuaSignatureInfo? signatureInfo = LuaLanguageServerResponseParser.ParseSignatureHelp( - JsonSerializer.SerializeToElement(new + DeserializeSignatureHelpResponse(new { activeSignature = 0, activeParameter = 1, @@ -375,7 +375,7 @@ public void ParseSignatureHelp_UsesParameterLabelOffsetsAndActiveParameter() public void ParseSignatureHelp_UsesSignatureLevelActiveParameterWhenResponseOmitsIt() { LuaSignatureInfo? signatureInfo = LuaLanguageServerResponseParser.ParseSignatureHelp( - JsonSerializer.SerializeToElement(new + DeserializeSignatureHelpResponse(new { signatures = new[] { @@ -397,8 +397,8 @@ public void ParseSignatureHelp_UsesSignatureLevelActiveParameterWhenResponseOmit Assert.AreEqual("y", signatureInfo.Parameters[1].Label); } - private static JsonElement CreateCompletionItem(string label, int kind, string? detail, string? documentation, string? insertText = null) - => JsonSerializer.SerializeToElement(new Dictionary + private static LuaCompletionItemPayload CreateCompletionItem(string label, int kind, string? detail, string? documentation, string? insertText = null) + => DeserializeCompletionItemPayload(new Dictionary { ["label"] = label, ["kind"] = kind, @@ -407,4 +407,23 @@ private static JsonElement CreateCompletionItem(string label, int kind, string? ["insertText"] = insertText ?? label, ["filterText"] = label }); + + private static LuaCompletionItemPayload DeserializeCompletionItemPayload(object payload) + => JsonSerializer.Deserialize(JsonSerializer.Serialize(payload)) + ?? throw new InvalidOperationException("Failed to deserialize the Lua completion-item test payload."); + + private static LuaSignatureHelpResponse? DeserializeSignatureHelpResponse(object payload) + => JsonSerializer.Deserialize(JsonSerializer.Serialize(payload)); + + private static LuaWorkspaceEditResponse? DeserializeWorkspaceEditResponse(object payload) + => JsonSerializer.Deserialize(JsonSerializer.Serialize(payload)); + + private static LuaTextEditPayload[]? DeserializeTextEdits(object payload) + => JsonSerializer.Deserialize(JsonSerializer.Serialize(payload)); + + private static LuaDefinitionResponse DeserializeDefinitionResponse(object payload) + => JsonSerializer.Deserialize(JsonSerializer.Serialize(payload)); + + private static LuaReferenceResponse[]? DeserializeReferenceResponse(object payload) + => JsonSerializer.Deserialize(JsonSerializer.Serialize(payload)); } diff --git a/TombLib/TombLib.Test/TombLib.Test.csproj b/TombLib/TombLib.Test/TombLib.Test.csproj index 51bf59557b..81daa927ca 100644 --- a/TombLib/TombLib.Test/TombLib.Test.csproj +++ b/TombLib/TombLib.Test/TombLib.Test.csproj @@ -18,6 +18,7 @@ +

3MgowfH2` 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

1jn!al-#W&nO8OE0y0n=E6p=tE%yS%eAc%B!eA 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Ónu^QlF@kyA=# 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