Skip to content

Commit 4bff29c

Browse files
author
N. Taylor Mullen
authored
Upgrade OmniSharp to 0.19.4. (#4134)
* 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 * Addressed code review comments - Set => Init - Removal of semantic token legend endpoint - Some refactoring in our serializer extensions - Test fixups
1 parent eb6fee7 commit 4bff29c

File tree

67 files changed

+520
-685
lines changed

Some content is hidden

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

67 files changed

+520
-685
lines changed

eng/Versions.props

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

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

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

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

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

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

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

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

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

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

0 commit comments

Comments
 (0)