Skip to content

Commit 09d9466

Browse files
fixed an issue where workspace folders could be null, and this would cause issues (#346)
* fixed an issue where workspace folders could be null, and this would cause issues * Change timings on test... SettleNext() was never awaited Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent c451a74 commit 09d9466

File tree

2 files changed

+59
-8
lines changed

2 files changed

+59
-8
lines changed

src/Server/LanguageServerWorkspaceFolderManager.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ async Task IOnLanguageServerStarted.OnStarted(ILanguageServer server, Cancellati
5555
IsSupported = server.ClientSettings?.Capabilities?.Workspace?.WorkspaceFolders.IsSupported == true;
5656
if (IsSupported)
5757
{
58-
await Refresh().LastOrDefaultAsync().ToTask(cancellationToken);
58+
foreach (var folder in server.ClientSettings?.WorkspaceFolders ?? Enumerable.Empty<WorkspaceFolder>())
59+
{
60+
_workspaceFolders.AddOrUpdate(folder.Uri, folder, (a, b) => folder);
61+
_workspaceFoldersChangedSubject.OnNext(new WorkspaceFolderChange(WorkspaceFolderEvent.Add, folder));
62+
}
5963
}
6064
}
6165

@@ -65,6 +69,7 @@ public IObservable<WorkspaceFolder> Refresh() => Observable.Create<WorkspaceFold
6569
return Observable.FromAsync(ct => _server.RequestWorkspaceFolders(new WorkspaceFolderParams(), ct))
6670
.Do(
6771
workspaceFolders => {
72+
workspaceFolders ??= new Container<WorkspaceFolder>();
6873
var existingFolders = new HashSet<WorkspaceFolder>(_workspaceFolders.Values.Join(workspaceFolders, z => z.Uri, z => z.Uri, (a, b) => b));
6974
var additions = new HashSet<WorkspaceFolder>();
7075
var removals = new HashSet<WorkspaceFolder>();

test/Lsp.Tests/Integration/WorkspaceFolderTests.cs

+53-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Linq;
44
using System.Reactive.Linq;
55
using System.Reactive.Threading.Tasks;
6+
using System.Threading;
67
using System.Threading.Tasks;
78
using FluentAssertions;
89
using NSubstitute;
@@ -11,6 +12,9 @@
1112
using OmniSharp.Extensions.LanguageServer.Client;
1213
using OmniSharp.Extensions.LanguageServer.Protocol;
1314
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
15+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
16+
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
17+
using OmniSharp.Extensions.LanguageServer.Protocol.Workspace;
1418
using OmniSharp.Extensions.LanguageServer.Server;
1519
using Serilog.Events;
1620
using Xunit;
@@ -21,10 +25,7 @@ namespace Lsp.Tests.Integration
2125
public class WorkspaceFolderTests : LanguageProtocolTestBase
2226
{
2327
public WorkspaceFolderTests(ITestOutputHelper outputHelper) : base(
24-
new JsonRpcTestOptions()
25-
.ConfigureForXUnit(outputHelper, LogEventLevel.Verbose)
26-
.WithWaitTime(TimeSpan.FromSeconds(1))
27-
.WithTimeout(TimeSpan.FromSeconds(2))
28+
new JsonRpcTestOptions().ConfigureForXUnit(outputHelper, LogEventLevel.Verbose)
2829
)
2930
{
3031
}
@@ -60,7 +61,7 @@ public async Task Should_Add_A_Workspace_Folder()
6061

6162
client.WorkspaceFoldersManager.Add("/abcd/", nameof(Should_Add_A_Workspace_Folder));
6263

63-
SettleNext();
64+
await SettleNext();
6465

6566
folders.Should().HaveCount(1);
6667
folders[0].Event.Should().Be(WorkspaceFolderEvent.Add);
@@ -89,7 +90,7 @@ public async Task Should_Remove_Workspace_Folder_by_name()
8990

9091
client.WorkspaceFoldersManager.Remove(nameof(Should_Remove_Workspace_Folder_by_name));
9192

92-
SettleNext();
93+
await SettleNext();
9394

9495
folders.Should().HaveCount(1);
9596
folders[0].Event.Should().Be(WorkspaceFolderEvent.Remove);
@@ -109,13 +110,58 @@ public async Task Should_Remove_Workspace_Folder_by_uri()
109110

110111
client.WorkspaceFoldersManager.Remove(DocumentUri.From("/abcd/"));
111112

112-
SettleNext();
113+
await SettleNext();
113114

114115
folders.Should().HaveCount(1);
115116
folders[0].Event.Should().Be(WorkspaceFolderEvent.Remove);
116117
folders[0].Folder.Name.Should().Be(nameof(Should_Remove_Workspace_Folder_by_uri));
117118
}
118119

120+
[Fact]
121+
public async Task Should_Handle_Null_Workspace_Folders()
122+
{
123+
var workspaceLanguageServer = Substitute.For<IWorkspaceLanguageServer>();
124+
var languageServer = Substitute.For<ILanguageServer>();
125+
languageServer.ClientSettings.Returns(
126+
new InitializeParams() {
127+
Capabilities = new ClientCapabilities() {
128+
Workspace = new WorkspaceClientCapabilities() {
129+
WorkspaceFolders = true
130+
}
131+
},
132+
WorkspaceFolders = null
133+
}
134+
);
135+
var workspaceFolders = new LanguageServerWorkspaceFolderManager(workspaceLanguageServer);
136+
var started = (IOnLanguageServerStarted) workspaceFolders;
137+
await started.OnStarted(languageServer, CancellationToken);
138+
}
139+
140+
[Fact]
141+
public async Task Should_Handle_Null_Workspace_Folders_On_Refresh()
142+
{
143+
var workspaceLanguageServer = Substitute.For<IWorkspaceLanguageServer>();
144+
var languageServer = Substitute.For<ILanguageServer>();
145+
languageServer.ClientSettings.Returns(
146+
new InitializeParams() {
147+
Capabilities = new ClientCapabilities() {
148+
Workspace = new WorkspaceClientCapabilities() {
149+
WorkspaceFolders = true
150+
}
151+
},
152+
WorkspaceFolders = null
153+
}
154+
);
155+
languageServer.SendRequest(Arg.Any<WorkspaceFolderParams>(), Arg.Any<CancellationToken>()).Returns((Container<WorkspaceFolder> ) null);
156+
var workspaceFolders = new LanguageServerWorkspaceFolderManager(workspaceLanguageServer);
157+
var started = (IOnLanguageServerStarted) workspaceFolders;
158+
await started.OnStarted(languageServer, CancellationToken);
159+
160+
var result = await workspaceFolders.Refresh().ToArray();
161+
162+
result.Should().BeEmpty();
163+
}
164+
119165
private void ConfigureClient(LanguageClientOptions options) =>
120166
options.WithClientCapabilities(
121167
new ClientCapabilities {

0 commit comments

Comments
 (0)