Skip to content

Commit f97fdb1

Browse files
Exposed ITextDocumentIdentifier as a top level type instead of just something that exists on a TextDocumentSyncHandler.
1 parent 93f8c56 commit f97fdb1

24 files changed

+556
-2057
lines changed

src/Directory.Build.props

Lines changed: 3 additions & 0 deletions
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

Lines changed: 3 additions & 3 deletions
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

Lines changed: 12 additions & 1 deletion
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

Lines changed: 5 additions & 1 deletion
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

Lines changed: 1 addition & 2 deletions
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

Lines changed: 42 additions & 39 deletions
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

Lines changed: 1 addition & 1 deletion
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
{

src/Server/LanguageServer.cs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ public class LanguageServer : ILanguageServer, IInitializeHandler, IInitializedH
3838
private ClientVersion? _clientVersion;
3939
private readonly ILspReciever _reciever;
4040
private readonly ISerializer _serializer;
41+
private readonly TextDocumentIdentifiers _textDocumentIdentifiers;
4142
private readonly IHandlerCollection _collection;
4243
private readonly IEnumerable<InitializeDelegate> _initializeDelegates;
4344
private readonly IEnumerable<InitializedDelegate> _initializedDelegates;
4445
private readonly IResponseRouter _responseRouter;
4546
private readonly ISubject<InitializeResult> _initializeComplete = new AsyncSubject<InitializeResult>();
4647
private readonly CompositeDisposable _disposable = new CompositeDisposable();
4748
private readonly IServiceProvider _serviceProvider;
48-
private SupportedCapabilities _supportedCapabilities;
49+
private readonly SupportedCapabilities _supportedCapabilities;
4950

5051
public static Task<ILanguageServer> From(Action<LanguageServerOptions> optionsAction)
5152
{
@@ -84,8 +85,11 @@ public static async Task<ILanguageServer> From(LanguageServerOptions options, Ca
8485
options.HandlerTypes.Select(x => x.Assembly)
8586
.Distinct().Concat(options.HandlerAssemblies),
8687
options.Handlers,
88+
options.HandlerTypes,
8789
options.NamedHandlers,
8890
options.NamedServiceHandlers,
91+
options.TextDocumentIdentifiers,
92+
options.TextDocumentIdentifierTypes,
8993
options.InitializeDelegates,
9094
options.InitializedDelegates
9195
);
@@ -118,8 +122,11 @@ public static ILanguageServer PreInit(LanguageServerOptions options)
118122
options.HandlerTypes.Select(x => x.Assembly)
119123
.Distinct().Concat(options.HandlerAssemblies),
120124
options.Handlers,
125+
options.HandlerTypes,
121126
options.NamedHandlers,
122127
options.NamedServiceHandlers,
128+
options.TextDocumentIdentifiers,
129+
options.TextDocumentIdentifierTypes,
123130
options.InitializeDelegates,
124131
options.InitializedDelegates
125132
);
@@ -140,8 +147,11 @@ internal LanguageServer(
140147
IServiceCollection services,
141148
IEnumerable<Assembly> assemblies,
142149
IEnumerable<IJsonRpcHandler> handlers,
150+
IEnumerable<Type> handlerTypes,
143151
IEnumerable<(string name, IJsonRpcHandler handler)> namedHandlers,
144152
IEnumerable<(string name, Func<IServiceProvider, IJsonRpcHandler> handlerFunc)> namedServiceHandlers,
153+
IEnumerable<ITextDocumentIdentifier> textDocumentIdentifiers,
154+
IEnumerable<Type> textDocumentIdentifierTypes,
145155
IEnumerable<InitializeDelegate> initializeDelegates,
146156
IEnumerable<InitializedDelegate> initializedDelegates)
147157
{
@@ -151,19 +161,37 @@ internal LanguageServer(
151161
_reciever = reciever;
152162
_serializer = serializer;
153163
_supportedCapabilities = new SupportedCapabilities();
154-
var collection = new HandlerCollection(_supportedCapabilities);
164+
_textDocumentIdentifiers = new TextDocumentIdentifiers();
165+
var collection = new HandlerCollection(_supportedCapabilities, _textDocumentIdentifiers);
155166
_collection = collection;
156167
_initializeDelegates = initializeDelegates;
157168
_initializedDelegates = initializedDelegates;
158169

159170
services.AddSingleton<IOutputHandler>(outputHandler);
160171
services.AddSingleton(_collection);
172+
services.AddSingleton(_textDocumentIdentifiers);
161173
services.AddSingleton(_serializer);
162174
services.AddSingleton<OmniSharp.Extensions.JsonRpc.ISerializer>(_serializer);
163175
services.AddSingleton(requestProcessIdentifier);
164176
services.AddSingleton<OmniSharp.Extensions.JsonRpc.IReciever>(reciever);
165177
services.AddSingleton<ILspReciever>(reciever);
166178
services.AddSingleton(loggerFactory);
179+
foreach (var item in handlers)
180+
{
181+
services.AddSingleton(item);
182+
}
183+
foreach (var item in textDocumentIdentifiers)
184+
{
185+
services.AddSingleton(item);
186+
}
187+
foreach (var item in handlerTypes)
188+
{
189+
services.AddSingleton(typeof(IJsonRpcHandler), item);
190+
}
191+
foreach (var item in textDocumentIdentifierTypes)
192+
{
193+
services.AddSingleton(typeof(ITextDocumentIdentifier), item);
194+
}
167195

168196
services.AddJsonRpcMediatR(assemblies);
169197
services.AddTransient<IHandlerMatcher, TextDocumentMatcher>();
@@ -208,8 +236,10 @@ internal LanguageServer(
208236
);
209237

210238
var serviceHandlers = _serviceProvider.GetServices<IJsonRpcHandler>().ToArray();
239+
var serviceIdentifiers = _serviceProvider.GetServices<ITextDocumentIdentifier>().ToArray();
240+
_disposable.Add(_textDocumentIdentifiers.Add(serviceIdentifiers));
211241
_disposable.Add(_collection.Add(serviceHandlers));
212-
_disposable.Add(_collection.Add(handlers));
242+
213243
foreach (var (name, handler) in namedHandlers)
214244
{
215245
_disposable.Add(_collection.Add(name, handler));
@@ -219,6 +249,7 @@ internal LanguageServer(
219249
_disposable.Add(_collection.Add(name, handlerFunc(_serviceProvider)));
220250
}
221251

252+
222253
Document = new LanguageServerDocument(_responseRouter);
223254
Client = new LanguageServerClient(_responseRouter);
224255
Window = new LanguageServerWindow(_responseRouter);
@@ -276,6 +307,22 @@ public IDisposable AddHandlers(params Type[] handlerTypes)
276307
return RegisterHandlers(handlerDisposable);
277308
}
278309

310+
public IDisposable AddTextDocumentIdentifier(params ITextDocumentIdentifier[] handlers)
311+
{
312+
var cd = new CompositeDisposable();
313+
foreach (var textDocumentIdentifier in handlers)
314+
{
315+
cd.Add(_textDocumentIdentifiers.Add(textDocumentIdentifier));
316+
}
317+
318+
return cd;
319+
}
320+
321+
public IDisposable AddTextDocumentIdentifier<T>() where T : ITextDocumentIdentifier
322+
{
323+
return _textDocumentIdentifiers.Add(ActivatorUtilities.CreateInstance<T>(_serviceProvider));
324+
}
325+
279326
private IDisposable RegisterHandlers(LspHandlerDescriptorDisposable handlerDisposable)
280327
{
281328
using (var scope = _serviceProvider.CreateScope())

0 commit comments

Comments
 (0)