Skip to content

Commit af789e0

Browse files
Merge pull request #153 from OmniSharp/fix/folding-not-working
Fix language server not working with the latest beta
2 parents 93f8c56 + b589834 commit af789e0

27 files changed

+618
-2073
lines changed

sample/SampleServer/Program.cs

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Threading.Tasks;
44
using Microsoft.Extensions.Logging;
55
using OmniSharp.Extensions.LanguageServer;
6+
using OmniSharp.Extensions.LanguageServer.Protocol.Server;
67
using OmniSharp.Extensions.LanguageServer.Server;
78

89
namespace SampleServer
@@ -29,6 +30,8 @@ static async Task MainAsync(string[] args)
2930
.AddDefaultLoggingProvider()
3031
.WithMinimumLogLevel(LogLevel.Trace)
3132
.WithHandler<TextDocumentHandler>()
33+
.WithHandler<DidChangeWatchedFilesHandler>()
34+
.WithHandler<FoldingRangeHandler>()
3235
);
3336

3437
await server.WaitForExit;

sample/SampleServer/TextDocumentHandler.cs

+55-12
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ class TextDocumentHandler : ITextDocumentSyncHandler
1818
private readonly OmniSharp.Extensions.LanguageServer.Protocol.Server.ILanguageServer _router;
1919

2020
private readonly DocumentSelector _documentSelector = new DocumentSelector(
21-
new DocumentFilter()
22-
{
21+
new DocumentFilter() {
2322
Pattern = "**/*.cs"
2423
}
2524
);
@@ -35,8 +34,7 @@ public TextDocumentHandler(OmniSharp.Extensions.LanguageServer.Protocol.Server.I
3534

3635
public Task<Unit> Handle(DidChangeTextDocumentParams notification, CancellationToken token)
3736
{
38-
_router.Window.LogMessage(new LogMessageParams()
39-
{
37+
_router.Window.LogMessage(new LogMessageParams() {
4038
Type = MessageType.Log,
4139
Message = "Hello World!!!!"
4240
});
@@ -45,8 +43,7 @@ public Task<Unit> Handle(DidChangeTextDocumentParams notification, CancellationT
4543

4644
TextDocumentChangeRegistrationOptions IRegistration<TextDocumentChangeRegistrationOptions>.GetRegistrationOptions()
4745
{
48-
return new TextDocumentChangeRegistrationOptions()
49-
{
46+
return new TextDocumentChangeRegistrationOptions() {
5047
DocumentSelector = _documentSelector,
5148
SyncKind = Change
5249
};
@@ -60,8 +57,7 @@ public void SetCapability(SynchronizationCapability capability)
6057
public async Task<Unit> Handle(DidOpenTextDocumentParams notification, CancellationToken token)
6158
{
6259
await Task.Yield();
63-
_router.Window.LogMessage(new LogMessageParams()
64-
{
60+
_router.Window.LogMessage(new LogMessageParams() {
6561
Type = MessageType.Log,
6662
Message = "Hello World!!!!"
6763
});
@@ -70,8 +66,7 @@ public async Task<Unit> Handle(DidOpenTextDocumentParams notification, Cancellat
7066

7167
TextDocumentRegistrationOptions IRegistration<TextDocumentRegistrationOptions>.GetRegistrationOptions()
7268
{
73-
return new TextDocumentRegistrationOptions()
74-
{
69+
return new TextDocumentRegistrationOptions() {
7570
DocumentSelector = _documentSelector,
7671
};
7772
}
@@ -88,8 +83,7 @@ public Task<Unit> Handle(DidSaveTextDocumentParams notification, CancellationTok
8883

8984
TextDocumentSaveRegistrationOptions IRegistration<TextDocumentSaveRegistrationOptions>.GetRegistrationOptions()
9085
{
91-
return new TextDocumentSaveRegistrationOptions()
92-
{
86+
return new TextDocumentSaveRegistrationOptions() {
9387
DocumentSelector = _documentSelector,
9488
IncludeText = true
9589
};
@@ -99,4 +93,53 @@ public TextDocumentAttributes GetTextDocumentAttributes(Uri uri)
9993
return new TextDocumentAttributes(uri, "csharp");
10094
}
10195
}
96+
97+
class FoldingRangeHandler : IFoldingRangeHandler
98+
{
99+
private FoldingRangeCapability _capability;
100+
101+
public TextDocumentRegistrationOptions GetRegistrationOptions()
102+
{
103+
return new TextDocumentRegistrationOptions() {
104+
DocumentSelector = DocumentSelector.ForLanguage("csharp")
105+
};
106+
}
107+
108+
public Task<Container<FoldingRange>> Handle(FoldingRangeRequestParam request,
109+
CancellationToken cancellationToken)
110+
{
111+
return Task.FromResult(new Container<FoldingRange>(new FoldingRange() {
112+
StartLine = 10,
113+
EndLine = 20,
114+
Kind = FoldingRangeKind.Region,
115+
EndCharacter = 0,
116+
StartCharacter = 0
117+
}));
118+
}
119+
120+
public void SetCapability(FoldingRangeCapability capability)
121+
{
122+
_capability = capability;
123+
}
124+
}
125+
126+
class DidChangeWatchedFilesHandler : IDidChangeWatchedFilesHandler
127+
{
128+
private DidChangeWatchedFilesCapability _capability;
129+
130+
public object GetRegistrationOptions()
131+
{
132+
return new object();
133+
}
134+
135+
public Task<Unit> Handle(DidChangeWatchedFilesParams request, CancellationToken cancellationToken)
136+
{
137+
return Unit.Task;
138+
}
139+
140+
public void SetCapability(DidChangeWatchedFilesCapability capability)
141+
{
142+
_capability = capability;
143+
}
144+
}
102145
}

src/Directory.Build.props

+3
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,8 @@
1818
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
1919
<_Parameter1>Lsp.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100391db875e68eb4bfef49ce14313b9e13f2cd3cc89eb273bbe6c11a55044c7d4f566cf092e1c77ef9e7c75b1496ae7f95d925938f5a01793dd8d9f99ae0a7595779b71b971287d7d7b5960d052078d14f5ce1a85ea5c9fb2f59ac735ff7bc215cab469b7c3486006860bad6f4c3b5204ea2f28dd4e1d05e2cca462cfd593b9f9f</_Parameter1>
2020
</AssemblyAttribute>
21+
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
22+
<_Parameter1>DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7</_Parameter1>
23+
</AssemblyAttribute>
2124
</ItemGroup>
2225
</Project>

src/JsonRpc/JsonRpc.csproj

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<TargetFrameworks>netstandard2.0</TargetFrameworks>
44
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -13,7 +13,7 @@
1313
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
1414
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
1515
<PackageReference Include="Newtonsoft.Json" />
16-
<Compile Include="../../submodules/MediatR/src/MediatR/**/*.cs" Exclude="**/AssemblyInfo.cs" />
17-
<Compile Include="../../submodules/MediatR.Extensions.Microsoft.DependencyInjection/src/MediatR.Extensions.Microsoft.DependencyInjection/**/*.cs" Exclude="**/AssemblyInfo.cs" />
16+
<Compile Include="../../submodules/MediatR/src/MediatR/**/*.cs" Exclude="**/AssemblyInfo.cs" Visible="false" />
17+
<Compile Include="../../submodules/MediatR.Extensions.Microsoft.DependencyInjection/src/MediatR.Extensions.Microsoft.DependencyInjection/**/*.cs" Exclude="**/AssemblyInfo.cs" Visible="false" />
1818
</ItemGroup>
1919
</Project>

src/Protocol/Document/ITextDocumentIdentifier.cs

+12-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,15 @@ public interface ITextDocumentIdentifier
1111
/// <returns></returns>
1212
TextDocumentAttributes GetTextDocumentAttributes(Uri uri);
1313
}
14-
}
14+
15+
public abstract class TextDocumentIdentifierBase : ITextDocumentIdentifier
16+
{
17+
public TextDocumentAttributes GetTextDocumentAttributes(Uri uri)
18+
{
19+
var (languageId, schema) = GetAttributes(uri);
20+
return new TextDocumentAttributes(uri, languageId, schema);
21+
}
22+
23+
protected abstract (string languageId, string schema) GetAttributes(Uri uri);
24+
}
25+
}

src/Protocol/ILanguageServerRegistry.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@
44
// ReSharper disable once CheckNamespace
55
namespace OmniSharp.Extensions.LanguageServer.Protocol.Server
66
{
7-
public interface ILanguageServerRegistry : IJsonRpcHandlerRegistry { }
7+
public interface ILanguageServerRegistry : IJsonRpcHandlerRegistry
8+
{
9+
IDisposable AddTextDocumentIdentifier(params ITextDocumentIdentifier[] handlers);
10+
IDisposable AddTextDocumentIdentifier<T>() where T : ITextDocumentIdentifier;
11+
}
812
}

src/Server/Abstractions/IHandlerCollection.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace OmniSharp.Extensions.LanguageServer.Server.Abstractions
88
{
9-
public interface IHandlerCollection : IEnumerable<ILspHandlerDescriptor>
9+
internal interface IHandlerCollection : IEnumerable<ILspHandlerDescriptor>
1010
{
1111
LspHandlerDescriptorDisposable Add(params IJsonRpcHandler[] handlers);
1212
LspHandlerDescriptorDisposable Add(params Type[] handlerTypes);
@@ -15,6 +15,5 @@ public interface IHandlerCollection : IEnumerable<ILspHandlerDescriptor>
1515
LspHandlerDescriptorDisposable Add(string method, Type handlerType);
1616
bool ContainsHandler(Type type);
1717
bool ContainsHandler(TypeInfo typeInfo);
18-
IEnumerable<ITextDocumentIdentifier> TextDocumentIdentifiers();
1918
}
2019
}

src/Server/HandlerCollection.cs

+42-39
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,23 @@ class HandlerCollection : IHandlerCollection
1717
.GetTypeInfo()
1818
.GetMethod(nameof(GetRegistration), BindingFlags.NonPublic | BindingFlags.Static);
1919
private readonly ISupportedCapabilities _supportedCapabilities;
20-
private readonly HashSet<HandlerDescriptor> _textDocumentIdentifiers = new HashSet<HandlerDescriptor>();
20+
private readonly TextDocumentIdentifiers _textDocumentIdentifiers;
2121
internal readonly HashSet<HandlerDescriptor> _handlers = new HashSet<HandlerDescriptor>();
2222
private IServiceProvider _serviceProvider;
2323

2424

25-
public HandlerCollection(ISupportedCapabilities supportedCapabilities)
25+
public HandlerCollection(ISupportedCapabilities supportedCapabilities,
26+
TextDocumentIdentifiers textDocumentIdentifiers)
2627
{
2728
_supportedCapabilities = supportedCapabilities;
29+
_textDocumentIdentifiers = textDocumentIdentifiers;
2830
}
2931

3032
public void SetServiceProvider(IServiceProvider serviceProvider)
3133
{
3234
_serviceProvider = serviceProvider;
3335
}
3436

35-
public IEnumerable<ITextDocumentIdentifier> TextDocumentIdentifiers()
36-
{
37-
return _textDocumentIdentifiers
38-
.Select(descriptor => descriptor.Handler)
39-
.OfType<ITextDocumentIdentifier>();
40-
}
41-
4237
public IEnumerator<ILspHandlerDescriptor> GetEnumerator()
4338
{
4439
return _handlers.GetEnumerator();
@@ -53,74 +48,85 @@ public LspHandlerDescriptorDisposable Add(string method, IJsonRpcHandler handler
5348
{
5449
var descriptor = GetDescriptor(method, handler.GetType(), handler);
5550
_handlers.Add(descriptor);
56-
return new LspHandlerDescriptorDisposable(descriptor);
51+
var cd = new CompositeDisposable();
52+
if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier)
53+
{
54+
cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier));
55+
}
56+
return new LspHandlerDescriptorDisposable(new[] { descriptor }, cd);
5757
}
5858

5959
public LspHandlerDescriptorDisposable Add(string method, Func<IServiceProvider, IJsonRpcHandler> handlerFunc)
6060
{
6161
var handler = handlerFunc(_serviceProvider);
6262
var descriptor = GetDescriptor(method, handler.GetType(), handler);
6363
_handlers.Add(descriptor);
64-
return new LspHandlerDescriptorDisposable(descriptor);
64+
var cd = new CompositeDisposable();
65+
if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier)
66+
{
67+
_textDocumentIdentifiers.Add(textDocumentIdentifier);
68+
}
69+
return new LspHandlerDescriptorDisposable(new[] { descriptor }, cd);
6570
}
6671

6772
public LspHandlerDescriptorDisposable Add(string method, Type handlerType)
6873
{
6974
var descriptor = GetDescriptor(method, handlerType, _serviceProvider);
7075
_handlers.Add(descriptor);
71-
return new LspHandlerDescriptorDisposable(descriptor);
76+
var cd = new CompositeDisposable();
77+
if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier)
78+
{
79+
cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier));
80+
}
81+
return new LspHandlerDescriptorDisposable(new [] {descriptor }, cd);
7282
}
7383

7484
public LspHandlerDescriptorDisposable Add(params Type[] handlerTypes)
7585
{
7686
var descriptors = new HashSet<HandlerDescriptor>();
87+
var cd = new CompositeDisposable();
7788
foreach (var handlerType in handlerTypes)
7889
{
7990
foreach (var (method, implementedInterface) in handlerType.GetTypeInfo()
8091
.ImplementedInterfaces
8192
.Select(x => (method: LspHelper.GetMethodName(x), implementedInterface: x))
8293
.Where(x => !string.IsNullOrWhiteSpace(x.method)))
8394
{
84-
descriptors.Add(GetDescriptor(method, implementedInterface, _serviceProvider));
85-
}
86-
}
87-
88-
foreach (var descriptor in descriptors)
89-
{
90-
_handlers.Add(descriptor);
91-
if (typeof(ITextDocumentIdentifier).IsAssignableFrom(descriptor.ImplementationType))
92-
{
93-
_textDocumentIdentifiers.Add(descriptor);
95+
var descriptor = GetDescriptor(method, implementedInterface, _serviceProvider);
96+
descriptors.Add(descriptor);
97+
_handlers.Add(descriptor);
98+
if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier)
99+
{
100+
cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier));
101+
}
94102
}
95103
}
96104

97-
return new LspHandlerDescriptorDisposable(descriptors);
105+
return new LspHandlerDescriptorDisposable(descriptors, cd);
98106
}
99107

100108
public LspHandlerDescriptorDisposable Add(params IJsonRpcHandler[] handlers)
101109
{
102110
var descriptors = new HashSet<HandlerDescriptor>();
111+
var cd = new CompositeDisposable();
103112
foreach (var handler in handlers)
104113
{
105114
foreach (var (method, implementedInterface) in handler.GetType().GetTypeInfo()
106115
.ImplementedInterfaces
107116
.Select(x => (method: LspHelper.GetMethodName(x), implementedInterface: x))
108117
.Where(x => !string.IsNullOrWhiteSpace(x.method)))
109118
{
110-
descriptors.Add(GetDescriptor(method, implementedInterface, handler));
111-
}
112-
}
113-
114-
foreach (var descriptor in descriptors)
115-
{
116-
_handlers.Add(descriptor);
117-
if (descriptor.Handler is ITextDocumentIdentifier)
118-
{
119-
_textDocumentIdentifiers.Add(descriptor);
119+
var descriptor = GetDescriptor(method, implementedInterface, handler);
120+
descriptors.Add(descriptor);
121+
_handlers.Add(descriptor);
122+
if (descriptor.Handler is ITextDocumentIdentifier textDocumentIdentifier)
123+
{
124+
cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier));
125+
}
120126
}
121127
}
122128

123-
return new LspHandlerDescriptorDisposable(descriptors);
129+
return new LspHandlerDescriptorDisposable(descriptors, cd);
124130
}
125131

126132
private HandlerDescriptor GetDescriptor(string method, Type handlerType, IServiceProvider serviceProvider)
@@ -153,8 +159,7 @@ private HandlerDescriptor GetDescriptor(string method, Type handlerType, IJsonRp
153159

154160
if (_supportedCapabilities.AllowsDynamicRegistration(capabilityType))
155161
{
156-
registration = new Registration()
157-
{
162+
registration = new Registration() {
158163
Id = Guid.NewGuid().ToString(),
159164
Method = method,
160165
RegisterOptions = registrationOptions
@@ -190,10 +195,8 @@ private HandlerDescriptor GetDescriptor(string method, Type handlerType, IJsonRp
190195
registrationType,
191196
registration,
192197
capabilityType,
193-
() =>
194-
{
198+
() => {
195199
_handlers.RemoveWhere(d => d.Handler == handler);
196-
_textDocumentIdentifiers.RemoveWhere(d => d.Handler == handler);
197200
});
198201

199202
return descriptor;

src/Server/HandlerCollectionExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace OmniSharp.Extensions.LanguageServer.Server
88
{
9-
public static class HandlerCollectionExtensions
9+
static class HandlerCollectionExtensions
1010
{
1111
public static LspHandlerDescriptorDisposable Add(this IHandlerCollection collection, IEnumerable<IJsonRpcHandler> handlers)
1212
{

0 commit comments

Comments
 (0)