Skip to content

Commit 4911dba

Browse files
Fix/prepare rename (#379)
* Added tests for prepare rename * added rename test Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 332e5ae commit 4911dba

File tree

2 files changed

+197
-3
lines changed

2 files changed

+197
-3
lines changed

src/Protocol/Serialization/Converters/RangeOrPlaceholderRangeConverter.cs

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using Newtonsoft.Json;
3+
using Newtonsoft.Json.Linq;
34
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
45
using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range;
56

@@ -13,16 +14,29 @@ public override void WriteJson(JsonWriter writer, RangeOrPlaceholderRange value,
1314
{
1415
serializer.Serialize(writer, value.Range);
1516
}
16-
else
17+
else if (value.IsPlaceholderRange)
1718
{
1819
serializer.Serialize(writer, value.PlaceholderRange);
1920
}
21+
else
22+
{
23+
writer.WriteNull();
24+
}
2025
}
2126

2227
public override RangeOrPlaceholderRange ReadJson(
2328
JsonReader reader, Type objectType, RangeOrPlaceholderRange existingValue, bool hasExistingValue, JsonSerializer serializer
24-
) => new RangeOrPlaceholderRange((Range) null);
29+
)
30+
{
31+
if (reader.TokenType is JsonToken.StartObject)
32+
{
33+
var obj = JToken.ReadFrom(reader) as JObject;
34+
return obj.ContainsKey("placeholder")
35+
? new RangeOrPlaceholderRange(obj.ToObject<PlaceholderRange>())
36+
: new RangeOrPlaceholderRange(obj.ToObject<Range>());
37+
}
2538

26-
public override bool CanRead => false;
39+
return null;
40+
}
2741
}
2842
}
+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
using System;
2+
using System.Linq;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using FluentAssertions;
6+
using NSubstitute;
7+
using OmniSharp.Extensions.JsonRpc.Testing;
8+
using OmniSharp.Extensions.LanguageProtocol.Testing;
9+
using OmniSharp.Extensions.LanguageServer.Client;
10+
using OmniSharp.Extensions.LanguageServer.Protocol;
11+
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
12+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
13+
using OmniSharp.Extensions.LanguageServer.Server;
14+
using Serilog.Events;
15+
using Xunit;
16+
using Xunit.Abstractions;
17+
using Range = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range;
18+
19+
namespace Lsp.Tests.Integration
20+
{
21+
public class RenameTests : LanguageProtocolTestBase
22+
{
23+
private readonly Func<PrepareRenameParams, CancellationToken, Task<RangeOrPlaceholderRange>> _prepareRename;
24+
private readonly Func<RenameParams, CancellationToken, Task<WorkspaceEdit>> _rename;
25+
26+
public RenameTests(ITestOutputHelper outputHelper) : base(new JsonRpcTestOptions().ConfigureForXUnit(outputHelper, LogEventLevel.Verbose))
27+
{
28+
_prepareRename = Substitute.For<Func<PrepareRenameParams, CancellationToken, Task<RangeOrPlaceholderRange>>>();
29+
_rename = Substitute.For<Func<RenameParams, CancellationToken, Task<WorkspaceEdit>>>();
30+
}
31+
32+
[Fact]
33+
public async Task Should_Handle_Rename_With_No_Value()
34+
{
35+
_prepareRename.Invoke(Arg.Any<PrepareRenameParams>(), Arg.Any<CancellationToken>())
36+
.Returns(
37+
call => {
38+
var pos = call.Arg<PrepareRenameParams>().Position;
39+
return new RangeOrPlaceholderRange(
40+
new Range(
41+
pos,
42+
( pos.Line, pos.Character + 2 )
43+
)
44+
);
45+
}
46+
);
47+
48+
_rename.Invoke(Arg.Any<RenameParams>(), Arg.Any<CancellationToken>())
49+
.Returns(
50+
new WorkspaceEdit() {
51+
DocumentChanges = new Container<WorkspaceEditDocumentChange>(new WorkspaceEditDocumentChange(new CreateFile() {
52+
Uri = DocumentUri.FromFileSystemPath("/abcd/create.cs")
53+
}))
54+
}
55+
);
56+
57+
var (client, server) = await Initialize(ClientOptionsAction, ServerOptionsAction);
58+
59+
var result = await client.PrepareRename(
60+
new PrepareRenameParams() {
61+
Position = ( 1, 1 ),
62+
TextDocument = DocumentUri.FromFileSystemPath("/abcd/file.cs")
63+
},
64+
CancellationToken
65+
);
66+
67+
result.Should().NotBeNull();
68+
69+
var renameResponse = await client.RequestRename(
70+
new RenameParams() {
71+
Position = result.Range.Start,
72+
NewName = "newname",
73+
TextDocument = DocumentUri.FromFileSystemPath("/abcd/file.cs")
74+
}
75+
);
76+
77+
renameResponse.DocumentChanges.Should().HaveCount(1);
78+
renameResponse.DocumentChanges.Should().Match(z => z.Any(x => x.IsCreateFile));
79+
}
80+
81+
[Fact]
82+
public async Task Should_Handle_Prepare_Rename_With_No_Value()
83+
{
84+
_prepareRename.Invoke(Arg.Any<PrepareRenameParams>(), Arg.Any<CancellationToken>())
85+
.Returns(Task.FromResult<RangeOrPlaceholderRange>(null));
86+
var (client, server) = await Initialize(ClientOptionsAction, ServerOptionsAction);
87+
88+
var result = await client.PrepareRename(
89+
new PrepareRenameParams() {
90+
Position = ( 1, 1 ),
91+
TextDocument = DocumentUri.FromFileSystemPath("/abcd/file.cs")
92+
},
93+
CancellationToken
94+
);
95+
96+
result.Should().BeNull();
97+
}
98+
99+
[Fact]
100+
public async Task Should_Handle_Prepare_Rename_With_Range()
101+
{
102+
_prepareRename.Invoke(Arg.Any<PrepareRenameParams>(), Arg.Any<CancellationToken>())
103+
.Returns(
104+
call => {
105+
var pos = call.Arg<PrepareRenameParams>().Position;
106+
return new RangeOrPlaceholderRange(
107+
new Range(
108+
pos,
109+
( pos.Line, pos.Character + 2 )
110+
)
111+
);
112+
}
113+
);
114+
115+
var (client, server) = await Initialize(ClientOptionsAction, ServerOptionsAction);
116+
117+
var result = await client.PrepareRename(
118+
new PrepareRenameParams() {
119+
Position = ( 1, 1 ),
120+
TextDocument = DocumentUri.FromFileSystemPath("/abcd/file.cs")
121+
},
122+
CancellationToken
123+
);
124+
125+
result.IsRange.Should().BeTrue();
126+
}
127+
128+
[Fact]
129+
public async Task Should_Handle_Prepare_Rename_With_PlaceholderRange()
130+
{
131+
_prepareRename.Invoke(Arg.Any<PrepareRenameParams>(), Arg.Any<CancellationToken>())
132+
.Returns(
133+
call => {
134+
var pos = call.Arg<PrepareRenameParams>().Position;
135+
return new RangeOrPlaceholderRange(
136+
new PlaceholderRange() {
137+
Range =
138+
new Range(
139+
pos,
140+
( pos.Line, pos.Character + 2 )
141+
),
142+
Placeholder = "Bogus"
143+
}
144+
);
145+
}
146+
);
147+
148+
var (client, server) = await Initialize(ClientOptionsAction, ServerOptionsAction);
149+
150+
var result = await client.PrepareRename(
151+
new PrepareRenameParams() {
152+
Position = ( 1, 1 ),
153+
TextDocument = DocumentUri.FromFileSystemPath("/abcd/file.cs")
154+
},
155+
CancellationToken
156+
);
157+
158+
result.IsPlaceholderRange.Should().BeTrue();
159+
}
160+
161+
private void ServerOptionsAction(LanguageServerOptions obj)
162+
{
163+
obj.OnPrepareRename(
164+
_prepareRename, new TextDocumentRegistrationOptions() {
165+
DocumentSelector = DocumentSelector.ForLanguage("csharp")
166+
}
167+
);
168+
obj.OnRename(
169+
_rename, new RenameRegistrationOptions() {
170+
DocumentSelector = DocumentSelector.ForLanguage("csharp"),
171+
PrepareProvider = true
172+
}
173+
);
174+
}
175+
176+
private void ClientOptionsAction(LanguageClientOptions obj)
177+
{
178+
}
179+
}
180+
}

0 commit comments

Comments
 (0)