rename symbol

This commit is contained in:
Matt Parker
2025-10-29 19:42:13 +10:00
parent bfda5b08b8
commit da2de0ed9b
9 changed files with 146 additions and 3 deletions

View File

@@ -0,0 +1,19 @@
using Microsoft.CodeAnalysis;
using SharpIDE.Application.Features.FileWatching;
namespace SharpIDE.Application.Features.Analysis;
public class IdeRenameService(RoslynAnalysis roslynAnalysis, FileChangedService fileChangedService)
{
private readonly RoslynAnalysis _roslynAnalysis = roslynAnalysis;
private readonly FileChangedService _fileChangedService = fileChangedService;
public async Task ApplyRename(ISymbol symbol, string newName)
{
var affectedFiles = await _roslynAnalysis.GetRenameApplyChanges(symbol, newName);
foreach (var (affectedFile, updatedText) in affectedFiles)
{
await _fileChangedService.SharpIdeFileChanged(affectedFile, updatedText, FileChangeType.CodeActionChange);
}
}
}

View File

@@ -31,6 +31,7 @@ public partial class DiAutoload : Node
services.AddScoped<SearchService>();
services.AddScoped<IdeFileExternalChangeHandler>();
services.AddScoped<IdeCodeActionService>();
services.AddScoped<IdeRenameService>();
services.AddScoped<IdeApplyCompletionService>();
services.AddScoped<FileChangedService>();
services.AddScoped<DotnetUserSecretsService>();

View File

@@ -0,0 +1,55 @@
using Godot;
namespace SharpIDE.Godot.Features.CodeEditor;
public partial class RenameSymbolDialog : ConfirmationDialog
{
private LineEdit _nameLineEdit = null!;
public TaskCompletionSource<string?> RenameTaskCompletionSource { get; } = new(TaskCreationOptions.RunContinuationsAsynchronously);
public string SymbolName { get; set; } = string.Empty;
private bool _isNameValid = true;
public override void _Ready()
{
_nameLineEdit = GetNode<LineEdit>("%SymbolNameLineEdit");
_nameLineEdit.Text = SymbolName;
_nameLineEdit.GrabFocus();
_nameLineEdit.SelectAll();
_nameLineEdit.TextChanged += ValidateNewSymbolName;
Confirmed += OnConfirmed;
}
public override void _ExitTree()
{
RenameTaskCompletionSource.TrySetResult(null);
}
private void ValidateNewSymbolName(string newSymbolNameText)
{
_isNameValid = true;
var newSymbolName = newSymbolNameText.Trim();
if (string.IsNullOrEmpty(newSymbolName))
{
_isNameValid = false;
}
var textColour = _isNameValid ? new Color(1, 1, 1) : new Color(1, 0, 0);
_nameLineEdit.AddThemeColorOverride("font_color", textColour);
}
public override void _Input(InputEvent @event)
{
if (@event is InputEventKey { Pressed: true, Keycode: Key.Enter })
{
EmitSignalConfirmed();
}
}
private void OnConfirmed()
{
if (_isNameValid is false) return;
var newSymbolName = _nameLineEdit.Text.Trim();
RenameTaskCompletionSource.SetResult(newSymbolName);
}
}

View File

@@ -0,0 +1 @@
uid://c4ppo6t4kcegp

View File

@@ -0,0 +1,26 @@
[gd_scene load_steps=2 format=3 uid="uid://cfcgmyhahblw"]
[ext_resource type="Script" uid="uid://c4ppo6t4kcegp" path="res://Features/CodeEditor/RenameSymbolDialog.cs" id="1_2s4mn"]
[node name="RenameSymbolDialog" type="ConfirmationDialog"]
oversampling_override = 1.0
title = "Rename: Symbol"
position = Vector2i(0, 36)
size = Vector2i(405, 115)
visible = true
script = ExtResource("1_2s4mn")
[node name="VBoxContainer" type="VBoxContainer" parent="."]
offset_left = 8.0
offset_top = 8.0
offset_right = 397.0
offset_bottom = 66.0
[node name="Label" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Enter new name:"
[node name="SymbolNameLineEdit" type="LineEdit" parent="VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "ExistingSymbolName"

View File

@@ -395,7 +395,11 @@ public partial class SharpIdeCodeEdit : CodeEdit
}
// Now we filter to only the focused tab
if (HasFocus() is false) return;
if (@event.IsActionPressed(InputStringNames.CodeFixes))
if (@event.IsActionPressed(InputStringNames.RenameSymbol))
{
_ = Task.GodotRun(async () => await RenameSymbol());
}
else if (@event.IsActionPressed(InputStringNames.CodeFixes))
{
EmitSignalCodeFixesRequested();
}
@@ -408,8 +412,6 @@ public partial class SharpIdeCodeEdit : CodeEdit
}
}
private readonly Color _breakpointLineColor = new Color("3a2323");
private readonly Color _executingLineColor = new Color("665001");
public void SetLineColour(int line)

View File

@@ -0,0 +1,37 @@
using Godot;
using Microsoft.CodeAnalysis.Text;
using SharpIDE.Application.Features.Analysis;
namespace SharpIDE.Godot.Features.CodeEditor;
public partial class SharpIdeCodeEdit
{
private readonly PackedScene _renameSymbolDialogScene = ResourceLoader.Load<PackedScene>("uid://cfcgmyhahblw");
[Inject] private readonly IdeRenameService _ideRenameService = null!;
public async Task RenameSymbol()
{
var cursorPosition = GetCaretPosition();
var (roslynSymbol, linePositionSpan) = await _roslynAnalysis.LookupSymbol(_currentFile, new LinePosition(cursorPosition.line, cursorPosition.col));
if (roslynSymbol is null || linePositionSpan is null)
{
GD.Print("No symbol found at cursor position for renaming.");
return;
}
var renameSymbolDialog = _renameSymbolDialogScene.Instantiate<RenameSymbolDialog>();
renameSymbolDialog.SymbolName = roslynSymbol.Name;
await this.InvokeAsync(() =>
{
AddChild(renameSymbolDialog);
renameSymbolDialog.PopupCentered();
});
var newName = await renameSymbolDialog.RenameTaskCompletionSource.Task;
renameSymbolDialog.QueueFree();
if (string.IsNullOrWhiteSpace(newName) || newName == roslynSymbol.Name)
{
GD.Print("Renaming cancelled or no change in name.");
return;
}
await _ideRenameService.ApplyRename(roslynSymbol, newName);
}
}

View File

@@ -0,0 +1 @@
uid://bxtxw0soa1l5u

View File

@@ -4,6 +4,7 @@ namespace SharpIDE.Godot;
public static class InputStringNames
{
public static readonly StringName RenameSymbol = nameof(RenameSymbol);
public static readonly StringName CodeFixes = "CodeFixes";
public static readonly StringName StepOver = "StepOver";
public static readonly StringName FindInFiles = nameof(FindInFiles);