Skip to content

Commit 2b60c71

Browse files
Breaking: LSP ISerializer interface is now deprecated, and marked obsolete. (#432)
* LSP Serializer renamed to LSPSerializer * Added serialization rules for client * Ensure code actions are provided properly. * Updated serialization rules for server
1 parent 7b4f140 commit 2b60c71

File tree

129 files changed

+555
-456
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+555
-456
lines changed

Directory.Build.targets

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project>
3+
<PropertyGroup>
4+
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
5+
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<Compile Condition="'$(DesignTimeBuild)' == 'true' and '$(IDEA_INITIAL_DIRECTORY)' != ''" Include="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
9+
</ItemGroup>
310
<ItemGroup>
411
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
512
<PackageReference Include="Rocket.Surgery.MSBuild.CI" Version="1.1.0" PrivateAssets="All" />

src/Client/LanguageClient.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using OmniSharp.Extensions.LanguageServer.Protocol.General;
2222
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
2323
using OmniSharp.Extensions.LanguageServer.Protocol.Progress;
24+
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;
2425
using OmniSharp.Extensions.LanguageServer.Protocol.Workspace;
2526
using OmniSharp.Extensions.LanguageServer.Shared;
2627
// ReSharper disable SuspiciousTypeConversion.Global
@@ -44,7 +45,7 @@ public class LanguageClient : JsonRpcServerBase, ILanguageClient
4445
private readonly IEnumerable<IOnLanguageClientInitialize> _initializeHandlers;
4546
private readonly IEnumerable<OnLanguageClientInitializedDelegate> _initializedDelegates;
4647
private readonly IEnumerable<IOnLanguageClientInitialized> _initializedHandlers;
47-
private readonly ISerializer _serializer;
48+
private readonly LspSerializer _serializer;
4849
private readonly InstanceHasStarted _instanceHasStarted;
4950
private readonly IResponseRouter _responseRouter;
5051
private readonly ISubject<InitializeResult> _initializeComplete = new AsyncSubject<InitializeResult>();
@@ -145,7 +146,7 @@ internal LanguageClient(
145146
ILanguageClientWorkspaceFoldersManager languageClientWorkspaceFoldersManager, IEnumerable<OnLanguageClientInitializeDelegate> initializeDelegates,
146147
IEnumerable<IOnLanguageClientInitialize> initializeHandlers, IEnumerable<OnLanguageClientInitializedDelegate> initializedDelegates,
147148
IEnumerable<IOnLanguageClientInitialized> initializedHandlers,
148-
ISerializer serializer,
149+
LspSerializer serializer,
149150
InstanceHasStarted instanceHasStarted
150151
) : base(handlerCollection, responseRouter)
151152
{
@@ -162,7 +163,7 @@ InstanceHasStarted instanceHasStarted
162163
_initializationOptions = options.Value.InitializationOptions;
163164
_settingsBag = languageProtocolSettingsBag;
164165
_collection = handlerCollection;
165-
Services = _resolverContext = resolverContext;
166+
Services = _resolverContext = resolverContext;
166167

167168
_responseRouter = responseRouter;
168169
ProgressManager = progressManager;
@@ -268,6 +269,7 @@ await LanguageProtocolEventingHelper.Run(
268269
var serverParams = await SendRequest(ClientSettings, token).ConfigureAwait(false);
269270

270271
ServerSettings = serverParams;
272+
_serializer.SetServerCapabilities(serverParams.Capabilities);
271273

272274
await LanguageProtocolEventingHelper.Run(
273275
_initializedDelegates,
@@ -385,7 +387,7 @@ private Supports<T> UseOrTryAndFindCapability<T>(Supports<T> supports) where T :
385387

386388
public IObservable<InitializeResult> Start => _initializeComplete.AsObservable();
387389

388-
bool IResponseRouter.TryGetRequest(long id, [NotNullWhen(true)] out string method, [NotNullWhen(true)]out TaskCompletionSource<JToken> pendingTask) =>
390+
bool IResponseRouter.TryGetRequest(long id, [NotNullWhen(true)] out string method, [NotNullWhen(true)] out TaskCompletionSource<JToken> pendingTask) =>
389391
_responseRouter.TryGetRequest(id, out method, out pendingTask);
390392

391393
public Task<InitializeResult> WasStarted => _initializeComplete.ToTask();

src/Protocol/LanguageProtocolRpcOptionsBase.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ public T AddTextDocumentIdentifier(params ITextDocumentIdentifier[] handlers)
2424
Services.AddSingleton(typeof(ITextDocumentIdentifier), item);
2525
}
2626

27-
return (T) (object) this;
27+
return (T)(object)this;
2828
}
2929

3030
public T AddTextDocumentIdentifier<TI>() where TI : ITextDocumentIdentifier
3131
{
3232
Services.AddSingleton(typeof(ITextDocumentIdentifier), typeof(TI));
33-
return (T) (object) this;
33+
return (T)(object)this;
3434
}
3535

36-
public ISerializer Serializer { get; set; } = new Serializer(ClientVersion.Lsp3);
36+
public ISerializer Serializer { get; set; } = new LspSerializer(ClientVersion.Lsp3);
3737
internal bool AddDefaultLoggingProvider { get; set; }
3838
internal Action<ILoggingBuilder>? LoggingBuilderAction { get; set; } = _ => { };
3939
internal Action<IConfigurationBuilder>? ConfigurationBuilderAction { get; set; } = _ => { };

src/Protocol/Models/CodeActionKind.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
4+
using System.Linq;
5+
using System.Reflection;
36
using Newtonsoft.Json;
47
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Converters;
58

@@ -12,6 +15,19 @@ namespace OmniSharp.Extensions.LanguageServer.Protocol.Models
1215
[JsonConverter(typeof(EnumLikeStringConverter))]
1316
public readonly struct CodeActionKind : IEquatable<CodeActionKind>, IEnumLikeString
1417
{
18+
private static readonly Lazy<IReadOnlyList<CodeActionKind>> _defaults =
19+
new Lazy<IReadOnlyList<CodeActionKind>>(
20+
() => {
21+
return typeof(CodeActionKind)
22+
.GetFields(BindingFlags.Static | BindingFlags.Public)
23+
.Select(z => z.GetValue(null))
24+
.Cast<CodeActionKind>()
25+
.ToArray();
26+
}
27+
);
28+
29+
public static IEnumerable<CodeActionKind> Defaults => _defaults.Value;
30+
1531
/// <summary>
1632
/// Base kind for quickfix actions: ''
1733
/// </summary>

src/Protocol/Models/Proposals/SemanticTokensLegend.cs

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,15 @@ public class SemanticTokensLegend
1414
private ImmutableDictionary<SemanticTokenModifier, int>? _tokenModifiersData;
1515
private ImmutableDictionary<SemanticTokenType, int>? _tokenTypesData;
1616

17-
private Container<string> _tokenTypes = new Container<string>(
18-
SemanticTokenType
19-
.Defaults
20-
.Select(z => (string) z)
21-
.ToArray()
22-
);
23-
24-
private Container<string> _tokenModifiers = new Container<string>(
25-
SemanticTokenModifier
26-
.Defaults
27-
.Select(z => (string) z)
28-
.ToArray()
29-
);
30-
3117
/// <summary>
3218
/// The token types a server uses.
3319
/// </summary>
34-
public Container<string> TokenTypes
35-
{
36-
get => _tokenTypes;
37-
set {
38-
_tokenTypes = value;
39-
_tokenTypesData = null;
40-
}
41-
}
20+
public Container<SemanticTokenType> TokenTypes { get; set; } = new Container<SemanticTokenType>(SemanticTokenType.Defaults);
4221

4322
/// <summary>
4423
/// The token modifiers a server uses.
4524
/// </summary>
46-
public Container<string> TokenModifiers
47-
{
48-
get => _tokenModifiers;
49-
set {
50-
_tokenModifiers = value;
51-
_tokenModifiersData = null;
52-
}
53-
}
25+
public Container<SemanticTokenModifier> TokenModifiers { get; set; } = new Container<SemanticTokenModifier>(SemanticTokenModifier.Defaults);
5426

5527
public int GetTokenTypeIdentity(string tokenType)
5628
{

src/Protocol/Protocol.csproj

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77
<PackageDescription>Language Server Protocol models, classes, interfaces and helper methods</PackageDescription>
88
</PropertyGroup>
99

10-
<PropertyGroup>
11-
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
12-
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
13-
</PropertyGroup>
14-
1510
<ItemGroup>
1611
<PackageReference Include="Microsoft.Extensions.Configuration" />
1712
<!--
@@ -20,6 +15,13 @@
2015
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" />
2116
-->
2217
</ItemGroup>
18+
<PropertyGroup>
19+
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
20+
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GeneratedFiles</CompilerGeneratedFilesOutputPath>
21+
</PropertyGroup>
22+
<ItemGroup>
23+
<Compile Condition="'$(DesignTimeBuild)' == 'true' and '$(IDEA_INITIAL_DIRECTORY)' != ''" Include="$(CompilerGeneratedFilesOutputPath)/**/*.cs" />
24+
</ItemGroup>
2325

2426
<ItemGroup>
2527
<ProjectReference Include="..\JsonRpc\JsonRpc.csproj" />

src/Protocol/Serialization/ISerializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization
44
{
5+
[System.Obsolete("This interface is deprecated and will be removed in the future")]
56
public interface ISerializer : JsonRpc.ISerializer
67
{
7-
void SetClientCapabilities(ClientVersion clientVersion, ClientCapabilities clientCapabilities);
88
}
99
}

src/Protocol/Serialization/LspContractResolver.cs

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,42 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Collections.Immutable;
34
using System.Linq;
45
using System.Reflection;
56
using Newtonsoft.Json;
67
using Newtonsoft.Json.Serialization;
78
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
89
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
10+
using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals;
911

1012
#pragma warning disable 618
1113

1214
namespace OmniSharp.Extensions.LanguageServer.Protocol.Serialization
1315
{
1416
internal class LspContractResolver : DefaultContractResolver
1517
{
16-
private readonly CompletionItemKind[] _completionItemKinds;
17-
private readonly CompletionItemTag[] _completionItemTags;
18-
private readonly SymbolKind[] _documentSymbolKinds;
19-
private readonly SymbolKind[] _workspaceSymbolKinds;
20-
private readonly SymbolTag[] _documentSymbolTags;
21-
private readonly SymbolTag[] _workspaceSymbolTags;
22-
private readonly DiagnosticTag[] _diagnosticTags;
23-
private readonly CodeActionKind[] _codeActionKinds;
18+
private readonly ImmutableArray<CompletionItemKind> _completionItemKinds;
19+
private readonly ImmutableArray<CompletionItemTag> _completionItemTags;
20+
private readonly ImmutableArray<SymbolKind> _documentSymbolKinds;
21+
private readonly ImmutableArray<SymbolKind> _workspaceSymbolKinds;
22+
private readonly ImmutableArray<SymbolTag> _documentSymbolTags;
23+
private readonly ImmutableArray<SymbolTag> _workspaceSymbolTags;
24+
private readonly ImmutableArray<DiagnosticTag> _diagnosticTags;
25+
private readonly ImmutableArray<CodeActionKind> _codeActionKinds;
26+
private readonly ImmutableArray<SemanticTokenType> _semanticTokenType;
27+
private readonly ImmutableArray<SemanticTokenModifier> _semanticTokenModifier;
2428

2529
public LspContractResolver(
26-
CompletionItemKind[] completionItemKinds,
27-
CompletionItemTag[] completionItemTags,
28-
SymbolKind[] documentSymbolKinds,
29-
SymbolKind[] workspaceSymbolKinds,
30-
SymbolTag[] documentSymbolTags,
31-
SymbolTag[] workspaceSymbolTags,
32-
DiagnosticTag[] diagnosticTags,
33-
CodeActionKind[] codeActionKinds
30+
ImmutableArray<CompletionItemKind> completionItemKinds,
31+
ImmutableArray<CompletionItemTag> completionItemTags,
32+
ImmutableArray<SymbolKind> documentSymbolKinds,
33+
ImmutableArray<SymbolKind> workspaceSymbolKinds,
34+
ImmutableArray<SymbolTag> documentSymbolTags,
35+
ImmutableArray<SymbolTag> workspaceSymbolTags,
36+
ImmutableArray<DiagnosticTag> diagnosticTags,
37+
ImmutableArray<CodeActionKind> codeActionKinds,
38+
ImmutableArray<SemanticTokenType> semanticTokenType,
39+
ImmutableArray<SemanticTokenModifier> semanticTokenModifier
3440
)
3541
{
3642
_completionItemKinds = completionItemKinds;
@@ -41,6 +47,8 @@ CodeActionKind[] codeActionKinds
4147
_workspaceSymbolTags = workspaceSymbolTags;
4248
_diagnosticTags = diagnosticTags;
4349
_codeActionKinds = codeActionKinds;
50+
_semanticTokenType = semanticTokenType;
51+
_semanticTokenModifier = semanticTokenModifier;
4452
NamingStrategy = new CamelCaseNamingStrategy(true, false, true);
4553
}
4654

@@ -83,13 +91,13 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
8391

8492
if (property.DeclaringType == typeof(CompletionItem))
8593
{
86-
if (property.PropertyType == typeof(CompletionItemKind))
94+
if (property.PropertyType == typeof(CompletionItemKind) && _completionItemKinds is { Length: > 0 })
8795
{
8896
property.ValueProvider =
8997
new RangeValueProvider<CompletionItemKind>(property.ValueProvider, _completionItemKinds);
9098
}
9199

92-
if (property.PropertyType == typeof(Container<CompletionItemTag>))
100+
if (property.PropertyType == typeof(Container<CompletionItemTag>) && _completionItemTags is { Length: > 0 })
93101
{
94102
property.ValueProvider =
95103
new ArrayRangeValueProvider<CompletionItemTag>(property.ValueProvider, _completionItemTags);
@@ -98,13 +106,13 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
98106

99107
if (property.DeclaringType == typeof(DocumentSymbol))
100108
{
101-
if (property.PropertyType == typeof(SymbolKind))
109+
if (property.PropertyType == typeof(SymbolKind) && _documentSymbolKinds is { Length: > 0 })
102110
{
103111
property.ValueProvider =
104112
new RangeValueProvider<SymbolKind>(property.ValueProvider, _documentSymbolKinds);
105113
}
106114

107-
if (property.PropertyType == typeof(Container<SymbolTag>))
115+
if (property.PropertyType == typeof(Container<SymbolTag>) && _documentSymbolTags is { Length: > 0 })
108116
{
109117
property.ValueProvider =
110118
new ArrayRangeValueProvider<SymbolTag>(property.ValueProvider, _documentSymbolTags);
@@ -113,7 +121,7 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
113121

114122
if (property.DeclaringType == typeof(Diagnostic))
115123
{
116-
if (property.PropertyType == typeof(Container<DiagnosticTag>))
124+
if (property.PropertyType == typeof(Container<DiagnosticTag>) && _diagnosticTags is { Length: > 0 })
117125
{
118126
property.ValueProvider =
119127
new ArrayRangeValueProvider<DiagnosticTag>(property.ValueProvider, _diagnosticTags);
@@ -122,7 +130,7 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
122130

123131
if (property.DeclaringType == typeof(CodeAction))
124132
{
125-
if (property.PropertyType == typeof(CodeActionKind))
133+
if (property.PropertyType == typeof(CodeActionKind) && _codeActionKinds is { Length: > 0 })
126134
{
127135
property.ValueProvider =
128136
new RangeValueProvider<CodeActionKind>(property.ValueProvider, _codeActionKinds);
@@ -131,19 +139,33 @@ protected override JsonProperty CreateProperty(MemberInfo member, MemberSerializ
131139

132140
if (property.DeclaringType == typeof(SymbolInformation))
133141
{
134-
if (property.PropertyType == typeof(SymbolKind))
142+
if (property.PropertyType == typeof(SymbolKind) && _workspaceSymbolKinds is { Length: > 0 })
135143
{
136144
property.ValueProvider =
137145
new RangeValueProvider<SymbolKind>(property.ValueProvider, _workspaceSymbolKinds);
138146
}
139147

140-
if (property.PropertyType == typeof(Container<SymbolTag>))
148+
if (property.PropertyType == typeof(Container<SymbolTag>) && _workspaceSymbolTags is { Length: > 0 })
141149
{
142150
property.ValueProvider =
143151
new ArrayRangeValueProvider<SymbolTag>(property.ValueProvider, _workspaceSymbolTags);
144152
}
145153
}
146154

155+
// TODO: Registration needs to be switched around to pass in the capability
156+
// if (property.DeclaringType == typeof(SemanticTokensLegend))
157+
// {
158+
// if (property.PropertyName == nameof(SemanticTokensLegend.TokenModifiers) && _semanticTokenModifier is { Length: > 0 })
159+
// {
160+
// property.ValueProvider = new ArrayRangeValueProvider<SemanticTokenModifier>(property.ValueProvider, _semanticTokenModifier);
161+
// }
162+
//
163+
// if (property.PropertyName == nameof(SemanticTokensLegend.TokenTypes) && _semanticTokenType is { Length: > 0 })
164+
// {
165+
// property.ValueProvider = new ArrayRangeValueProvider<SemanticTokenType>(property.ValueProvider, _semanticTokenType);
166+
// }
167+
// }
168+
147169
return property;
148170
}
149171

@@ -165,10 +187,10 @@ private class RangeValueProvider<T> : IValueProvider
165187
where T : struct
166188
{
167189
private readonly IValueProvider _valueProvider;
168-
private readonly T[] _validValues;
190+
private readonly ImmutableArray<T> _validValues;
169191
private readonly T _defaultValue;
170192

171-
public RangeValueProvider(IValueProvider valueProvider, T[] validValues)
193+
public RangeValueProvider(IValueProvider valueProvider, ImmutableArray<T> validValues)
172194
{
173195
_valueProvider = valueProvider;
174196
_validValues = validValues;
@@ -193,9 +215,9 @@ private class ArrayRangeValueProvider<T> : IValueProvider
193215
where T : struct
194216
{
195217
private readonly IValueProvider _valueProvider;
196-
private readonly T[] _validValues;
218+
private readonly ImmutableArray<T> _validValues;
197219

198-
public ArrayRangeValueProvider(IValueProvider valueProvider, T[] validValues)
220+
public ArrayRangeValueProvider(IValueProvider valueProvider, ImmutableArray<T> validValues)
199221
{
200222
_valueProvider = valueProvider;
201223
_validValues = validValues;

0 commit comments

Comments
 (0)