Auto size symbol lookup popup
This commit is contained in:
@@ -667,12 +667,30 @@ public class RoslynAnalysis(ILogger<RoslynAnalysis> logger, BuildService buildSe
|
||||
return changedFilesWithText;
|
||||
}
|
||||
|
||||
public async Task<ISymbol?> GetEnclosingSymbolForReferenceLocation(ReferenceLocation referenceLocation)
|
||||
public record IdeReferenceLocationResult(ReferenceLocation ReferenceLocation, SharpIdeFile? File, ISymbol? EnclosingSymbol);
|
||||
public async Task<IdeReferenceLocationResult?> GetIdeReferenceLocationResult(ReferenceLocation referenceLocation)
|
||||
{
|
||||
var semanticModel = await referenceLocation.Document.GetSemanticModelAsync();
|
||||
if (semanticModel is null) return null;
|
||||
var enclosingSymbol = ReferenceLocationExtensions.GetEnclosingMethodOrPropertyOrField(semanticModel, referenceLocation);
|
||||
return enclosingSymbol;
|
||||
var lineSpan = referenceLocation.Location.GetMappedLineSpan();
|
||||
var file = _sharpIdeSolutionModel!.AllFiles.SingleOrDefault(f => f.Path == lineSpan.Path);
|
||||
var result = new IdeReferenceLocationResult(referenceLocation, file!, enclosingSymbol);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<IdeReferenceLocationResult>> GetIdeReferenceLocationResults(ImmutableArray<ReferenceLocation> referenceLocations)
|
||||
{
|
||||
var results = new List<IdeReferenceLocationResult>();
|
||||
foreach (var referenceLocation in referenceLocations)
|
||||
{
|
||||
var result = await GetIdeReferenceLocationResult(referenceLocation);
|
||||
if (result is not null)
|
||||
{
|
||||
results.Add(result);
|
||||
}
|
||||
}
|
||||
return results.ToImmutableArray();
|
||||
}
|
||||
|
||||
public async Task<ImmutableArray<ReferencedSymbol>> FindAllSymbolReferences(ISymbol symbol, CancellationToken cancellationToken = default)
|
||||
@@ -682,7 +700,7 @@ public class RoslynAnalysis(ILogger<RoslynAnalysis> logger, BuildService buildSe
|
||||
|
||||
var solution = _workspace!.CurrentSolution;
|
||||
var references = await SymbolFinder.FindReferencesAsync(symbol, solution, cancellationToken);
|
||||
return references.AsImmutable();
|
||||
return references.ToImmutableArray();
|
||||
}
|
||||
|
||||
public async Task<(ISymbol?, LinePositionSpan?, TokenSemanticInfo?)> LookupSymbolSemanticInfo(SharpIdeFile fileModel, LinePosition linePosition)
|
||||
|
||||
@@ -48,20 +48,15 @@ public partial class SharpIdeCodeEdit
|
||||
else
|
||||
{
|
||||
// Show popup to select which reference to go to
|
||||
var scene = _symbolUsagePopupScene.Instantiate<SymbolLookupPopup>();
|
||||
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;
|
||||
var symbolLookupPopup = _symbolUsagePopupScene.Instantiate<SymbolLookupPopup>();
|
||||
var ideReferenceLocationResults = await _roslynAnalysis.GetIdeReferenceLocationResults(locations);
|
||||
symbolLookupPopup.IdeReferenceLocationResults = ideReferenceLocationResults;
|
||||
symbolLookupPopup.Symbol = semanticInfo.Value.DeclaredSymbol;
|
||||
symbolLookupPopup.Size = new Vector2I(1, 1); // Set tiny size so it autosizes up based on child content
|
||||
await this.InvokeAsync(() =>
|
||||
{
|
||||
AddChild(scene);
|
||||
scene.PopupCenteredClamped();
|
||||
AddChild(symbolLookupPopup);
|
||||
symbolLookupPopup.PopupCentered();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections.Immutable;
|
||||
using Godot;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.FindSymbols;
|
||||
using SharpIDE.Application.Features.Analysis;
|
||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||
|
||||
namespace SharpIDE.Godot.Features.SymbolLookup;
|
||||
@@ -10,8 +11,8 @@ public partial class SymbolLookupPopup : PopupPanel
|
||||
{
|
||||
private Label _symbolNameLabel = null!;
|
||||
private VBoxContainer _usagesContainer = null!;
|
||||
public ImmutableArray<ReferenceLocation> Locations { get; set; }
|
||||
public ImmutableArray<(ReferenceLocation location, SharpIdeFile file)> LocationsAndFiles { get; set; }
|
||||
|
||||
public ImmutableArray<RoslynAnalysis.IdeReferenceLocationResult> IdeReferenceLocationResults { get; set; }
|
||||
public ISymbol Symbol { get; set; } = null!;
|
||||
private readonly PackedScene _symbolUsageScene = ResourceLoader.Load<PackedScene>("uid://dokm0dyac2enh");
|
||||
|
||||
@@ -24,11 +25,12 @@ public partial class SymbolLookupPopup : PopupPanel
|
||||
AboutToPopup += OnAboutToPopup;
|
||||
|
||||
_usagesContainer.GetChildren().ToList().ForEach(s => s.QueueFree());
|
||||
foreach (var (location, file) in LocationsAndFiles)
|
||||
foreach (var result in IdeReferenceLocationResults)
|
||||
{
|
||||
var resultNode = _symbolUsageScene.Instantiate<SymbolUsageComponent>();
|
||||
resultNode.Location = location;
|
||||
resultNode.File = file;
|
||||
resultNode.Location = result.ReferenceLocation;
|
||||
resultNode.File = result.File;
|
||||
resultNode.EnclosingSymbol = result.EnclosingSymbol;
|
||||
resultNode.ParentSearchWindow = this;
|
||||
_usagesContainer.AddChild(resultNode);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ shadow_size = 4
|
||||
|
||||
[node name="SymbolLookupPopup" type="PopupPanel"]
|
||||
oversampling_override = 1.0
|
||||
size = Vector2i(505, 340)
|
||||
size = Vector2i(564, 340)
|
||||
visible = true
|
||||
theme_override_styles/panel = SubResource("StyleBoxFlat_cuaw5")
|
||||
script = ExtResource("1_f5udm")
|
||||
@@ -50,15 +50,10 @@ unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "'UseWebApi()'"
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/VBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
follow_focus = true
|
||||
|
||||
[node name="UsagesVBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer/ScrollContainer"]
|
||||
[node name="UsagesVBoxContainer" type="VBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="SymbolUsageComponent" parent="MarginContainer/VBoxContainer/ScrollContainer/UsagesVBoxContainer" instance=ExtResource("1_k5g0h")]
|
||||
[node name="SymbolUsageComponent" parent="MarginContainer/VBoxContainer/UsagesVBoxContainer" instance=ExtResource("1_k5g0h")]
|
||||
layout_mode = 2
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Godot;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.FindSymbols;
|
||||
using SharpIDE.Application.Features.Analysis;
|
||||
using SharpIDE.Application.Features.SolutionDiscovery;
|
||||
@@ -14,9 +15,8 @@ public partial class SymbolUsageComponent : MarginContainer
|
||||
|
||||
public SymbolLookupPopup ParentSearchWindow { get; set; } = null!;
|
||||
public ReferenceLocation? Location { get; set; }
|
||||
public SharpIdeFile File { get; set; } = null!;
|
||||
|
||||
[Inject] private readonly RoslynAnalysis _roslynAnalysis = null!;
|
||||
public ISymbol? EnclosingSymbol { get; set; } = null!;
|
||||
public SharpIdeFile? File { get; set; } = null!;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
@@ -32,7 +32,10 @@ public partial class SymbolUsageComponent : MarginContainer
|
||||
{
|
||||
var mappedLineSpan = Location!.Value.Location.GetMappedLineSpan();
|
||||
var fileLinePosition = new SharpIdeFileLinePosition { Line = mappedLineSpan.StartLinePosition.Line, Column = mappedLineSpan.StartLinePosition.Character };
|
||||
GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelFireAndForget(File, fileLinePosition);
|
||||
if (File is not null)
|
||||
{
|
||||
GodotGlobalEvents.Instance.FileExternallySelected.InvokeParallelFireAndForget(File, fileLinePosition);
|
||||
}
|
||||
ParentSearchWindow.Hide();
|
||||
}
|
||||
|
||||
@@ -41,13 +44,8 @@ public partial class SymbolUsageComponent : MarginContainer
|
||||
if (result is null) return;
|
||||
var mappedLineSpan = result.Value.Location.GetMappedLineSpan();
|
||||
|
||||
_fileNameLabel.Text = File.Name;
|
||||
_fileNameLabel.Text = File?.Name ?? Path.GetFileName(mappedLineSpan.Path);
|
||||
_lineNumberLabel.Text = (mappedLineSpan.StartLinePosition.Line + 1).ToString();
|
||||
|
||||
_ = Task.GodotRun(async () =>
|
||||
{
|
||||
var enclosingSymbol = await _roslynAnalysis.GetEnclosingSymbolForReferenceLocation(result.Value);
|
||||
await this.InvokeAsync(() => _enclosingSymbolLabel.Text = enclosingSymbol?.Name);
|
||||
});
|
||||
_enclosingSymbolLabel.Text = EnclosingSymbol?.Name;
|
||||
}
|
||||
}
|
||||
@@ -29,33 +29,32 @@ layout_mode = 2
|
||||
theme_override_styles/normal = SubResource("StyleBoxFlat_6ov2c")
|
||||
theme_override_styles/focus = SubResource("StyleBoxFlat_dtmd4")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="Button"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 2
|
||||
mouse_filter = 0
|
||||
mouse_behavior_recursive = 1
|
||||
theme_override_constants/margin_left = 5
|
||||
theme_override_constants/margin_right = 5
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Button/MarginContainer"]
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="EnclosingSymbolLabel" type="Label" parent="Button/MarginContainer/HBoxContainer"]
|
||||
[node name="EnclosingSymbolLabel" type="Label" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Containing Symbol Name"
|
||||
text_overrun_behavior = 3
|
||||
|
||||
[node name="FileNameLabel" type="Label" parent="Button/MarginContainer/HBoxContainer"]
|
||||
[node name="Spacer" type="Control" parent="MarginContainer/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="FileNameLabel" type="Label" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 0.7411765)
|
||||
text = "FileName.cs"
|
||||
|
||||
[node name="LineNumberLabel" type="Label" parent="Button/MarginContainer/HBoxContainer"]
|
||||
[node name="LineNumberLabel" type="Label" parent="MarginContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
theme_override_colors/font_color = Color(1, 1, 1, 0.7411765)
|
||||
|
||||
Reference in New Issue
Block a user