Skip to content

Commit 00c92e9

Browse files
author
N. Taylor Mullen
committed
Upgrade OmniSharp to 0.19.4.
- With the latest OmniSharp upgrade there were a few high profile changes: - Most DTO's are records now which makes them immutable. You'll see throughout the codebase that we now have to use `with {...}` to translate one type to another. - `ServerCapabilities` are expandable by default. This means we no longer need our `ExtendableServerCapabilities` type. - Getting client and server capabilities in each of our endpoints are now a single method call. This resulted in lots of deleted code. - O# upgraded its LSP version to 3.17 which means semantic tokens are no longer proposed. This resulted in a lot of warnings/obsolete bits getting removed. We now also have code action resolution as part of this upgrade so we could remove our old code action resolution endpoint (it's in VSCode now too). - The way the O# serializer gets construed now is different and extendable. Because of this we now have a primary method to add all of our converters to an O# serializer. - O# embraced the optional vs. required text document identifiers. This makes it super clear whenever we're expected to provided a document version or not. Probably one of my favorite changes in the upgrade. - A new dependency of `System.Threading.Channels` was introduced so we had to make sure that was included in our VS scenarios. - This changeset is in preparation for another O# release where we'll replace the [O# request invoker](OmniSharp/csharp-language-server-protocol#641) to get some pretty massive perf wins! Fixes dotnet/aspnetcore#35622
1 parent 6b32699 commit 00c92e9

File tree

66 files changed

+476
-591
lines changed

Some content is hidden

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

66 files changed

+476
-591
lines changed

eng/Versions.props

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
<MonoDevelopSdkPackageVersion>1.0.15</MonoDevelopSdkPackageVersion>
126126
<MoqPackageVersion>4.16.0</MoqPackageVersion>
127127
<NerdbankStreamsPackageVersion>2.7.74</NerdbankStreamsPackageVersion>
128-
<OmniSharpExtensionsLanguageServerPackageVersion>0.18.1</OmniSharpExtensionsLanguageServerPackageVersion>
128+
<OmniSharpExtensionsLanguageServerPackageVersion>0.19.4</OmniSharpExtensionsLanguageServerPackageVersion>
129129
<OmniSharpMSBuildPackageVersion>1.37.13</OmniSharpMSBuildPackageVersion>
130130
<StreamJsonRpcPackageVersion>2.8.21</StreamJsonRpcPackageVersion>
131131
<Tooling_MicrosoftCodeAnalysisAnalyzersPackageVersion>3.3.2</Tooling_MicrosoftCodeAnalysisAnalyzersPackageVersion>

src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/CompletionListSerializationBenchmark.cs

+11-8
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
using Microsoft.AspNetCore.Razor.Language;
77
using Microsoft.AspNetCore.Razor.LanguageServer.Completion;
88
using Microsoft.CodeAnalysis.Razor.Completion;
9-
using Microsoft.CodeAnalysis.Razor.Serialization;
9+
using Microsoft.AspNetCore.Razor.LanguageServer.Serialization;
1010
using Microsoft.VisualStudio.Editor.Razor;
1111
using Newtonsoft.Json;
1212
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
@@ -30,9 +30,12 @@ public CompletionListSerializationBenchmark()
3030
CompletionList = GenerateCompletionList(documentContent, queryIndex, tagHelperCompletionProvider);
3131
_completionListBuffer = GenerateBuffer(CompletionList);
3232

33-
Serializer.Instance.JsonSerializer.Converters.Add(TagHelperDescriptorJsonConverter.Instance);
33+
Serializer = new LspSerializer();
34+
Serializer.RegisterRazorConverters();
3435
}
3536

37+
private LspSerializer Serializer { get; }
38+
3639
private CompletionList CompletionList { get; }
3740

3841
[Benchmark(Description = "Component Completion List Roundtrip Serialization")]
@@ -43,15 +46,15 @@ public void ComponentElement_CompletionList_Serialization_RoundTrip()
4346
using (originalStream = new MemoryStream())
4447
using (var writer = new StreamWriter(originalStream, Encoding.UTF8, bufferSize: 4096))
4548
{
46-
Serializer.Instance.JsonSerializer.Serialize(writer, CompletionList);
49+
Serializer.JsonSerializer.Serialize(writer, CompletionList);
4750
}
4851

4952
CompletionList deserializedCompletions;
5053
var stream = new MemoryStream(originalStream.GetBuffer());
5154
using (stream)
5255
using (var reader = new JsonTextReader(new StreamReader(stream)))
5356
{
54-
deserializedCompletions = Serializer.Instance.JsonSerializer.Deserialize<CompletionList>(reader);
57+
deserializedCompletions = Serializer.JsonSerializer.Deserialize<CompletionList>(reader);
5558
}
5659
}
5760

@@ -60,7 +63,7 @@ public void ComponentElement_CompletionList_Serialization()
6063
{
6164
using var stream = new MemoryStream();
6265
using var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 4096);
63-
Serializer.Instance.JsonSerializer.Serialize(writer, CompletionList);
66+
Serializer.JsonSerializer.Serialize(writer, CompletionList);
6467
}
6568

6669
[Benchmark(Description = "Component Completion List Deserialization")]
@@ -70,7 +73,7 @@ public void ComponentElement_CompletionList_Deserialization()
7073
using var stream = new MemoryStream(_completionListBuffer);
7174
using var reader = new JsonTextReader(new StreamReader(stream));
7275
CompletionList deserializedCompletions;
73-
deserializedCompletions = Serializer.Instance.JsonSerializer.Deserialize<CompletionList>(reader);
76+
deserializedCompletions = Serializer.JsonSerializer.Deserialize<CompletionList>(reader);
7477
}
7578

7679
private CompletionList GenerateCompletionList(string documentContent, int queryIndex, TagHelperCompletionProvider componentCompletionProvider)
@@ -98,11 +101,11 @@ private CompletionList GenerateCompletionList(string documentContent, int queryI
98101
return completionList;
99102
}
100103

101-
private static byte[] GenerateBuffer(CompletionList completionList)
104+
private byte[] GenerateBuffer(CompletionList completionList)
102105
{
103106
using var stream = new MemoryStream();
104107
using var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 4096);
105-
Serializer.Instance.JsonSerializer.Serialize(writer, completionList);
108+
Serializer.JsonSerializer.Serialize(writer, completionList);
106109
var buffer = stream.GetBuffer();
107110

108111
return buffer;

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Serialization/JsonConverterCollectionExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ internal static class JsonConverterCollectionExtensions
2121
ProjectSnapshotJsonConverter.Instance,
2222
};
2323

24-
public static void RegisterRazorConverters(this JsonConverterCollection collection)
24+
public static void RegisterRazorConverters(this IList<JsonConverter> collection)
2525
{
2626
if (collection == null)
2727
{

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionResolver.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ public override async Task<WorkspaceEdit> ResolveAsync(JObject data, Cancellatio
8383
return null;
8484
}
8585

86-
var codeDocumentIdentifier = new VersionedTextDocumentIdentifier() { Uri = actionParams.Uri };
86+
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = actionParams.Uri };
8787
return CreateAddUsingWorkspaceEdit(actionParams.Namespace, codeDocument, codeDocumentIdentifier);
8888
}
8989

90-
internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, RazorCodeDocument codeDocument, VersionedTextDocumentIdentifier codeDocumentIdentifier)
90+
internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, RazorCodeDocument codeDocument, OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier)
9191
{
9292
/* The heuristic is as follows:
9393
*
@@ -127,7 +127,7 @@ internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, Raz
127127

128128
private static WorkspaceEditDocumentChange GenerateSingleUsingEditsInterpolated(
129129
RazorCodeDocument codeDocument,
130-
VersionedTextDocumentIdentifier codeDocumentIdentifier,
130+
OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier,
131131
string newUsingNamespace,
132132
List<RazorUsingDirective> existingUsingDirectives)
133133
{
@@ -172,7 +172,7 @@ private static WorkspaceEditDocumentChange GenerateSingleUsingEditsInterpolated(
172172

173173
private static WorkspaceEditDocumentChange GenerateSingleUsingEditsAtTop(
174174
RazorCodeDocument codeDocument,
175-
VersionedTextDocumentIdentifier codeDocumentIdentifier,
175+
OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier,
176176
string newUsingNamespace)
177177
{
178178
var head = new Position(0, 0);

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/AddUsingsCSharpCodeActionResolver.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,14 @@ public async override Task<CodeAction> ResolveAsync(
115115
return version;
116116
}, cancellationToken).ConfigureAwait(false);
117117

118-
var codeDocumentIdentifier = new VersionedTextDocumentIdentifier()
118+
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier()
119119
{
120120
Uri = csharpParams.RazorFileUri,
121121
Version = documentVersion.Value
122122
};
123123

124-
resolvedCodeAction.Edit = AddUsingsCodeActionResolver.CreateAddUsingWorkspaceEdit(@namespace, codeDocument, codeDocumentIdentifier);
124+
var edit = AddUsingsCodeActionResolver.CreateAddUsingWorkspaceEdit(@namespace, codeDocument, codeDocumentIdentifier);
125+
resolvedCodeAction = resolvedCodeAction with { Edit = edit };
125126

126127
return resolvedCodeAction;
127128
}

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs

+12-11
Original file line numberDiff line numberDiff line change
@@ -140,22 +140,23 @@ public async override Task<CodeAction> ResolveAsync(
140140
return version;
141141
}, cancellationToken).ConfigureAwait(false);
142142

143-
var codeDocumentIdentifier = new VersionedTextDocumentIdentifier()
143+
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier()
144144
{
145145
Uri = csharpParams.RazorFileUri,
146146
Version = documentVersion.Value
147147
};
148-
149-
resolvedCodeAction.Edit = new WorkspaceEdit()
148+
resolvedCodeAction = resolvedCodeAction with
150149
{
151-
DocumentChanges = new[] {
152-
new WorkspaceEditDocumentChange(
153-
new TextDocumentEdit()
154-
{
155-
TextDocument = codeDocumentIdentifier,
156-
Edits = formattedEdits,
157-
}
158-
)
150+
Edit = new WorkspaceEdit()
151+
{
152+
DocumentChanges = new[] {
153+
new WorkspaceEditDocumentChange(
154+
new TextDocumentEdit()
155+
{
156+
TextDocument = codeDocumentIdentifier,
157+
Edits = formattedEdits,
158+
})
159+
}
159160
}
160161
};
161162

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ private static IEnumerable<RazorCodeAction> ProcessCodeActionsVS(
191191
else if (codeAction.Name.Equals(RazorPredefinedCodeFixProviderNames.AddImport, StringComparison.Ordinal) &&
192192
AddUsingsCodeActionProviderFactory.TryExtractNamespace(codeAction.Title, out var @namespace))
193193
{
194-
codeAction.Title = $"@using {@namespace}";
195-
typeAccessibilityCodeActions.Add(codeAction.WrapResolvableCSharpCodeAction(context, LanguageServerConstants.CodeActions.AddUsing));
194+
var newCodeAction = codeAction with { Title = $"@using {@namespace}" };
195+
typeAccessibilityCodeActions.Add(newCodeAction.WrapResolvableCSharpCodeAction(context, LanguageServerConstants.CodeActions.AddUsing));
196196
}
197197
// Not a type accessibility code action
198198
else
@@ -234,7 +234,7 @@ private static RazorCodeAction CreateFQNCodeAction(
234234
RazorCodeAction codeAction,
235235
string fullyQualifiedName)
236236
{
237-
var codeDocumentIdentifier = new VersionedTextDocumentIdentifier() { Uri = context.Request.TextDocument.Uri };
237+
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = context.Request.TextDocument.Uri };
238238

239239
var fqnTextEdit = new TextEdit()
240240
{

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs

+8-6
Original file line numberDiff line numberDiff line change
@@ -111,25 +111,27 @@ public async override Task<CodeAction> ResolveAsync(
111111
return codeAction;
112112
}
113113

114-
textEdit.Range = originalRange;
114+
textEdit = textEdit with { Range = originalRange };
115115

116-
var codeDocumentIdentifier = new VersionedTextDocumentIdentifier()
116+
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier()
117117
{
118118
Uri = csharpParams.RazorFileUri,
119119
Version = documentVersion
120120
};
121121

122-
resolvedCodeAction.Edit = new WorkspaceEdit()
122+
resolvedCodeAction = resolvedCodeAction with
123123
{
124-
DocumentChanges = new[] {
124+
Edit = new WorkspaceEdit()
125+
{
126+
DocumentChanges = new[] {
125127
new WorkspaceEditDocumentChange(
126128
new TextDocumentEdit()
127129
{
128130
TextDocument = codeDocumentIdentifier,
129131
Edits = new[] { textEdit },
130-
}
131-
)
132+
})
132133
}
134+
},
133135
};
134136

135137
return resolvedCodeAction;

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs

+12-20
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
using Microsoft.CodeAnalysis.Razor.Workspaces;
1717
using Microsoft.CodeAnalysis.Text;
1818
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
19+
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
1920
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
2021

2122
namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions
2223
{
23-
internal class CodeActionEndpoint : IRazorCodeActionHandler
24+
internal class CodeActionEndpoint : ICodeActionHandler
2425
{
2526
private readonly RazorDocumentMappingService _documentMappingService;
2627
private readonly IEnumerable<RazorCodeActionProvider> _razorCodeActionProviders;
@@ -56,8 +57,10 @@ public CodeActionEndpoint(
5657
_allAvailableCodeActionNames = GetAllAvailableCodeActionNames();
5758
}
5859

59-
public CodeActionRegistrationOptions GetRegistrationOptions()
60+
public CodeActionRegistrationOptions GetRegistrationOptions(CodeActionCapability capability, ClientCapabilities clientCapabilities)
6061
{
62+
_capability = capability;
63+
_supportsCodeActionResolve = _capability.ResolveSupport != null;
6164
return new CodeActionRegistrationOptions()
6265
{
6366
DocumentSelector = RazorDefaults.Selector,
@@ -70,14 +73,7 @@ public CodeActionRegistrationOptions GetRegistrationOptions()
7073
};
7174
}
7275

73-
public void SetCapability(CodeActionCapability capability)
74-
{
75-
_capability = capability;
76-
77-
_supportsCodeActionResolve = _capability.ResolveSupport != null;
78-
}
79-
80-
public async Task<CommandOrCodeActionContainer> Handle(RazorCodeActionParams request, CancellationToken cancellationToken)
76+
public async Task<CommandOrCodeActionContainer> Handle(CodeActionParams request, CancellationToken cancellationToken)
8177
{
8278
if (request is null)
8379
{
@@ -119,7 +115,7 @@ public async Task<CommandOrCodeActionContainer> Handle(RazorCodeActionParams req
119115
}
120116

121117
// internal for testing
122-
internal async Task<RazorCodeActionContext> GenerateRazorCodeActionContextAsync(RazorCodeActionParams request, CancellationToken cancellationToken)
118+
internal async Task<RazorCodeActionContext> GenerateRazorCodeActionContextAsync(CodeActionParams request, CancellationToken cancellationToken)
123119
{
124120
var documentSnapshot = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() =>
125121
{
@@ -148,16 +144,12 @@ internal async Task<RazorCodeActionContext> GenerateRazorCodeActionContextAsync(
148144
// context.
149145
//
150146
// Note: VS Code doesn't provide a `SelectionRange`.
151-
if (request.Context.SelectionRange != null)
147+
var vsCodeActionContext = (OmniSharpVSCodeActionContext)request.Context;
148+
if (vsCodeActionContext.SelectionRange != null)
152149
{
153-
request.Range = request.Context.SelectionRange;
150+
request = request with { Range = vsCodeActionContext.SelectionRange };
154151
}
155152

156-
// We hide `CodeActionParams.CodeActionContext` in order to capture
157-
// `RazorCodeActionParams.ExtendedCodeActionContext`, we must
158-
// restore this context to access diagnostics.
159-
(request as CodeActionParams).Context = request.Context;
160-
161153
var linePosition = new LinePosition(
162154
request.Range.Start.Line,
163155
request.Range.Start.Character);
@@ -255,11 +247,11 @@ internal async Task<IEnumerable<RazorCodeAction>> GetCSharpCodeActionsFromLangua
255247
return Array.Empty<RazorCodeAction>();
256248
}
257249

258-
context.Request.Range = projectedRange;
250+
var newRequest = context.Request with { Range = projectedRange };
259251

260252
cancellationToken.ThrowIfCancellationRequested();
261253

262-
var response = await _languageServer.SendRequestAsync(LanguageServerConstants.RazorProvideCodeActionsEndpoint, context.Request);
254+
var response = await _languageServer.SendRequestAsync(LanguageServerConstants.RazorProvideCodeActionsEndpoint, newRequest);
263255
return await response.Returning<RazorCodeAction[]>(cancellationToken);
264256
}
265257

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolutionEndpoint.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public async Task<CodeAction> Handle(CodeAction request, CancellationToken cance
6868
// as it does not support Command.Edit based code actions anymore.
6969
if (resolutionParams.Action == LanguageServerConstants.CodeActions.EditBasedCodeActionCommand)
7070
{
71-
request.Edit = (resolutionParams.Data as JObject)?.ToObject<WorkspaceEdit>();
71+
request = request with { Edit = (resolutionParams.Data as JObject)?.ToObject<WorkspaceEdit>() };
7272
return request;
7373
}
7474

@@ -101,8 +101,8 @@ internal async Task<CodeAction> ResolveRazorCodeActionAsync(
101101
Debug.Fail($"No resolver registered for {GetCodeActionId(resolutionParams)}.");
102102
return codeAction;
103103
}
104-
105-
codeAction.Edit = await resolver.ResolveAsync(resolutionParams.Data as JObject, cancellationToken).ConfigureAwait(false);
104+
var edit = await resolver.ResolveAsync(resolutionParams.Data as JObject, cancellationToken).ConfigureAwait(false);
105+
codeAction = codeAction with { Edit = edit };
106106
return codeAction;
107107
}
108108

@@ -119,7 +119,7 @@ internal async Task<CodeAction> ResolveCSharpCodeActionAsync(
119119
}
120120

121121
var csharpParams = csharpParamsObj.ToObject<CSharpCodeActionParams>();
122-
codeAction.Data = csharpParams.Data as JToken;
122+
codeAction = codeAction with { Data = csharpParams.Data as JToken };
123123

124124
if (!_csharpCodeActionResolvers.TryGetValue(resolutionParams.Action, out var resolver))
125125
{

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/IRazorCodeActionHandler.cs

-19
This file was deleted.

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public static RazorCodeAction WrapResolvableCSharpCodeAction(
6868
Language = LanguageServerConstants.CodeActions.Languages.CSharp,
6969
Data = csharpParams
7070
};
71-
razorCodeAction.Data = JToken.FromObject(resolutionParams);
71+
razorCodeAction = razorCodeAction with { Data = JToken.FromObject(resolutionParams) };
7272

7373
if (razorCodeAction.Children?.Length != 0)
7474
{
+4-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
// Copyright (c) .NET Foundation. All rights reserved.
22
// Licensed under the MIT license. See License.txt in the project root for license information.
33

4+
using Microsoft.AspNetCore.Razor.LanguageServer.Serialization;
45
using Newtonsoft.Json;
56
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
67
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;
78

89
namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models
910
{
10-
internal class ExtendedCodeActionContext : CodeActionContext
11+
internal record OmniSharpVSCodeActionContext : CodeActionContext
1112
{
13+
public static readonly PlatformExtensionConverter<CodeActionContext, OmniSharpVSCodeActionContext> JsonConverter = new();
14+
1215
[Optional]
1316
[JsonProperty("_vs_selectionRange")]
1417
public Range SelectionRange { get; set; }

src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeAction.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models
1111
{
1212
[DebuggerDisplay("{Title,nq}")]
13-
internal class RazorCodeAction : CodeAction, IRequest<RazorCodeAction>, IBaseRequest
13+
internal record RazorCodeAction : CodeAction, IRequest<RazorCodeAction>, IBaseRequest
1414
{
1515
/// <summary>
1616
/// Typically null, only present in VS scenarios.

0 commit comments

Comments
 (0)