Skip to content

Commit 7cf0c0a

Browse files
Avoid double registration of text change handlers (they also can be double registered by dynamic registration!)
1 parent d86c644 commit 7cf0c0a

File tree

7 files changed

+420
-383
lines changed

7 files changed

+420
-383
lines changed

src/Protocol/Client/Capabilities/SynchronizationCapability.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
using Newtonsoft.Json;
22
using OmniSharp.Extensions.LanguageServer.Protocol;
33
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;
4+
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
45

56
namespace OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities
67
{
7-
public class SynchronizationCapability : DynamicCapability
8+
public class SynchronizationCapability : DynamicCapability, ConnectedCapability<IDidChangeTextDocumentHandler>, ConnectedCapability<IDidCloseTextDocumentHandler>, ConnectedCapability<IDidOpenTextDocumentHandler>, ConnectedCapability<IDidSaveTextDocumentHandler>, ConnectedCapability<IWillSaveTextDocumentHandler>, ConnectedCapability<IWillSaveWaitUntilTextDocumentHandler>
89
{
910
/// <summary>
1011
/// The client supports sending will save notifications.

src/Protocol/Models/IExecuteCommandOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ public interface IExecuteCommandOptions
44
{
55
Container<string> Commands { get; set; }
66
}
7-
}
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities;
2+
3+
namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
4+
{
5+
public interface ITextDocumentSyncOptions
6+
{
7+
bool OpenClose { get; set; }
8+
TextDocumentSyncKind Change { get; set; }
9+
bool WillSave { get; set; }
10+
bool WillSaveWaitUntil { get; set; }
11+
SaveOptions Save { get; set; }
12+
}
13+
}

src/Protocol/Server/Capabilities/TextDocumentSyncOptions.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
13
using Newtonsoft.Json;
24
using Newtonsoft.Json.Serialization;
5+
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
36
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;
47

58
namespace OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities
69
{
7-
public class TextDocumentSyncOptions
10+
public class TextDocumentSyncOptions : ITextDocumentSyncOptions
811
{
912
/// <summary>
1013
/// Open and close notifications are sent to the server.
@@ -32,5 +35,20 @@ public class TextDocumentSyncOptions
3235
/// </summary>
3336
[Optional]
3437
public SaveOptions Save { get; set; }
38+
39+
public static TextDocumentSyncOptions Of(IEnumerable<ITextDocumentSyncOptions> options)
40+
{
41+
return new TextDocumentSyncOptions() {
42+
OpenClose = options.Any(z => z.OpenClose),
43+
Change = options
44+
.Where(x => x.Change != TextDocumentSyncKind.None)
45+
.Min(z => z.Change),
46+
WillSave = options.Any(z => z.WillSave),
47+
WillSaveWaitUntil = options.Any(z => z.WillSaveWaitUntil),
48+
Save = new SaveOptions() {
49+
IncludeText = options.Any(z => z.Save?.IncludeText == true)
50+
}
51+
};
52+
}
3553
}
3654
}

src/Server/LanguageServer.cs

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ async Task<InitializeResult> IRequestHandler<InitializeParams, InitializeResult>
307307
DocumentRangeFormattingProvider = ccp.HasStaticHandler(textDocumentCapabilities.RangeFormatting),
308308
DocumentSymbolProvider = ccp.HasStaticHandler(textDocumentCapabilities.DocumentSymbol),
309309
ExecuteCommandProvider = ccp.GetStaticOptions(workspaceCapabilities.ExecuteCommand).Reduce<IExecuteCommandOptions, ExecuteCommandOptions>(ExecuteCommandOptions.Of),
310+
TextDocumentSync = ccp.GetStaticOptions(textDocumentCapabilities.Synchronization).Reduce<ITextDocumentSyncOptions, TextDocumentSyncOptions>(TextDocumentSyncOptions.Of),
310311
HoverProvider = ccp.HasStaticHandler(textDocumentCapabilities.Hover),
311312
ReferencesProvider = ccp.HasStaticHandler(textDocumentCapabilities.References),
312313
RenameProvider = ccp.GetStaticOptions(textDocumentCapabilities.Rename).Get<IRenameOptions, RenameOptions>(RenameOptions.Of),
@@ -330,30 +331,33 @@ async Task<InitializeResult> IRequestHandler<InitializeParams, InitializeResult>
330331
};
331332
}
332333

333-
var textDocumentSyncKind = _collection.ContainsHandler(typeof(IDidChangeTextDocumentHandler))
334-
? _collection
335-
.Select(x => x.Handler)
336-
.OfType<IDidChangeTextDocumentHandler>()
337-
.Where(x => x.Change != TextDocumentSyncKind.None)
338-
.Min(z => z.Change)
339-
: TextDocumentSyncKind.None;
340-
341-
if (_clientVersion == ClientVersion.Lsp2)
334+
if (ccp.HasStaticHandler(textDocumentCapabilities.Synchronization))
342335
{
343-
serverCapabilities.TextDocumentSync = textDocumentSyncKind;
344-
}
345-
else
346-
{
347-
serverCapabilities.TextDocumentSync = new TextDocumentSyncOptions()
336+
var textDocumentSyncKind = _collection.ContainsHandler(typeof(IDidChangeTextDocumentHandler))
337+
? _collection
338+
.Select(x => x.Handler)
339+
.OfType<IDidChangeTextDocumentHandler>()
340+
.Where(x => x.Change != TextDocumentSyncKind.None)
341+
.Min(z => z.Change)
342+
: TextDocumentSyncKind.None;
343+
344+
if (_clientVersion == ClientVersion.Lsp2)
348345
{
349-
Change = textDocumentSyncKind,
350-
OpenClose = _collection.ContainsHandler(typeof(IDidOpenTextDocumentHandler)) || _collection.ContainsHandler(typeof(IDidCloseTextDocumentHandler)),
351-
Save = _collection.ContainsHandler(typeof(IDidSaveTextDocumentHandler)) ?
352-
new SaveOptions() { IncludeText = true /* TODO: Make configurable */ } :
353-
null,
354-
WillSave = _collection.ContainsHandler(typeof(IWillSaveTextDocumentHandler)),
355-
WillSaveWaitUntil = _collection.ContainsHandler(typeof(IWillSaveWaitUntilTextDocumentHandler))
356-
};
346+
serverCapabilities.TextDocumentSync = textDocumentSyncKind;
347+
}
348+
else
349+
{
350+
serverCapabilities.TextDocumentSync = new TextDocumentSyncOptions()
351+
{
352+
Change = textDocumentSyncKind,
353+
OpenClose = _collection.ContainsHandler(typeof(IDidOpenTextDocumentHandler)) || _collection.ContainsHandler(typeof(IDidCloseTextDocumentHandler)),
354+
Save = _collection.ContainsHandler(typeof(IDidSaveTextDocumentHandler)) ?
355+
new SaveOptions() { IncludeText = true /* TODO: Make configurable */ } :
356+
null,
357+
WillSave = _collection.ContainsHandler(typeof(IWillSaveTextDocumentHandler)),
358+
WillSaveWaitUntil = _collection.ContainsHandler(typeof(IWillSaveWaitUntilTextDocumentHandler))
359+
};
360+
}
357361
}
358362

359363
// TODO: Need a call back here

0 commit comments

Comments
 (0)