From c6d3e424fe334131612fc53664f7b4c2ed0f9994 Mon Sep 17 00:00:00 2001 From: Matt Parker <61717342+MattParkerDev@users.noreply.github.com> Date: Mon, 27 Oct 2025 18:40:35 +1000 Subject: [PATCH] extract partial --- .../Features/CodeEditor/SharpIdeCodeEdit.cs | 82 ---------------- .../SharpIdeCodeEdit_SymbolLookup.cs | 95 +++++++++++++++++++ 2 files changed, 95 insertions(+), 82 deletions(-) create mode 100644 src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolLookup.cs diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs index 7de7b97..e9230e4 100644 --- a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs +++ b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit.cs @@ -20,7 +20,6 @@ using SharpIDE.Godot.Features.Problems; using SharpIDE.Godot.Features.SymbolLookup; using SharpIDE.RazorAccess; using Task = System.Threading.Tasks.Task; -using Timer = Godot.Timer; namespace SharpIDE.Godot.Features.CodeEditor; @@ -156,87 +155,6 @@ public partial class SharpIdeCodeEdit : CodeEdit GD.Print($"Breakpoint {(breakpointAdded ? "added" : "removed")} at line {lineForDebugger}"); } - private readonly PackedScene _symbolUsagePopupScene = ResourceLoader.Load("uid://dq7ss2ha5rk44"); - private void OnSymbolLookup(string symbolString, long line, long column) - { - GD.Print($"Symbol lookup requested: {symbolString} at line {line}, column {column}"); - _ = Task.GodotRun(async () => - { - var (symbol, linePositionSpan, semanticInfo) = await _roslynAnalysis.LookupSymbolSemanticInfo(_currentFile, new LinePosition((int)line, (int)column)); - if (symbol is null) return; - - //var locations = symbol.Locations; - - if (semanticInfo is null) return; - if (semanticInfo.Value.DeclaredSymbol is not null) - { - GD.Print($"Symbol is declared here: {symbolString}"); - // TODO: Lookup references instead - var references = await _roslynAnalysis.FindAllSymbolReferences(semanticInfo.Value.DeclaredSymbol); - if (references.Length is 1) - { - var reference = references[0]; - var locations = reference.LocationsArray; - if (locations.Length is 1) - { - // Lets jump to the definition - var referenceLocation = locations[0]; - - var referenceLineSpan = referenceLocation.Location.GetMappedLineSpan(); - var sharpIdeFile = Solution!.AllFiles.SingleOrDefault(f => f.Path == referenceLineSpan.Path); - if (sharpIdeFile is null) - { - GD.Print($"Reference file not found in solution: {referenceLineSpan.Path}"); - return; - } - await GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelAsync(sharpIdeFile, new SharpIdeFileLinePosition(referenceLineSpan.Span.Start.Line, referenceLineSpan.Span.Start.Character)); - } - else - { - // Show popup to select which reference to go to - var scene = _symbolUsagePopupScene.Instantiate(); - var locationsAndFiles = locations.Select(s => - { - var lineSpan = s.Location.GetMappedLineSpan(); - var file = Solution!.AllFiles.SingleOrDefault(f => f.Path == lineSpan.Path); - return (s, file); - }).Where(t => t.file is not null).ToImmutableArray(); - scene.Locations = locations; - scene.LocationsAndFiles = locationsAndFiles!; - scene.Symbol = semanticInfo.Value.DeclaredSymbol; - await this.InvokeAsync(() => - { - AddChild(scene); - scene.PopupCenteredClamped(); - }); - } - } - } - else if (semanticInfo.Value.ReferencedSymbols.Length is not 0) - { - var referencedSymbol = semanticInfo.Value.ReferencedSymbols.Single(); // Handle more than one when I run into it - var locations = referencedSymbol.Locations; - if (locations.Length is 1) - { - // Lets jump to the definition - var definitionLocation = locations[0]; - var definitionLineSpan = definitionLocation.GetMappedLineSpan(); - var sharpIdeFile = Solution!.AllFiles.SingleOrDefault(f => f.Path == definitionLineSpan.Path); - if (sharpIdeFile is null) - { - GD.Print($"Definition file not found in solution: {definitionLineSpan.Path}"); - return; - } - await GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelAsync(sharpIdeFile, new SharpIdeFileLinePosition(definitionLineSpan.Span.Start.Line, definitionLineSpan.Span.Start.Character)); - } - else - { - // TODO: Show a popup to select which definition location to go to - } - } - }); - } - private void OnSymbolValidate(string symbol) { GD.Print($"Symbol validating: {symbol}"); diff --git a/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolLookup.cs b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolLookup.cs new file mode 100644 index 0000000..044b7f6 --- /dev/null +++ b/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_SymbolLookup.cs @@ -0,0 +1,95 @@ +using System.Collections.Immutable; +using Godot; +using Microsoft.CodeAnalysis.Text; +using SharpIDE.Application.Features.Analysis; +using SharpIDE.Godot.Features.SymbolLookup; + +namespace SharpIDE.Godot.Features.CodeEditor; + +public partial class SharpIdeCodeEdit +{ + private readonly PackedScene _symbolUsagePopupScene = ResourceLoader.Load("uid://dq7ss2ha5rk44"); + + private void OnSymbolLookup(string symbolString, long line, long column) + { + GD.Print($"Symbol lookup requested: {symbolString} at line {line}, column {column}"); + _ = Task.GodotRun(async () => + { + var (symbol, linePositionSpan, semanticInfo) = await _roslynAnalysis.LookupSymbolSemanticInfo(_currentFile, new LinePosition((int)line, (int)column)); + if (symbol is null) return; + + //var locations = symbol.Locations; + + if (semanticInfo is null) return; + if (semanticInfo.Value.DeclaredSymbol is not null) + { + GD.Print($"Symbol is declared here: {symbolString}"); + // TODO: Lookup references instead + var references = await _roslynAnalysis.FindAllSymbolReferences(semanticInfo.Value.DeclaredSymbol); + if (references.Length is 1) + { + var reference = references[0]; + var locations = reference.LocationsArray; + if (locations.Length is 1) + { + // Lets jump to the definition + var referenceLocation = locations[0]; + + var referenceLineSpan = referenceLocation.Location.GetMappedLineSpan(); + var sharpIdeFile = Solution!.AllFiles.SingleOrDefault(f => f.Path == referenceLineSpan.Path); + if (sharpIdeFile is null) + { + GD.Print($"Reference file not found in solution: {referenceLineSpan.Path}"); + return; + } + + await GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelAsync(sharpIdeFile, new SharpIdeFileLinePosition(referenceLineSpan.Span.Start.Line, referenceLineSpan.Span.Start.Character)); + } + else + { + // Show popup to select which reference to go to + var scene = _symbolUsagePopupScene.Instantiate(); + var locationsAndFiles = locations.Select(s => + { + var lineSpan = s.Location.GetMappedLineSpan(); + var file = Solution!.AllFiles.SingleOrDefault(f => f.Path == lineSpan.Path); + return (s, file); + }).Where(t => t.file is not null).ToImmutableArray(); + scene.Locations = locations; + scene.LocationsAndFiles = locationsAndFiles!; + scene.Symbol = semanticInfo.Value.DeclaredSymbol; + await this.InvokeAsync(() => + { + AddChild(scene); + scene.PopupCenteredClamped(); + }); + } + } + } + else if (semanticInfo.Value.ReferencedSymbols.Length is not 0) + { + var referencedSymbol = + semanticInfo.Value.ReferencedSymbols.Single(); // Handle more than one when I run into it + var locations = referencedSymbol.Locations; + if (locations.Length is 1) + { + // Lets jump to the definition + var definitionLocation = locations[0]; + var definitionLineSpan = definitionLocation.GetMappedLineSpan(); + var sharpIdeFile = Solution!.AllFiles.SingleOrDefault(f => f.Path == definitionLineSpan.Path); + if (sharpIdeFile is null) + { + GD.Print($"Definition file not found in solution: {definitionLineSpan.Path}"); + return; + } + + await GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelAsync(sharpIdeFile, new SharpIdeFileLinePosition(definitionLineSpan.Span.Start.Line, definitionLineSpan.Span.Start.Character)); + } + else + { + // TODO: Show a popup to select which definition location to go to + } + } + }); + } +} \ No newline at end of file