|
11 | 11 | using OmniSharp.Extensions.JsonRpc.Server; |
12 | 12 | using OmniSharp.Extensions.JsonRpc.Server.Messages; |
13 | 13 | using OmniSharp.Extensions.LanguageServer.Abstractions; |
| 14 | +using OmniSharp.Extensions.LanguageServer.Capabilities.Server; |
14 | 15 | using OmniSharp.Extensions.LanguageServer.Messages; |
15 | 16 | using OmniSharp.Extensions.LanguageServer.Models; |
16 | 17 | using OmniSharp.Extensions.LanguageServer.Protocol.Document; |
17 | 18 |
|
18 | 19 | namespace OmniSharp.Extensions.LanguageServer |
19 | 20 | { |
20 | | - class LspRequestRouter : IRequestRouter |
| 21 | + internal class LspRequestRouter : IRequestRouter |
21 | 22 | { |
22 | 23 | private readonly IHandlerCollection _collection; |
| 24 | + private readonly IEnumerable<IHandlerMatcher> _routeMatchers; |
23 | 25 | private readonly ConcurrentDictionary<string, CancellationTokenSource> _requests = new ConcurrentDictionary<string, CancellationTokenSource>(); |
24 | 26 | private readonly ILogger<LspRequestRouter> _logger; |
25 | 27 |
|
26 | | - public LspRequestRouter(IHandlerCollection collection, ILoggerFactory loggerFactory) |
| 28 | + public LspRequestRouter(IHandlerCollection collection, |
| 29 | + ILoggerFactory loggerFactory, |
| 30 | + IHandlerMatcherCollection routeMatchers) |
27 | 31 | { |
28 | 32 | _collection = collection; |
| 33 | + _routeMatchers = routeMatchers; |
29 | 34 | _logger = loggerFactory.CreateLogger<LspRequestRouter>(); |
30 | 35 | } |
31 | 36 |
|
@@ -59,78 +64,13 @@ private ILspHandlerDescriptor FindDescriptor(string method, JToken @params) |
59 | 64 | return null; |
60 | 65 | } |
61 | 66 |
|
62 | | - if (@params != null && descriptor.Params != null) |
63 | | - { |
64 | | - var paramsValue = @params.ToObject(descriptor.Params); |
65 | | - if (paramsValue is ITextDocumentIdentifierParams textDocumentIdentifierParams) |
66 | | - { |
67 | | - var attributes = GetTextDocumentAttributes(textDocumentIdentifierParams.TextDocument.Uri); |
68 | | - |
69 | | - _logger.LogTrace("Found attributes {Count}, {Attributes}", attributes.Count, attributes.Select(x => $"{x.LanguageId}:{x.Scheme}:{x.Uri}")); |
70 | | - |
71 | | - return GetHandler(method, attributes); |
72 | | - } |
73 | | - else if (paramsValue is DidOpenTextDocumentParams openTextDocumentParams) |
74 | | - { |
75 | | - var attributes = new TextDocumentAttributes(openTextDocumentParams.TextDocument.Uri, openTextDocumentParams.TextDocument.LanguageId); |
76 | | - |
77 | | - _logger.LogTrace("Created attribute {Attribute}", $"{attributes.LanguageId}:{attributes.Scheme}:{attributes.Uri}"); |
| 67 | + if (@params == null || descriptor.Params == null) return descriptor; |
78 | 68 |
|
79 | | - return GetHandler(method, attributes); |
80 | | - } |
81 | | - else if (paramsValue is DidChangeTextDocumentParams didChangeDocumentParams) |
82 | | - { |
83 | | - // TODO: Do something with document version here? |
84 | | - var attributes = GetTextDocumentAttributes(didChangeDocumentParams.TextDocument.Uri); |
| 69 | + var paramsValue = @params.ToObject(descriptor.Params); |
85 | 70 |
|
86 | | - _logger.LogTrace("Found attributes {Count}, {Attributes}", attributes.Count, attributes.Select(x => $"{x.LanguageId}:{x.Scheme}:{x.Uri}")); |
| 71 | + var lspHandlerDescriptors = _collection.Where(handler => handler.Method == method).ToList(); |
87 | 72 |
|
88 | | - return GetHandler(method, attributes); |
89 | | - } |
90 | | - } |
91 | | - |
92 | | - // TODO: How to split these |
93 | | - // Do they fork and join? |
94 | | - return descriptor; |
95 | | - } |
96 | | - |
97 | | - private List<TextDocumentAttributes> GetTextDocumentAttributes(Uri uri) |
98 | | - { |
99 | | - var textDocumentSyncHandlers = _collection |
100 | | - .Select(x => x.Handler is ITextDocumentSyncHandler r ? r : null) |
101 | | - .Where(x => x != null) |
102 | | - .Distinct(); |
103 | | - return textDocumentSyncHandlers |
104 | | - .Select(x => x.GetTextDocumentAttributes(uri)) |
105 | | - .Where(x => x != null) |
106 | | - .Distinct() |
107 | | - .ToList(); |
108 | | - } |
109 | | - |
110 | | - private ILspHandlerDescriptor GetHandler(string method, IEnumerable<TextDocumentAttributes> attributes) |
111 | | - { |
112 | | - return attributes |
113 | | - .Select(x => GetHandler(method, x)) |
114 | | - .FirstOrDefault(x => x != null); |
115 | | - } |
116 | | - |
117 | | - private ILspHandlerDescriptor GetHandler(string method, TextDocumentAttributes attributes) |
118 | | - { |
119 | | - _logger.LogTrace("Looking for handler for method {Method}", method); |
120 | | - foreach (var handler in _collection.Where(x => x.Method == method)) |
121 | | - { |
122 | | - _logger.LogTrace("Checking handler {Method}:{Handler}", method, handler.Handler.GetType().FullName); |
123 | | - var registrationOptions = handler.Registration.RegisterOptions as TextDocumentRegistrationOptions; |
124 | | - |
125 | | - _logger.LogTrace("Registration options {OptionsName}", registrationOptions.GetType().FullName); |
126 | | - _logger.LogTrace("Document Selector {DocumentSelector}", registrationOptions.DocumentSelector.ToString()); |
127 | | - if (registrationOptions.DocumentSelector == null || registrationOptions.DocumentSelector.IsMatch(attributes)) |
128 | | - { |
129 | | - _logger.LogTrace("Handler Selected: {Handler} via {DocumentSelector} (targeting {HandlerInterface})", handler.Handler.GetType().FullName, registrationOptions.DocumentSelector.ToString(), handler.HandlerType.GetType().FullName); |
130 | | - return handler; |
131 | | - } |
132 | | - } |
133 | | - return null; |
| 73 | + return _routeMatchers.SelectMany(strat => strat.FindHandler(paramsValue, lspHandlerDescriptors)).FirstOrDefault() ?? descriptor; |
134 | 74 | } |
135 | 75 |
|
136 | 76 | public async Task RouteNotification(IHandlerDescriptor handler, Notification notification) |
@@ -192,7 +132,6 @@ public async Task<ErrorResponse> RouteRequest(IHandlerDescriptor descriptor, Req |
192 | 132 |
|
193 | 133 | await result.ConfigureAwait(false); |
194 | 134 |
|
195 | | - |
196 | 135 | object responseValue = null; |
197 | 136 | if (result.GetType().GetTypeInfo().IsGenericType) |
198 | 137 | { |
|
0 commit comments