From 28a6e95d2bff25242087f675a867eb067e264997 Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Mon, 18 Aug 2025 19:56:25 +1000 Subject: [PATCH] display completions --- .../Features/Analysis/RoslynAnalysis.cs | 28 +++++++++++++++++++ src/SharpIDE.Godot/SharpIdeCodeEdit.cs | 26 ++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs b/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs index ea04a6f..573f973 100644 --- a/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs +++ b/src/SharpIDE.Application/Features/Analysis/RoslynAnalysis.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeRefactorings; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.MSBuild; @@ -162,6 +163,16 @@ public static class RoslynAnalysis return result; } + public static async Task GetCodeCompletionsForDocumentAtPosition(SharpIdeFile fileModel, LinePosition linePosition) + { + await _solutionLoadedTcs.Task; + var project = _workspace!.CurrentSolution.Projects.Single(s => s.FilePath == ((IChildSharpIdeNode)fileModel).GetNearestProjectNode()!.FilePath); + var document = project.Documents.Single(s => s.FilePath == fileModel.Path); + Guard.Against.Null(document, nameof(document)); + var completions = await GetCompletionsAsync(document, linePosition).ConfigureAwait(false); + return completions; + } + public static async Task> GetCodeFixesForDocumentAtPosition(SharpIdeFile fileModel, LinePosition linePosition) { var cancellationToken = CancellationToken.None; @@ -241,4 +252,21 @@ public static class RoslynAnalysis return codeActions.ToImmutableArray(); } + + private static async Task GetCompletionsAsync(Document document, LinePosition linePosition) + { + var cancellationToken = CancellationToken.None; + var completionService = CompletionService.GetService(document); + if (completionService is null) throw new InvalidOperationException("Completion service is not available for the document."); + + var sourceText = await document.GetTextAsync(cancellationToken); + var position = sourceText.Lines.GetPosition(linePosition); + var completions = await completionService.GetCompletionsAsync(document, position, cancellationToken: cancellationToken); + + // foreach (var item in completions.ItemsList) + // { + // Console.WriteLine($"Completion: {item.DisplayText}"); + // } + return completions; + } } diff --git a/src/SharpIDE.Godot/SharpIdeCodeEdit.cs b/src/SharpIDE.Godot/SharpIdeCodeEdit.cs index 62ae8dd..f684f8c 100644 --- a/src/SharpIDE.Godot/SharpIdeCodeEdit.cs +++ b/src/SharpIDE.Godot/SharpIdeCodeEdit.cs @@ -4,7 +4,6 @@ using System.Collections.Immutable; using System.IO; using System.Linq; using Godot; -using Microsoft.Build.Utilities; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Classification; using Microsoft.CodeAnalysis.Text; @@ -176,7 +175,32 @@ public partial class SharpIdeCodeEdit : CodeEdit private void OnCodeCompletionRequested() { var (caretLine, caretColumn) = GetCaretPosition(); + GD.Print($"Code completion requested at line {caretLine}, column {caretColumn}"); + _ = Task.Run(async () => + { + try + { + var linePos = new LinePosition(caretLine, caretColumn); + + var completions = await RoslynAnalysis.GetCodeCompletionsForDocumentAtPosition(_currentFile, linePos); + Callable.From(() => + { + foreach (var completionItem in completions.ItemsList) + { + AddCodeCompletionOption(CodeCompletionKind.Class, completionItem.DisplayText, completionItem.DisplayText); + } + // partially working - displays menu only when caret is what CodeEdit determines as valid + UpdateCodeCompletionOptions(true); + //RequestCodeCompletion(true); + GD.Print($"Found {completions.ItemsList.Count} completions, displaying menu"); + }).CallDeferred(); + } + catch (Exception ex) + { + GD.Print(ex); + } + }); } private (int, int) GetCaretPosition()