Skip to content

Commit 43b9649

Browse files
committed
Extract some duplicate functions and enable NRT checking for RenameHandler
1 parent 3336814 commit 43b9649

File tree

2 files changed

+51
-19
lines changed

2 files changed

+51
-19
lines changed

src/PowerShellEditorServices/Services/PowerShell/Handlers/RenameHandler.cs

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT License.
3+
#nullable enable
34

45
using System.Collections.Generic;
56
using System.Threading;
@@ -14,10 +15,10 @@
1415
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
1516
using OmniSharp.Extensions.LanguageServer.Protocol;
1617
using System;
17-
using PowerShellEditorServices.Services.PowerShell.Utility;
1818

1919
namespace Microsoft.PowerShell.EditorServices.Handlers;
2020

21+
2122
/// <summary>
2223
/// A handler for <a href="https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename">textDocument/prepareRename</a>
2324
/// LSP Ref: <see cref="PrepareRename()"/>
@@ -26,7 +27,7 @@ internal class PrepareRenameHandler(WorkspaceService workspaceService) : IPrepar
2627
{
2728
public RenameRegistrationOptions GetRegistrationOptions(RenameCapability capability, ClientCapabilities clientCapabilities) => capability.PrepareSupport ? new() { PrepareProvider = true } : new();
2829

29-
public async Task<RangeOrPlaceholderRange> Handle(PrepareRenameParams request, CancellationToken cancellationToken)
30+
public async Task<RangeOrPlaceholderRange?> Handle(PrepareRenameParams request, CancellationToken cancellationToken)
3031
{
3132
ScriptFile scriptFile = workspaceService.GetFile(request.TextDocument.Uri);
3233

@@ -37,11 +38,28 @@ public async Task<RangeOrPlaceholderRange> Handle(PrepareRenameParams request, C
3738
}
3839

3940
ScriptPositionAdapter position = request.Position;
40-
Ast token = FindRenamableSymbol(scriptFile, position);
41-
if (token is null) { return null; }
41+
Ast target = FindRenamableSymbol(scriptFile, position);
42+
if (target is null) { return null; }
43+
return target switch
44+
{
45+
FunctionDefinitionAst funcAst => GetFunctionNameExtent(funcAst),
46+
_ => new ScriptExtentAdapter(target.Extent)
47+
};
48+
}
49+
50+
private static ScriptExtentAdapter GetFunctionNameExtent(FunctionDefinitionAst ast)
51+
{
52+
string name = ast.Name;
53+
// FIXME: Gather dynamically from the AST and include backticks and whatnot that might be present
54+
int funcLength = "function ".Length;
55+
ScriptExtentAdapter funcExtent = new(ast.Extent);
4256

43-
// TODO: Really should have a class with implicit convertors handing these conversions to avoid off-by-one mistakes.
44-
return new ScriptExtentAdapter(token.Extent);
57+
// Get a range that represents only the function name
58+
return funcExtent with
59+
{
60+
Start = funcExtent.Start.Delta(0, funcLength),
61+
End = funcExtent.Start.Delta(0, funcLength + name.Length)
62+
};
4563
}
4664

4765
/// <summary>
@@ -89,8 +107,15 @@ or CommandAst
89107
if (parent.GetCommandName() != stringAst.Value) { return false; }
90108
}
91109

92-
return ast.Extent.Contains(position);
110+
ScriptExtentAdapter target = ast switch
111+
{
112+
FunctionDefinitionAst funcAst => GetFunctionNameExtent(funcAst),
113+
_ => new ScriptExtentAdapter(ast.Extent)
114+
};
115+
116+
return target.Contains(position);
93117
}, true);
118+
94119
return token;
95120
}
96121
}
@@ -104,7 +129,7 @@ internal class RenameHandler(WorkspaceService workspaceService) : IRenameHandler
104129
// RenameOptions may only be specified if the client states that it supports prepareSupport in its initial initialize request.
105130
public RenameRegistrationOptions GetRegistrationOptions(RenameCapability capability, ClientCapabilities clientCapabilities) => capability.PrepareSupport ? new() { PrepareProvider = true } : new();
106131

107-
public async Task<WorkspaceEdit> Handle(RenameParams request, CancellationToken cancellationToken)
132+
public async Task<WorkspaceEdit?> Handle(RenameParams request, CancellationToken cancellationToken)
108133
{
109134
ScriptFile scriptFile = workspaceService.GetFile(request.TextDocument.Uri);
110135
ScriptPositionAdapter position = request.Position;
@@ -179,7 +204,7 @@ internal static TextEdit[] RenameVariable(Ast symbol, Ast scriptAst, RenameParam
179204
return visitor.Modifications.ToArray();
180205

181206
}
182-
return null;
207+
return [];
183208
}
184209
}
185210

@@ -205,12 +230,16 @@ public record ScriptPositionAdapter(IScriptPosition position) : IScriptPosition,
205230

206231
public ScriptPositionAdapter(int Line, int Column) : this(new ScriptPosition(null, Line, Column, null)) { }
207232
public ScriptPositionAdapter(ScriptPosition position) : this((IScriptPosition)position) { }
208-
public ScriptPositionAdapter(Position position) : this(position.Line + 1, position.Character + 1) { }
209233

234+
public ScriptPositionAdapter(Position position) : this(position.Line + 1, position.Character + 1) { }
210235
public static implicit operator ScriptPositionAdapter(Position position) => new(position);
211-
public static implicit operator ScriptPositionAdapter(ScriptPosition position) => new(position);
236+
public static implicit operator Position(ScriptPositionAdapter scriptPosition) => new
237+
(
238+
scriptPosition.position.LineNumber - 1, scriptPosition.position.ColumnNumber - 1
239+
);
212240

213-
public static implicit operator Position(ScriptPositionAdapter scriptPosition) => new(scriptPosition.position.LineNumber - 1, scriptPosition.position.ColumnNumber - 1);
241+
242+
public static implicit operator ScriptPositionAdapter(ScriptPosition position) => new(position);
214243
public static implicit operator ScriptPosition(ScriptPositionAdapter position) => position;
215244

216245
internal ScriptPositionAdapter Delta(int LineAdjust, int ColumnAdjust) => new(
@@ -241,19 +270,22 @@ internal record ScriptExtentAdapter(IScriptExtent extent) : IScriptExtent
241270
public ScriptPositionAdapter End = new(extent.EndScriptPosition);
242271

243272
public static implicit operator ScriptExtentAdapter(ScriptExtent extent) => new(extent);
273+
244274
public static implicit operator ScriptExtentAdapter(Range range) => new(new ScriptExtent(
245275
// Will get shifted to 1-based
246276
new ScriptPositionAdapter(range.Start),
247277
new ScriptPositionAdapter(range.End)
248278
));
249-
250-
public static implicit operator ScriptExtent(ScriptExtentAdapter adapter) => adapter;
251279
public static implicit operator Range(ScriptExtentAdapter adapter) => new()
252280
{
281+
// Will get shifted to 0-based
253282
Start = adapter.Start,
254283
End = adapter.End
255284
};
256-
public static implicit operator RangeOrPlaceholderRange(ScriptExtentAdapter adapter) => new(adapter);
285+
286+
public static implicit operator ScriptExtent(ScriptExtentAdapter adapter) => adapter;
287+
288+
public static implicit operator RangeOrPlaceholderRange(ScriptExtentAdapter adapter) => new((Range)adapter);
257289

258290
public IScriptPosition StartScriptPosition => Start;
259291
public IScriptPosition EndScriptPosition => End;
@@ -272,11 +304,11 @@ internal record ScriptExtentAdapter(IScriptExtent extent) : IScriptExtent
272304

273305
public class RenameSymbolParams : IRequest<RenameSymbolResult>
274306
{
275-
public string FileName { get; set; }
307+
public string? FileName { get; set; }
276308
public int Line { get; set; }
277309
public int Column { get; set; }
278-
public string RenameTo { get; set; }
279-
public RenameSymbolOptions Options { get; set; }
310+
public string? RenameTo { get; set; }
311+
public RenameSymbolOptions? Options { get; set; }
280312
}
281313

282314
public class RenameSymbolResult

test/PowerShellEditorServices.Test/Refactoring/PrepareRenameHandlerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public async Task FindsSymbol(RenameSymbolParamsSerialized param)
4949
}
5050
};
5151

52-
RangeOrPlaceholderRange result = await handler.Handle(testParams, CancellationToken.None);
52+
RangeOrPlaceholderRange? result = await handler.Handle(testParams, CancellationToken.None);
5353
Assert.NotNull(result);
5454
Assert.NotNull(result.Range);
5555
Assert.True(result.Range.Contains(position));

0 commit comments

Comments
 (0)