Skip to content

Commit

Permalink
Upgrade OmniSharp to 0.19.4.
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
NTaylorMullen committed Aug 24, 2021
1 parent 6b32699 commit 00c92e9
Show file tree
Hide file tree
Showing 66 changed files with 476 additions and 591 deletions.
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@
<MonoDevelopSdkPackageVersion>1.0.15</MonoDevelopSdkPackageVersion>
<MoqPackageVersion>4.16.0</MoqPackageVersion>
<NerdbankStreamsPackageVersion>2.7.74</NerdbankStreamsPackageVersion>
<OmniSharpExtensionsLanguageServerPackageVersion>0.18.1</OmniSharpExtensionsLanguageServerPackageVersion>
<OmniSharpExtensionsLanguageServerPackageVersion>0.19.4</OmniSharpExtensionsLanguageServerPackageVersion>
<OmniSharpMSBuildPackageVersion>1.37.13</OmniSharpMSBuildPackageVersion>
<StreamJsonRpcPackageVersion>2.8.21</StreamJsonRpcPackageVersion>
<Tooling_MicrosoftCodeAnalysisAnalyzersPackageVersion>3.3.2</Tooling_MicrosoftCodeAnalysisAnalyzersPackageVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.LanguageServer.Completion;
using Microsoft.CodeAnalysis.Razor.Completion;
using Microsoft.CodeAnalysis.Razor.Serialization;
using Microsoft.AspNetCore.Razor.LanguageServer.Serialization;
using Microsoft.VisualStudio.Editor.Razor;
using Newtonsoft.Json;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
Expand All @@ -30,9 +30,12 @@ public CompletionListSerializationBenchmark()
CompletionList = GenerateCompletionList(documentContent, queryIndex, tagHelperCompletionProvider);
_completionListBuffer = GenerateBuffer(CompletionList);

Serializer.Instance.JsonSerializer.Converters.Add(TagHelperDescriptorJsonConverter.Instance);
Serializer = new LspSerializer();
Serializer.RegisterRazorConverters();
}

private LspSerializer Serializer { get; }

private CompletionList CompletionList { get; }

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

CompletionList deserializedCompletions;
var stream = new MemoryStream(originalStream.GetBuffer());
using (stream)
using (var reader = new JsonTextReader(new StreamReader(stream)))
{
deserializedCompletions = Serializer.Instance.JsonSerializer.Deserialize<CompletionList>(reader);
deserializedCompletions = Serializer.JsonSerializer.Deserialize<CompletionList>(reader);
}
}

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

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

private CompletionList GenerateCompletionList(string documentContent, int queryIndex, TagHelperCompletionProvider componentCompletionProvider)
Expand Down Expand Up @@ -98,11 +101,11 @@ private CompletionList GenerateCompletionList(string documentContent, int queryI
return completionList;
}

private static byte[] GenerateBuffer(CompletionList completionList)
private byte[] GenerateBuffer(CompletionList completionList)
{
using var stream = new MemoryStream();
using var writer = new StreamWriter(stream, Encoding.UTF8, bufferSize: 4096);
Serializer.Instance.JsonSerializer.Serialize(writer, completionList);
Serializer.JsonSerializer.Serialize(writer, completionList);
var buffer = stream.GetBuffer();

return buffer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal static class JsonConverterCollectionExtensions
ProjectSnapshotJsonConverter.Instance,
};

public static void RegisterRazorConverters(this JsonConverterCollection collection)
public static void RegisterRazorConverters(this IList<JsonConverter> collection)
{
if (collection == null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ public override async Task<WorkspaceEdit> ResolveAsync(JObject data, Cancellatio
return null;
}

var codeDocumentIdentifier = new VersionedTextDocumentIdentifier() { Uri = actionParams.Uri };
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = actionParams.Uri };
return CreateAddUsingWorkspaceEdit(actionParams.Namespace, codeDocument, codeDocumentIdentifier);
}

internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, RazorCodeDocument codeDocument, VersionedTextDocumentIdentifier codeDocumentIdentifier)
internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, RazorCodeDocument codeDocument, OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier)
{
/* The heuristic is as follows:
*
Expand Down Expand Up @@ -127,7 +127,7 @@ internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, Raz

private static WorkspaceEditDocumentChange GenerateSingleUsingEditsInterpolated(
RazorCodeDocument codeDocument,
VersionedTextDocumentIdentifier codeDocumentIdentifier,
OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier,
string newUsingNamespace,
List<RazorUsingDirective> existingUsingDirectives)
{
Expand Down Expand Up @@ -172,7 +172,7 @@ private static WorkspaceEditDocumentChange GenerateSingleUsingEditsInterpolated(

private static WorkspaceEditDocumentChange GenerateSingleUsingEditsAtTop(
RazorCodeDocument codeDocument,
VersionedTextDocumentIdentifier codeDocumentIdentifier,
OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier,
string newUsingNamespace)
{
var head = new Position(0, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,14 @@ public async override Task<CodeAction> ResolveAsync(
return version;
}, cancellationToken).ConfigureAwait(false);

var codeDocumentIdentifier = new VersionedTextDocumentIdentifier()
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier()
{
Uri = csharpParams.RazorFileUri,
Version = documentVersion.Value
};

resolvedCodeAction.Edit = AddUsingsCodeActionResolver.CreateAddUsingWorkspaceEdit(@namespace, codeDocument, codeDocumentIdentifier);
var edit = AddUsingsCodeActionResolver.CreateAddUsingWorkspaceEdit(@namespace, codeDocument, codeDocumentIdentifier);
resolvedCodeAction = resolvedCodeAction with { Edit = edit };

return resolvedCodeAction;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,22 +140,23 @@ public async override Task<CodeAction> ResolveAsync(
return version;
}, cancellationToken).ConfigureAwait(false);

var codeDocumentIdentifier = new VersionedTextDocumentIdentifier()
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier()
{
Uri = csharpParams.RazorFileUri,
Version = documentVersion.Value
};

resolvedCodeAction.Edit = new WorkspaceEdit()
resolvedCodeAction = resolvedCodeAction with
{
DocumentChanges = new[] {
new WorkspaceEditDocumentChange(
new TextDocumentEdit()
{
TextDocument = codeDocumentIdentifier,
Edits = formattedEdits,
}
)
Edit = new WorkspaceEdit()
{
DocumentChanges = new[] {
new WorkspaceEditDocumentChange(
new TextDocumentEdit()
{
TextDocument = codeDocumentIdentifier,
Edits = formattedEdits,
})
}
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ private static IEnumerable<RazorCodeAction> ProcessCodeActionsVS(
else if (codeAction.Name.Equals(RazorPredefinedCodeFixProviderNames.AddImport, StringComparison.Ordinal) &&
AddUsingsCodeActionProviderFactory.TryExtractNamespace(codeAction.Title, out var @namespace))
{
codeAction.Title = $"@using {@namespace}";
typeAccessibilityCodeActions.Add(codeAction.WrapResolvableCSharpCodeAction(context, LanguageServerConstants.CodeActions.AddUsing));
var newCodeAction = codeAction with { Title = $"@using {@namespace}" };
typeAccessibilityCodeActions.Add(newCodeAction.WrapResolvableCSharpCodeAction(context, LanguageServerConstants.CodeActions.AddUsing));
}
// Not a type accessibility code action
else
Expand Down Expand Up @@ -234,7 +234,7 @@ private static RazorCodeAction CreateFQNCodeAction(
RazorCodeAction codeAction,
string fullyQualifiedName)
{
var codeDocumentIdentifier = new VersionedTextDocumentIdentifier() { Uri = context.Request.TextDocument.Uri };
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = context.Request.TextDocument.Uri };

var fqnTextEdit = new TextEdit()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,25 +111,27 @@ public async override Task<CodeAction> ResolveAsync(
return codeAction;
}

textEdit.Range = originalRange;
textEdit = textEdit with { Range = originalRange };

var codeDocumentIdentifier = new VersionedTextDocumentIdentifier()
var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier()
{
Uri = csharpParams.RazorFileUri,
Version = documentVersion
};

resolvedCodeAction.Edit = new WorkspaceEdit()
resolvedCodeAction = resolvedCodeAction with
{
DocumentChanges = new[] {
Edit = new WorkspaceEdit()
{
DocumentChanges = new[] {
new WorkspaceEditDocumentChange(
new TextDocumentEdit()
{
TextDocument = codeDocumentIdentifier,
Edits = new[] { textEdit },
}
)
})
}
},
};

return resolvedCodeAction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Text;
using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities;
using OmniSharp.Extensions.LanguageServer.Protocol.Document;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions
{
internal class CodeActionEndpoint : IRazorCodeActionHandler
internal class CodeActionEndpoint : ICodeActionHandler
{
private readonly RazorDocumentMappingService _documentMappingService;
private readonly IEnumerable<RazorCodeActionProvider> _razorCodeActionProviders;
Expand Down Expand Up @@ -56,8 +57,10 @@ public CodeActionEndpoint(
_allAvailableCodeActionNames = GetAllAvailableCodeActionNames();
}

public CodeActionRegistrationOptions GetRegistrationOptions()
public CodeActionRegistrationOptions GetRegistrationOptions(CodeActionCapability capability, ClientCapabilities clientCapabilities)
{
_capability = capability;
_supportsCodeActionResolve = _capability.ResolveSupport != null;
return new CodeActionRegistrationOptions()
{
DocumentSelector = RazorDefaults.Selector,
Expand All @@ -70,14 +73,7 @@ public CodeActionRegistrationOptions GetRegistrationOptions()
};
}

public void SetCapability(CodeActionCapability capability)
{
_capability = capability;

_supportsCodeActionResolve = _capability.ResolveSupport != null;
}

public async Task<CommandOrCodeActionContainer> Handle(RazorCodeActionParams request, CancellationToken cancellationToken)
public async Task<CommandOrCodeActionContainer> Handle(CodeActionParams request, CancellationToken cancellationToken)
{
if (request is null)
{
Expand Down Expand Up @@ -119,7 +115,7 @@ public async Task<CommandOrCodeActionContainer> Handle(RazorCodeActionParams req
}

// internal for testing
internal async Task<RazorCodeActionContext> GenerateRazorCodeActionContextAsync(RazorCodeActionParams request, CancellationToken cancellationToken)
internal async Task<RazorCodeActionContext> GenerateRazorCodeActionContextAsync(CodeActionParams request, CancellationToken cancellationToken)
{
var documentSnapshot = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() =>
{
Expand Down Expand Up @@ -148,16 +144,12 @@ internal async Task<RazorCodeActionContext> GenerateRazorCodeActionContextAsync(
// context.
//
// Note: VS Code doesn't provide a `SelectionRange`.
if (request.Context.SelectionRange != null)
var vsCodeActionContext = (OmniSharpVSCodeActionContext)request.Context;
if (vsCodeActionContext.SelectionRange != null)
{
request.Range = request.Context.SelectionRange;
request = request with { Range = vsCodeActionContext.SelectionRange };
}

// We hide `CodeActionParams.CodeActionContext` in order to capture
// `RazorCodeActionParams.ExtendedCodeActionContext`, we must
// restore this context to access diagnostics.
(request as CodeActionParams).Context = request.Context;

var linePosition = new LinePosition(
request.Range.Start.Line,
request.Range.Start.Character);
Expand Down Expand Up @@ -255,11 +247,11 @@ internal async Task<IEnumerable<RazorCodeAction>> GetCSharpCodeActionsFromLangua
return Array.Empty<RazorCodeAction>();
}

context.Request.Range = projectedRange;
var newRequest = context.Request with { Range = projectedRange };

cancellationToken.ThrowIfCancellationRequested();

var response = await _languageServer.SendRequestAsync(LanguageServerConstants.RazorProvideCodeActionsEndpoint, context.Request);
var response = await _languageServer.SendRequestAsync(LanguageServerConstants.RazorProvideCodeActionsEndpoint, newRequest);
return await response.Returning<RazorCodeAction[]>(cancellationToken);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public async Task<CodeAction> Handle(CodeAction request, CancellationToken cance
// as it does not support Command.Edit based code actions anymore.
if (resolutionParams.Action == LanguageServerConstants.CodeActions.EditBasedCodeActionCommand)
{
request.Edit = (resolutionParams.Data as JObject)?.ToObject<WorkspaceEdit>();
request = request with { Edit = (resolutionParams.Data as JObject)?.ToObject<WorkspaceEdit>() };
return request;
}

Expand Down Expand Up @@ -101,8 +101,8 @@ internal async Task<CodeAction> ResolveRazorCodeActionAsync(
Debug.Fail($"No resolver registered for {GetCodeActionId(resolutionParams)}.");
return codeAction;
}

codeAction.Edit = await resolver.ResolveAsync(resolutionParams.Data as JObject, cancellationToken).ConfigureAwait(false);
var edit = await resolver.ResolveAsync(resolutionParams.Data as JObject, cancellationToken).ConfigureAwait(false);
codeAction = codeAction with { Edit = edit };
return codeAction;
}

Expand All @@ -119,7 +119,7 @@ internal async Task<CodeAction> ResolveCSharpCodeActionAsync(
}

var csharpParams = csharpParamsObj.ToObject<CSharpCodeActionParams>();
codeAction.Data = csharpParams.Data as JToken;
codeAction = codeAction with { Data = csharpParams.Data as JToken };

if (!_csharpCodeActionResolvers.TryGetValue(resolutionParams.Action, out var resolver))
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static RazorCodeAction WrapResolvableCSharpCodeAction(
Language = LanguageServerConstants.CodeActions.Languages.CSharp,
Data = csharpParams
};
razorCodeAction.Data = JToken.FromObject(resolutionParams);
razorCodeAction = razorCodeAction with { Data = JToken.FromObject(resolutionParams) };

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

using Microsoft.AspNetCore.Razor.LanguageServer.Serialization;
using Newtonsoft.Json;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
using OmniSharp.Extensions.LanguageServer.Protocol.Serialization;

namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models
{
internal class ExtendedCodeActionContext : CodeActionContext
internal record OmniSharpVSCodeActionContext : CodeActionContext
{
public static readonly PlatformExtensionConverter<CodeActionContext, OmniSharpVSCodeActionContext> JsonConverter = new();

[Optional]
[JsonProperty("_vs_selectionRange")]
public Range SelectionRange { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models
{
[DebuggerDisplay("{Title,nq}")]
internal class RazorCodeAction : CodeAction, IRequest<RazorCodeAction>, IBaseRequest
internal record RazorCodeAction : CodeAction, IRequest<RazorCodeAction>, IBaseRequest
{
/// <summary>
/// Typically null, only present in VS scenarios.
Expand Down
Loading

0 comments on commit 00c92e9

Please sign in to comment.