diff --git a/eng/Versions.props b/eng/Versions.props index c5065fec0f5..2f16cc862c3 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -125,7 +125,7 @@ 1.0.15 4.16.0 2.7.74 - 0.18.1 + 0.19.4 1.37.13 2.8.21 3.3.2 diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/CompletionListSerializationBenchmark.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/CompletionListSerializationBenchmark.cs index ed8aa905dc4..c569ff0f4d4 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/CompletionListSerializationBenchmark.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/CompletionListSerializationBenchmark.cs @@ -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; @@ -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")] @@ -43,7 +46,7 @@ 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; @@ -51,7 +54,7 @@ public void ComponentElement_CompletionList_Serialization_RoundTrip() using (stream) using (var reader = new JsonTextReader(new StreamReader(stream))) { - deserializedCompletions = Serializer.Instance.JsonSerializer.Deserialize(reader); + deserializedCompletions = Serializer.JsonSerializer.Deserialize(reader); } } @@ -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")] @@ -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(reader); + deserializedCompletions = Serializer.JsonSerializer.Deserialize(reader); } private CompletionList GenerateCompletionList(string documentContent, int queryIndex, TagHelperCompletionProvider componentCompletionProvider) @@ -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; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Serialization/JsonConverterCollectionExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Serialization/JsonConverterCollectionExtensions.cs index 02bf87a25a9..95c8a1ac7d0 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Serialization/JsonConverterCollectionExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer.Common/Serialization/JsonConverterCollectionExtensions.cs @@ -21,7 +21,7 @@ internal static class JsonConverterCollectionExtensions ProjectSnapshotJsonConverter.Instance, }; - public static void RegisterRazorConverters(this JsonConverterCollection collection) + public static void RegisterRazorConverters(this IList collection) { if (collection == null) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionResolver.cs index 14becc900d4..b5ee8519452 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/AddUsingsCodeActionResolver.cs @@ -83,11 +83,11 @@ public override async Task 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: * @@ -127,7 +127,7 @@ internal static WorkspaceEdit CreateAddUsingWorkspaceEdit(string @namespace, Raz private static WorkspaceEditDocumentChange GenerateSingleUsingEditsInterpolated( RazorCodeDocument codeDocument, - VersionedTextDocumentIdentifier codeDocumentIdentifier, + OptionalVersionedTextDocumentIdentifier codeDocumentIdentifier, string newUsingNamespace, List existingUsingDirectives) { @@ -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); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/AddUsingsCSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/AddUsingsCSharpCodeActionResolver.cs index c22307d20fa..c8cd478ac9c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/AddUsingsCSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/AddUsingsCSharpCodeActionResolver.cs @@ -115,13 +115,14 @@ public async override Task 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; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs index d7a06ff7044..637c865dd63 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/DefaultCSharpCodeActionResolver.cs @@ -140,22 +140,23 @@ public async override Task 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, + }) + } } }; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs index 36fa575690b..6b14c1808c2 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/TypeAccessibilityCodeActionProvider.cs @@ -191,8 +191,8 @@ private static IEnumerable 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 @@ -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() { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs index ec51cac1a67..2f4f87b5f13 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CSharp/UnformattedRemappingCSharpCodeActionResolver.cs @@ -111,25 +111,27 @@ public async override Task 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; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs index e43cafba73c..1361539cc0a 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionEndpoint.cs @@ -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 _razorCodeActionProviders; @@ -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, @@ -70,14 +73,7 @@ public CodeActionRegistrationOptions GetRegistrationOptions() }; } - public void SetCapability(CodeActionCapability capability) - { - _capability = capability; - - _supportsCodeActionResolve = _capability.ResolveSupport != null; - } - - public async Task Handle(RazorCodeActionParams request, CancellationToken cancellationToken) + public async Task Handle(CodeActionParams request, CancellationToken cancellationToken) { if (request is null) { @@ -119,7 +115,7 @@ public async Task Handle(RazorCodeActionParams req } // internal for testing - internal async Task GenerateRazorCodeActionContextAsync(RazorCodeActionParams request, CancellationToken cancellationToken) + internal async Task GenerateRazorCodeActionContextAsync(CodeActionParams request, CancellationToken cancellationToken) { var documentSnapshot = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => { @@ -148,16 +144,12 @@ internal async Task 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); @@ -255,11 +247,11 @@ internal async Task> GetCSharpCodeActionsFromLangua return Array.Empty(); } - 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(cancellationToken); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolutionEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolutionEndpoint.cs index c92b0990f37..3a6075c00ba 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolutionEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/CodeActionResolutionEndpoint.cs @@ -68,7 +68,7 @@ public async Task 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(); + request = request with { Edit = (resolutionParams.Data as JObject)?.ToObject() }; return request; } @@ -101,8 +101,8 @@ internal async Task 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; } @@ -119,7 +119,7 @@ internal async Task ResolveCSharpCodeActionAsync( } var csharpParams = csharpParamsObj.ToObject(); - codeAction.Data = csharpParams.Data as JToken; + codeAction = codeAction with { Data = csharpParams.Data as JToken }; if (!_csharpCodeActionResolvers.TryGetValue(resolutionParams.Action, out var resolver)) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/IRazorCodeActionHandler.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/IRazorCodeActionHandler.cs deleted file mode 100644 index bb1c319de26..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/IRazorCodeActionHandler.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; -using OmniSharp.Extensions.LanguageServer.Protocol; -using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; - -namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions -{ - [Parallel, Method("textDocument/codeAction", Direction.ClientToServer)] - internal interface IRazorCodeActionHandler : - IJsonRpcRequestHandler, - IRegistration, - ICapability - { - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs index fc9b42b7f65..e22f6310e22 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/CodeActionExtensions.cs @@ -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) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/ExtendedCodeActionContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/OmniSharpVSCodeActionContext.cs similarity index 65% rename from src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/ExtendedCodeActionContext.cs rename to src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/OmniSharpVSCodeActionContext.cs index be438a89ad3..3e1ee7ce489 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/ExtendedCodeActionContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/OmniSharpVSCodeActionContext.cs @@ -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 JsonConverter = new(); + [Optional] [JsonProperty("_vs_selectionRange")] public Range SelectionRange { get; set; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeAction.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeAction.cs index f3b24fdd5ab..33852ead7bc 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeAction.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeAction.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models { [DebuggerDisplay("{Title,nq}")] - internal class RazorCodeAction : CodeAction, IRequest, IBaseRequest + internal record RazorCodeAction : CodeAction, IRequest, IBaseRequest { /// /// Typically null, only present in VS scenarios. diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionParams.cs deleted file mode 100644 index b6de73b5ac7..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Models/RazorCodeActionParams.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using OmniSharp.Extensions.LanguageServer.Protocol.Models; - -namespace Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models -{ - internal class RazorCodeActionParams : CodeActionParams - { - public new ExtendedCodeActionContext Context { get; set; } - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs index 48899f3e08b..b8815a6055c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ComponentAccessibilityCodeActionProvider.cs @@ -200,7 +200,7 @@ private Dictionary FindMatchingTagHelpers(RazorCodeAction private static WorkspaceEdit CreateRenameTagEdit(RazorCodeActionContext context, MarkupStartTagSyntax startTag, string newTagName) { var textEdits = new List(); - var codeDocumentIdentifier = new VersionedTextDocumentIdentifier() { Uri = context.Request.TextDocument.Uri }; + var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier() { Uri = context.Request.TextDocument.Uri }; var startTagTextEdit = new TextEdit { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs index dd5632c91bd..b070a182f43 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/CreateComponentCodeActionResolver.cs @@ -106,7 +106,7 @@ private static void TryAddNamespaceDirective(RazorCodeDocument codeDocument, Uri if (namespaceDirective != null) { - var documentIdentifier = new VersionedTextDocumentIdentifier { Uri = newComponentUri }; + var documentIdentifier = new OptionalVersionedTextDocumentIdentifier { Uri = newComponentUri }; documentChanges.Add(new WorkspaceEditDocumentChange(new TextDocumentEdit { TextDocument = documentIdentifier, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs index 5eb932f9eff..0a3d222d032 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/CodeActions/Razor/ExtractToCodeBehindCodeActionResolver.cs @@ -104,8 +104,8 @@ public override async Task ResolveAsync(JObject data, Cancellatio new Position(start.LineIndex, start.CharacterIndex), new Position(end.LineIndex, end.CharacterIndex)); - var codeDocumentIdentifier = new VersionedTextDocumentIdentifier { Uri = actionParams.Uri }; - var codeBehindDocumentIdentifier = new VersionedTextDocumentIdentifier { Uri = codeBehindUri }; + var codeDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier { Uri = actionParams.Uri }; + var codeBehindDocumentIdentifier = new OptionalVersionedTextDocumentIdentifier { Uri = codeBehindUri }; var documentChanges = new List { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionItemExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionItemExtensions.cs index f5dfd8e20fc..b99f9188fb2 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionItemExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/CompletionItemExtensions.cs @@ -11,16 +11,17 @@ internal static class CompletionItemExtensions { private const string ResultIdKey = "_resultId"; - public static void SetCompletionListResultId(this CompletionItem completion, long resultId) + public static CompletionItem CreateWithCompletionListResultId(this CompletionItem completionItem, long resultId) { - if (completion is null) + if (completionItem is null) { - throw new ArgumentNullException(nameof(completion)); + throw new ArgumentNullException(nameof(completionItem)); } - var data = completion.Data ?? new JObject(); + var data = completionItem.Data ?? new JObject(); data[ResultIdKey] = resultId; - completion.Data = data; + completionItem = completionItem with { Data = data }; + return completionItem; } public static bool TryGetCompletionListResultId(this CompletionItem completion, out int resultId) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/OmniSharpVSCompletionContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/OmniSharpVSCompletionContext.cs index 43edfb671a9..27633b16ae7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/OmniSharpVSCompletionContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/OmniSharpVSCompletionContext.cs @@ -7,7 +7,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion { - internal class OmniSharpVSCompletionContext : CompletionContext + internal record OmniSharpVSCompletionContext : CompletionContext { public static readonly PlatformExtensionConverter JsonConverter = new PlatformExtensionConverter(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/RazorCompletionEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/RazorCompletionEndpoint.cs index 0008a2d2bec..e4d8e607886 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/RazorCompletionEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/RazorCompletionEndpoint.cs @@ -23,7 +23,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion { internal class RazorCompletionEndpoint : ICompletionHandler, ICompletionResolveHandler { - private PlatformAgnosticCompletionCapability _capability; private readonly ILogger _logger; private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; private readonly DocumentResolver _documentResolver; @@ -37,9 +36,12 @@ internal class RazorCompletionEndpoint : ICompletionHandler, ICompletionResolveH Name = "editor.action.triggerSuggest", Title = RazorLS.Resources.ReTrigger_Completions_Title, }; - + private PlatformAgnosticCompletionCapability _capability; private IReadOnlyList _supportedItemKinds; + // Guid is magically generated and doesn't mean anything. O# magic. + public Guid Id => new Guid("011c77cc-f90e-4f2e-b32c-dafc6587ccd6"); + public RazorCompletionEndpoint( ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, DocumentResolver documentResolver, @@ -94,10 +96,24 @@ public RazorCompletionEndpoint( _completionListCache = new CompletionListCache(); } - public void SetCapability(CompletionCapability capability) + public void SetCapability(CompletionCapability capability, ClientCapabilities clientCapabilities) + { + } + + public CompletionRegistrationOptions GetRegistrationOptions(CompletionCapability capability, ClientCapabilities clientCapabilities) { _capability = (PlatformAgnosticCompletionCapability)capability; _supportedItemKinds = _capability.CompletionItemKind.ValueSet.Cast().ToList(); + return new CompletionRegistrationOptions() + { + DocumentSelector = RazorDefaults.Selector, + ResolveProvider = true, + TriggerCharacters = new Container("@", "<", ":"), + + // NOTE: This property is *NOT* processed in O# versions < 0.16 + // https://github.com/OmniSharp/csharp-language-server-protocol/blame/bdec4c73240be52fbb25a81f6ad7d409f77b5215/src/Protocol/Server/Capabilities/CompletionOptions.cs#L35-L44 + AllCommitCharacters = new Container(":", ">", " ", "="), + }; } public async Task Handle(CompletionParams request, CancellationToken cancellationToken) @@ -149,20 +165,6 @@ public async Task Handle(CompletionParams request, CancellationT return completionList; } - public CompletionRegistrationOptions GetRegistrationOptions() - { - return new CompletionRegistrationOptions() - { - DocumentSelector = RazorDefaults.Selector, - ResolveProvider = true, - TriggerCharacters = new Container("@", "<", ":"), - - // NOTE: This property is *NOT* processed in O# versions < 0.16 - // https://github.com/OmniSharp/csharp-language-server-protocol/blame/bdec4c73240be52fbb25a81f6ad7d409f77b5215/src/Protocol/Server/Capabilities/CompletionOptions.cs#L35-L44 - AllCommitCharacters = new Container(":", ">", " ", "="), - }; - } - public Task Handle(CompletionItem completionItem, CancellationToken cancellationToken) { if (!completionItem.TryGetCompletionListResultId(out var resultId)) @@ -196,13 +198,13 @@ public Task Handle(CompletionItem completionItem, CancellationTo case RazorCompletionItemKind.Directive: { var descriptionInfo = associatedRazorCompletion.GetDirectiveCompletionDescription(); - completionItem.Documentation = descriptionInfo.Description; + completionItem = completionItem with { Documentation = descriptionInfo.Description }; break; } case RazorCompletionItemKind.MarkupTransition: { var descriptionInfo = associatedRazorCompletion.GetMarkupTransitionCompletionDescription(); - completionItem.Documentation = descriptionInfo.Description; + completionItem = completionItem with { Documentation = descriptionInfo.Description }; break; } case RazorCompletionItemKind.DirectiveAttribute: @@ -240,13 +242,13 @@ public Task Handle(CompletionItem completionItem, CancellationTo if (tagHelperMarkupTooltip != null) { var documentation = new StringOrMarkupContent(tagHelperMarkupTooltip); - completionItem.Documentation = documentation; + completionItem = completionItem with { Documentation = documentation }; } if (tagHelperClassifiedTextTooltip != null) { var vsCompletionItem = completionItem.ToVSCompletionItem(); - vsCompletionItem.Documentation = string.Empty; + completionItem = completionItem with { Documentation = string.Empty }; vsCompletionItem.Description = tagHelperClassifiedTextTooltip; return Task.FromResult(vsCompletionItem); } @@ -291,7 +293,7 @@ internal static CompletionList CreateLSPCompletionList( if (TryConvert(razorCompletionItem, supportedItemKinds, out var completionItem)) { // The completion items are cached and can be retrieved via this result id to enable the "resolve" completion functionality. - completionItem.SetCompletionListResultId(resultId); + completionItem = completionItem.CreateWithCompletionListResultId(resultId); completionItems.Add(completionItem); } } @@ -348,13 +350,16 @@ internal static bool TryConvert( if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0) { - directiveCompletionItem.CommitCharacters = new Container(razorCompletionItem.CommitCharacters); + directiveCompletionItem = directiveCompletionItem with { CommitCharacters = new Container(razorCompletionItem.CommitCharacters) }; } if (razorCompletionItem == DirectiveAttributeTransitionCompletionItemProvider.TransitionCompletionItem) { - directiveCompletionItem.Command = s_retriggerCompletionCommand; - directiveCompletionItem.Kind = tagHelperCompletionItemKind; + directiveCompletionItem = directiveCompletionItem with + { + Command = s_retriggerCompletionCommand, + Kind = tagHelperCompletionItemKind, + }; } completionItem = directiveCompletionItem; @@ -373,7 +378,7 @@ internal static bool TryConvert( if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0) { - directiveAttributeCompletionItem.CommitCharacters = new Container(razorCompletionItem.CommitCharacters); + directiveAttributeCompletionItem = directiveAttributeCompletionItem with { CommitCharacters = new Container(razorCompletionItem.CommitCharacters) }; } completionItem = directiveAttributeCompletionItem; @@ -406,7 +411,7 @@ internal static bool TryConvert( if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0) { - markupTransitionCompletionItem.CommitCharacters = new Container(razorCompletionItem.CommitCharacters); + markupTransitionCompletionItem = markupTransitionCompletionItem with { CommitCharacters = new Container(razorCompletionItem.CommitCharacters) }; } completionItem = markupTransitionCompletionItem; @@ -425,7 +430,7 @@ internal static bool TryConvert( if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0) { - tagHelperElementCompletionItem.CommitCharacters = new Container(razorCompletionItem.CommitCharacters); + tagHelperElementCompletionItem = tagHelperElementCompletionItem with { CommitCharacters = new Container(razorCompletionItem.CommitCharacters) }; } completionItem = tagHelperElementCompletionItem; @@ -444,7 +449,7 @@ internal static bool TryConvert( if (razorCompletionItem.CommitCharacters != null && razorCompletionItem.CommitCharacters.Count > 0) { - tagHelperAttributeCompletionItem.CommitCharacters = new Container(razorCompletionItem.CommitCharacters); + tagHelperAttributeCompletionItem = tagHelperAttributeCompletionItem with { CommitCharacters = new Container(razorCompletionItem.CommitCharacters) }; } completionItem = tagHelperAttributeCompletionItem; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionItem.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionItem.cs index 407f02bff25..4fc6cf7c835 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionItem.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionItem.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion /// /// VS-specific completion item based off of LSP's VSCompletionItem. /// - internal class VSCompletionItem : CompletionItem + internal record VSCompletionItem : CompletionItem { [JsonProperty("_vs_description")] public VSClassifiedTextElement Description { get; set; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionList.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionList.cs index 565835bdd2d..0881178e003 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionList.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Completion/VSCompletionList.cs @@ -13,7 +13,11 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Completion /// internal class VSCompletionList : CompletionList { - protected VSCompletionList(CompletionList innerCompletionList) : base (innerCompletionList.Items, innerCompletionList.IsIncomplete) + protected VSCompletionList(CompletionList innerCompletionList) : this(innerCompletionList.Items, innerCompletionList.IsIncomplete) + { + } + + protected VSCompletionList(IEnumerable completionItems, bool isIncomplete) : base(completionItems, isIncomplete) { } @@ -34,18 +38,18 @@ public static VSCompletionList Convert(CompletionList completionList, VSCompleti var vsCompletionList = new VSCompletionList(completionList); if (vsCompletionListCapability.CommitCharacters) { - PromoteCommonCommitCharactersOntoList(vsCompletionList); + vsCompletionList = PromoteCommonCommitCharactersOntoList(vsCompletionList); } if (vsCompletionListCapability.Data) { - PromotedDataOntoList(vsCompletionList); + vsCompletionList = PromotedDataOntoList(vsCompletionList); } return vsCompletionList; } - private static void PromoteCommonCommitCharactersOntoList(VSCompletionList completionList) + private static VSCompletionList PromoteCommonCommitCharactersOntoList(VSCompletionList completionList) { var commitCharacterReferences = new Dictionary(); var highestUsedCount = 0; @@ -71,33 +75,53 @@ private static void PromoteCommonCommitCharactersOntoList(VSCompletionList compl commitCharacterReferences[commitCharacters] = existingCount; } - // Promoted the most used commit characters onto the list and then remove these from child items. - completionList.CommitCharacters = mostUsedCommitCharacters; + // Promote the most used commit characters onto the list and remove duplicates from child items. + var promotedCompletionItems = new List(); foreach (var completionItem in completionList.Items) { - if (completionItem.CommitCharacters == completionList.CommitCharacters) + if (completionItem.CommitCharacters == mostUsedCommitCharacters) + { + var clearedCompletionItem = completionItem with { CommitCharacters = null }; + promotedCompletionItems.Add(clearedCompletionItem); + } + else { - completionItem.CommitCharacters = null; + promotedCompletionItems.Add(completionItem); } } + + var promotedCompletionList = new VSCompletionList(promotedCompletionItems, completionList.IsIncomplete) + { + CommitCharacters = mostUsedCommitCharacters, + Data = completionList.Data, + }; + return promotedCompletionList; } - private static void PromotedDataOntoList(VSCompletionList completionList) + private static VSCompletionList PromotedDataOntoList(VSCompletionList completionList) { // This piece makes a massive assumption that all completion items will have a resultId associated with them and their // data properties will all be the same. Therefore, we can inspect the first item and empty out the rest. var commonDataItem = completionList.FirstOrDefault(); if (commonDataItem is null) { - // Empty list - return; + // No common data items, nothing to do + return completionList; } - completionList.Data = commonDataItem.Data; + var promotedCompletionItems = new List(); foreach (var completionItem in completionList.Items) { - completionItem.Data = null; + var clearedCompletionItem = completionItem with { Data = null }; + promotedCompletionItems.Add(clearedCompletionItem); } + + var promotedCompletionList = new VSCompletionList(promotedCompletionItems, completionList.IsIncomplete) + { + CommitCharacters = completionList.CommitCharacters, + Data = commonDataItem.Data, + }; + return promotedCompletionList; } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Definition/RazorDefinitionEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Definition/RazorDefinitionEndpoint.cs index 70d715dac62..c902ad02b6e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Definition/RazorDefinitionEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Definition/RazorDefinitionEndpoint.cs @@ -35,7 +35,7 @@ public RazorDefinitionEndpoint( _componentSearchEngine = componentSearchEngine ?? throw new ArgumentNullException(nameof(componentSearchEngine)); } - public DefinitionRegistrationOptions GetRegistrationOptions() + public DefinitionRegistrationOptions GetRegistrationOptions(DefinitionCapability capability, ClientCapabilities clientCapabilities) { return new DefinitionRegistrationOptions { @@ -108,10 +108,6 @@ public async Task Handle(DefinitionParams request, Canc }); } - public void SetCapability(DefinitionCapability capability) - { - } - internal static async Task GetOriginTagHelperBindingAsync( DocumentSnapshot documentSnapshot, RazorCodeDocument codeDocument, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/OmniSharpVSDiagnostic.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/OmniSharpVSDiagnostic.cs index 5fc34fc8412..1170824c527 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/OmniSharpVSDiagnostic.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/OmniSharpVSDiagnostic.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Diagnostics { - internal class OmniSharpVSDiagnostic : Diagnostic + internal record OmniSharpVSDiagnostic : Diagnostic { public static readonly PlatformExtensionConverter JsonConverter = new(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/RazorDiagnosticsEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/RazorDiagnosticsEndpoint.cs index 25ba876000d..22853746a36 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/RazorDiagnosticsEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Diagnostics/RazorDiagnosticsEndpoint.cs @@ -397,7 +397,7 @@ private OmniSharpVSDiagnostic[] MapDiagnostics( continue; } - diagnostic.Range = originalRange; + diagnostic = diagnostic with { Range = originalRange }; mappedDiagnostics.Add(diagnostic); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ExtendableServerCapabilities.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ExtendableServerCapabilities.cs deleted file mode 100644 index ab4cf7e9583..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ExtendableServerCapabilities.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; - -namespace Microsoft.AspNetCore.Razor.LanguageServer -{ - internal class ExtendableServerCapabilities : ServerCapabilities - { - public ExtendableServerCapabilities(ServerCapabilities inner, IEnumerable registrationExtensions) - { - FoldingRangeProvider = inner.FoldingRangeProvider; - ColorProvider = inner.ColorProvider; - ImplementationProvider = inner.ImplementationProvider; - TypeDefinitionProvider = inner.TypeDefinitionProvider; - Experimental = inner.Experimental; - ExecuteCommandProvider = inner.ExecuteCommandProvider; - DocumentLinkProvider = inner.DocumentLinkProvider; - RenameProvider = inner.RenameProvider; - DocumentOnTypeFormattingProvider = inner.DocumentOnTypeFormattingProvider; - DocumentRangeFormattingProvider = inner.DocumentRangeFormattingProvider; - DeclarationProvider = inner.DeclarationProvider; - DocumentFormattingProvider = inner.DocumentFormattingProvider; - CodeActionProvider = inner.CodeActionProvider; - WorkspaceSymbolProvider = inner.WorkspaceSymbolProvider; - DocumentSymbolProvider = inner.DocumentSymbolProvider; - DocumentHighlightProvider = inner.DocumentHighlightProvider; - ReferencesProvider = inner.ReferencesProvider; - DefinitionProvider = inner.DefinitionProvider; - SignatureHelpProvider = inner.SignatureHelpProvider; - CompletionProvider = inner.CompletionProvider; - HoverProvider = inner.HoverProvider; - TextDocumentSync = inner.TextDocumentSync; - CodeLensProvider = inner.CodeLensProvider; - Workspace = inner.Workspace; -#pragma warning disable CS0618 // Type or member is obsolete - SemanticTokensProvider = inner.SemanticTokensProvider; -#pragma warning restore CS0618 // Type or member is obsolete - - RazorLanguageServerCapability.AddTo(this); - - CapabilityExtensions = new Dictionary(StringComparer.Ordinal); - foreach (var registrationExtension in registrationExtensions) - { - var optionsResult = registrationExtension.GetRegistration(); - CapabilityExtensions[optionsResult.ServerCapability] = optionsResult.Options; - } - } - - [JsonExtensionData] - public Dictionary CapabilityExtensions { get; set; } - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingEndpoint.cs index 8ded612cee1..336dd11493e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingEndpoint.cs @@ -13,7 +13,6 @@ using Microsoft.CodeAnalysis.Text; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; using OmniSharp.Extensions.LanguageServer.Protocol.Document; using OmniSharp.Extensions.LanguageServer.Protocol.Models; @@ -67,17 +66,17 @@ public RazorFormattingEndpoint( _logger = loggerFactory.CreateLogger(); } - DocumentRangeFormattingRegistrationOptions IRegistration.GetRegistrationOptions() + public DocumentFormattingRegistrationOptions GetRegistrationOptions(DocumentFormattingCapability capability, ClientCapabilities clientCapabilities) { - return new DocumentRangeFormattingRegistrationOptions + return new DocumentFormattingRegistrationOptions { DocumentSelector = RazorDefaults.Selector, }; } - DocumentFormattingRegistrationOptions IRegistration.GetRegistrationOptions() + public DocumentRangeFormattingRegistrationOptions GetRegistrationOptions(DocumentRangeFormattingCapability capability, ClientCapabilities clientCapabilities) { - return new DocumentFormattingRegistrationOptions + return new DocumentRangeFormattingRegistrationOptions { DocumentSelector = RazorDefaults.Selector, }; @@ -148,13 +147,5 @@ public async Task Handle(DocumentRangeFormattingParams reques return editContainer; } #nullable restore - - public void SetCapability(DocumentFormattingCapability capability) - { - } - - public void SetCapability(DocumentRangeFormattingCapability capability) - { - } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/DefaultRazorHoverInfoService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/DefaultRazorHoverInfoService.cs index b368a38b92d..41f45ae170d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/DefaultRazorHoverInfoService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/DefaultRazorHoverInfoService.cs @@ -197,7 +197,7 @@ private HoverModel AttributeInfoToHover(IEnumerable de platformAgnosticClientCapabilities.SupportsVisualStudioExtensions; if (isVSClient && _vsLspTagHelperTooltipFactory.TryCreateTooltip(attrDescriptionInfo, out VSContainerElement classifiedTextElement)) { - var vsHover = new VSHover + var vsHover = new OmniSharpVSHover { Contents = new MarkedStringsOrMarkupContent(), Range = range, @@ -234,7 +234,7 @@ private HoverModel ElementInfoToHover(IEnumerable descripto platformAgnosticClientCapabilities.SupportsVisualStudioExtensions; if (isVSClient && _vsLspTagHelperTooltipFactory.TryCreateTooltip(elementDescriptionInfo, out VSContainerElement classifiedTextElement)) { - var vsHover = new VSHover + var vsHover = new OmniSharpVSHover { Contents = new MarkedStringsOrMarkupContent(), Range = range, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/VSHover.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/OmniSharpVSHover.cs similarity index 89% rename from src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/VSHover.cs rename to src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/OmniSharpVSHover.cs index 6e2d0e0c15b..58a2e8ac5d1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/VSHover.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/OmniSharpVSHover.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Hover { - internal class VSHover : HoverModel + internal record OmniSharpVSHover : HoverModel { [JsonProperty("_vs_rawContent")] public object? RawContent { get; set; } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/RazorHoverEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/RazorHoverEndpoint.cs index 1778772bc8f..98cf4266fa6 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/RazorHoverEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hover/RazorHoverEndpoint.cs @@ -19,7 +19,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Hover { internal class RazorHoverEndpoint : IHoverHandler { - private HoverCapability _capability; private readonly ILogger _logger; private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; private readonly DocumentResolver _documentResolver; @@ -103,12 +102,7 @@ public async Task Handle(HoverParams request, CancellationToken canc return hoverItem; } - public void SetCapability(HoverCapability capability) - { - _capability = capability; - } - - public HoverRegistrationOptions GetRegistrationOptions() + public HoverRegistrationOptions GetRegistrationOptions(HoverCapability capability, ClientCapabilities clientCapabilities) { return new HoverRegistrationOptions { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorConfigurationEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorConfigurationEndpoint.cs index 6c66a0d652b..8f128058b08 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorConfigurationEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorConfigurationEndpoint.cs @@ -34,12 +34,9 @@ public RazorConfigurationEndpoint(RazorLSPOptionsMonitor optionsMonitor, ILogger _logger = loggerFactory.CreateLogger(); } - public object GetRegistrationOptions() + public void SetCapability(DidChangeConfigurationCapability capability, ClientCapabilities clientCapabilities) { - return new TextDocumentRegistrationOptions() - { - DocumentSelector = RazorDefaults.Selector - }; + _capability = capability; } public async Task Handle(DidChangeConfigurationParams request, CancellationToken cancellationToken) @@ -50,10 +47,5 @@ public async Task Handle(DidChangeConfigurationParams request, Cancellatio return new Unit(); } - - public void SetCapability(DidChangeConfigurationCapability capability) - { - _capability = capability; - } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorDocumentSynchronizationEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorDocumentSynchronizationEndpoint.cs index 5e463faeed7..709405f2f63 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorDocumentSynchronizationEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorDocumentSynchronizationEndpoint.cs @@ -20,7 +20,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer { internal class RazorDocumentSynchronizationEndpoint : ITextDocumentSyncHandler { - private SynchronizationCapability _capability; private readonly ILogger _logger; private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; private readonly DocumentResolver _documentResolver; @@ -60,11 +59,6 @@ public RazorDocumentSynchronizationEndpoint( public TextDocumentSyncKind Change { get; } = TextDocumentSyncKind.Incremental; - public void SetCapability(SynchronizationCapability capability) - { - _capability = capability; - } - public async Task Handle(DidChangeTextDocumentParams notification, CancellationToken token) { var document = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() => @@ -121,7 +115,7 @@ public Task Handle(DidSaveTextDocumentParams notification, CancellationTok return Unit.Task; } - TextDocumentChangeRegistrationOptions IRegistration.GetRegistrationOptions() + public TextDocumentChangeRegistrationOptions GetRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) { return new TextDocumentChangeRegistrationOptions() { @@ -130,15 +124,23 @@ TextDocumentChangeRegistrationOptions IRegistration.GetRegistrationOptions() + TextDocumentOpenRegistrationOptions IRegistration.GetRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) { - return new TextDocumentRegistrationOptions() + return new TextDocumentOpenRegistrationOptions() { - DocumentSelector = RazorDefaults.Selector, + DocumentSelector = RazorDefaults.Selector + }; + } + + TextDocumentCloseRegistrationOptions IRegistration.GetRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) + { + return new TextDocumentCloseRegistrationOptions() + { + DocumentSelector = RazorDefaults.Selector }; } - TextDocumentSaveRegistrationOptions IRegistration.GetRegistrationOptions() + TextDocumentSaveRegistrationOptions IRegistration.GetRegistrationOptions(SynchronizationCapability capability, ClientCapabilities clientCapabilities) { return new TextDocumentSaveRegistrationOptions() { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageEndpoint.cs index 7f28aee0082..880d01c89fc 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageEndpoint.cs @@ -321,7 +321,7 @@ static void WrapCSharpSnippets(TextEdit[] snippetEdits) // Formatting doesn't work with syntax errors caused by the cursor marker ($0). // So, let's avoid the error by wrapping the cursor marker in a comment. var wrappedText = snippetEdit.NewText?.Replace("$0", "/*$0*/"); - snippetEdit.NewText = wrappedText; + snippetEdits[i] = snippetEdit with { NewText = wrappedText }; } } @@ -333,7 +333,7 @@ static void UnwrapCSharpSnippets(TextEdit[] snippetEdits) // Unwrap the cursor marker. var unwrappedText = snippetEdit.NewText?.Replace("/*$0*/", "$0"); - snippetEdit.NewText = unwrappedText; + snippetEdits[i] = snippetEdit with { NewText = unwrappedText }; } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs index ea36b2f89ad..696bb72f2fc 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs @@ -5,34 +5,35 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.AutoInsert; +using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization; using Microsoft.AspNetCore.Razor.LanguageServer.Completion; +using Microsoft.AspNetCore.Razor.LanguageServer.Definition; +using Microsoft.AspNetCore.Razor.LanguageServer.Diagnostics; using Microsoft.AspNetCore.Razor.LanguageServer.Formatting; using Microsoft.AspNetCore.Razor.LanguageServer.Hover; using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem; +using Microsoft.AspNetCore.Razor.LanguageServer.Refactoring; using Microsoft.AspNetCore.Razor.LanguageServer.Semantic; -using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions; +using Microsoft.AspNetCore.Razor.LanguageServer.Serialization; +using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Completion; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.VisualStudio.Editor.Razor; +using Newtonsoft.Json.Linq; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using OmniSharp.Extensions.LanguageServer.Protocol.Server; using OmniSharp.Extensions.LanguageServer.Server; -using System.Threading; -using Microsoft.AspNetCore.Razor.LanguageServer.Refactoring; -using Microsoft.AspNetCore.Razor.LanguageServer.Definition; -using Microsoft.CodeAnalysis.Razor.Workspaces; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.AspNetCore.Razor.LanguageServer.Tooltip; -using Microsoft.AspNetCore.Razor.LanguageServer.Diagnostics; namespace Microsoft.AspNetCore.Razor.LanguageServer { @@ -61,13 +62,8 @@ private RazorLanguageServer(ILanguageServer innerServer) public static Task CreateAsync(Stream input, Stream output, Trace trace, Action configure = null) { - Serializer.Instance.JsonSerializer.Converters.RegisterRazorConverters(); - - // Custom ClientCapabilities deserializer to extract platform specific capabilities - Serializer.Instance.JsonSerializer.Converters.Add(PlatformAgnosticClientCapabilities.JsonConverter); - Serializer.Instance.JsonSerializer.Converters.Add(PlatformAgnosticCompletionCapability.JsonConverter); - Serializer.Instance.JsonSerializer.Converters.Add(OmniSharpVSCompletionContext.JsonConverter); - Serializer.Instance.JsonSerializer.Converters.Add(OmniSharpVSDiagnostic.JsonConverter); + var serializer = new LspSerializer(); + serializer.RegisterRazorConverters(); ILanguageServer server = null; var logLevel = RazorLSPOptions.GetLogLevelForTrace(trace); @@ -88,17 +84,20 @@ public static Task CreateAsync(Stream input, Stream output, // I recommend that we attempt to resolve this and switch back to WithContentModifiedSupport(true) in the future, // I think that would mean either having 0 Serial Handlers in the whole LS, or making VSLanguageServerClient handle this more gracefully. .WithContentModifiedSupport(false) - .WithSerializer(Serializer.Instance) + .WithSerializer(serializer) .OnInitialized(async (s, request, response, cancellationToken) => { var handlersManager = s.GetRequiredService(); var jsonRpcHandlers = handlersManager.Descriptors.Select(d => d.Handler); var registrationExtensions = jsonRpcHandlers.OfType().Distinct(); - if (registrationExtensions.Any()) + foreach (var registrationExtension in registrationExtensions) { - var capabilities = new ExtendableServerCapabilities(response.Capabilities, registrationExtensions); - response.Capabilities = capabilities; + var optionsResult = registrationExtension.GetRegistration(); + response.Capabilities.ExtensionData[optionsResult.ServerCapability] = JObject.FromObject(optionsResult.Options); } + + RazorLanguageServerCapability.AddTo(response.Capabilities); + var fileChangeDetectorManager = s.Services.GetRequiredService(); await fileChangeDetectorManager.InitializedAsync(); @@ -133,7 +132,7 @@ public static Task CreateAsync(Stream input, Stream output, { services.AddLogging(builder => builder .SetMinimumLevel(logLevel) - .AddLanguageProtocolLogging(logLevel)); + .AddLanguageProtocolLogging()); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RazorComponentRenameEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RazorComponentRenameEndpoint.cs index fdd9e9d8d62..b8b74579588 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RazorComponentRenameEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RazorComponentRenameEndpoint.cs @@ -32,7 +32,6 @@ internal class RazorComponentRenameEndpoint : IRenameHandler private readonly ProjectSnapshotManager _projectSnapshotManager; private readonly RazorComponentSearchEngine _componentSearchEngine; private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; - private RenameCapability _capability; public RazorComponentRenameEndpoint( ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, @@ -48,7 +47,7 @@ public RazorComponentRenameEndpoint( _languageServerFeatureOptions = languageServerFeatureOptions ?? throw new ArgumentNullException(nameof(languageServerFeatureOptions)); } - public RenameRegistrationOptions GetRegistrationOptions() + public RenameRegistrationOptions GetRegistrationOptions(RenameCapability capability, ClientCapabilities clientCapabilities) { return new RenameRegistrationOptions { @@ -227,7 +226,7 @@ public void AddEditsForCodeDocument( DocumentUri uri, RazorCodeDocument codeDocument) { - var documentIdentifier = new VersionedTextDocumentIdentifier { Uri = uri }; + var documentIdentifier = new OptionalVersionedTextDocumentIdentifier { Uri = uri }; var tagHelperElements = codeDocument.GetSyntaxTree().Root .DescendantNodes() .Where(n => n.Kind == SyntaxKind.MarkupTagHelperElement) @@ -380,10 +379,5 @@ private static TagHelperDescriptor FindAssociatedTagHelper(TagHelperDescriptor t return null; } - - public void SetCapability(RenameCapability capability) - { - _capability = capability; - } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/ISemanticTokensLegendHandler.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/ISemanticTokensLegendHandler.cs index 4d5752cdfc0..65537ac6033 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/ISemanticTokensLegendHandler.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/ISemanticTokensLegendHandler.cs @@ -1,10 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 + #nullable enable + using Microsoft.AspNetCore.Razor.LanguageServer.Common; using OmniSharp.Extensions.JsonRpc; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensDeltaParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensDeltaParams.cs index 4af8b6cb268..564542d0eb1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensDeltaParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensDeltaParams.cs @@ -1,13 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models { -#pragma warning disable CS0618 // Type or member is obsolete - internal class ProvideSemanticTokensDeltaParams : SemanticTokensDeltaParams -#pragma warning restore CS0618 // Type or member is obsolete + internal record ProvideSemanticTokensDeltaParams : SemanticTokensDeltaParams { public long RequiredHostDocumentVersion { get; set; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensParams.cs index 7a34efa0323..270e9be8434 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensParams.cs @@ -1,13 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models { - [Obsolete("Proposed for the next version of the language server. May not work with all clients. May be removed or changed in the future.")] - public class ProvideSemanticTokensParams : SemanticTokensParams + public record ProvideSemanticTokensParams : SemanticTokensParams { public long RequiredHostDocumentVersion { get; set; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensResponse.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensResponse.cs index 1f9a5f5a740..45a4dc83a37 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensResponse.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/ProvideSemanticTokensResponse.cs @@ -1,9 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 + #nullable enable + using System; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { @@ -29,4 +30,3 @@ public override int GetHashCode() } } } -#pragma warning restore CS0618 diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/RazorSemanticTokensLegend.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/RazorSemanticTokensLegend.cs index cba8a241141..bfee65f9ffc 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/RazorSemanticTokensLegend.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/RazorSemanticTokensLegend.cs @@ -1,36 +1,36 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 + #nullable enable + using System.Collections.Generic; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models { internal class RazorSemanticTokensLegend { - private const string RazorComponentElementString = "razorComponentElement"; - private const string RazorComponentAttributeString = "RazorComponentAttribute"; - private const string RazorTagHelperElementString = "razorTagHelperElement"; - private const string RazorTagHelperAttributeString = "razorTagHelperAttribute"; - private const string RazorTransitionString = "razorTransition"; - private const string RazorDirectiveAttributeString = "razorDirectiveAttribute"; - private const string RazorDirectiveColonString = "razorDirectiveColon"; - private const string RazorDirectiveString = "razorDirective"; - private const string RazorCommentString = "razorComment"; - private const string RazorCommentTransitionString = "razorCommentTransition"; - private const string RazorCommentStarString = "razorCommentStar"; + private static readonly SemanticTokenType RazorComponentElementString = new SemanticTokenType("razorComponentElement"); + private static readonly SemanticTokenType RazorComponentAttributeString = new SemanticTokenType("RazorComponentAttribute"); + private static readonly SemanticTokenType RazorTagHelperElementString = new SemanticTokenType("razorTagHelperElement"); + private static readonly SemanticTokenType RazorTagHelperAttributeString = new SemanticTokenType("razorTagHelperAttribute"); + private static readonly SemanticTokenType RazorTransitionString = new SemanticTokenType("razorTransition"); + private static readonly SemanticTokenType RazorDirectiveAttributeString = new SemanticTokenType("razorDirectiveAttribute"); + private static readonly SemanticTokenType RazorDirectiveColonString = new SemanticTokenType("razorDirectiveColon"); + private static readonly SemanticTokenType RazorDirectiveString = new SemanticTokenType("razorDirective"); + private static readonly SemanticTokenType RazorCommentString = new SemanticTokenType("razorComment"); + private static readonly SemanticTokenType RazorCommentTransitionString = new SemanticTokenType("razorCommentTransition"); + private static readonly SemanticTokenType RazorCommentStarString = new SemanticTokenType("razorCommentStar"); - private const string MarkupTagDelimiterString = "markupTagDelimiter"; - private const string MarkupOperatorString = "markupOperator"; - private const string MarkupElementString = "markupElement"; - private const string MarkupAttributeString = "markupAttribute"; - private const string MarkupAttributeValueString = "markupAttributeValue"; - private const string MarkupAttributeQuoteString = "markupAttributeQuote"; - private const string MarkupTextLiteralString = "markupTextLiteral"; - private const string MarkupCommentPunctuationString = "markupCommentPunctuation"; - private const string MarkupCommentString = "markupComment"; + private static readonly SemanticTokenType MarkupTagDelimiterString = new SemanticTokenType("markupTagDelimiter"); + private static readonly SemanticTokenType MarkupOperatorString = new SemanticTokenType("markupOperator"); + private static readonly SemanticTokenType MarkupElementString = new SemanticTokenType("markupElement"); + private static readonly SemanticTokenType MarkupAttributeString = new SemanticTokenType("markupAttribute"); + private static readonly SemanticTokenType MarkupAttributeValueString = new SemanticTokenType("markupAttributeValue"); + private static readonly SemanticTokenType MarkupAttributeQuoteString = new SemanticTokenType("markupAttributeQuote"); + private static readonly SemanticTokenType MarkupTextLiteralString = new SemanticTokenType("markupTextLiteral"); + private static readonly SemanticTokenType MarkupCommentPunctuationString = new SemanticTokenType("markupCommentPunctuation"); + private static readonly SemanticTokenType MarkupCommentString = new SemanticTokenType("markupComment"); public static int RazorCommentTransition => TokenTypesLegend[RazorCommentTransitionString]; public static int RazorCommentStar => TokenTypesLegend[RazorCommentStarString]; @@ -59,90 +59,90 @@ internal class RazorSemanticTokensLegend public static int CSharpString => TokenTypesLegend["string"]; public static int CSharpPunctuation => TokenTypesLegend["punctuation"]; - public static readonly IReadOnlyList TokenTypes = new string[] { + public static readonly IReadOnlyList TokenTypes = new SemanticTokenType[] { // C# token types - "namespace", // 0 - "type", - "class", - "enum", - "interface", - "struct", - "typeParameter", - "parameter", - "variable", - "property", - "enumMember", // 10 - "event", - "function", - "member", - "macro", - "keyword", - "modifier", - "comment", - "string", - "number", - "regexp", // 20 - "operator", - "class name", - "constant name", - "keyword - control", - "delegate name", - "enum member name", - "enum name", - "event name", - "excluded code", - "extension method name", // 30 - "field name", - "interface name", - "label name", - "local name", - "method name", - "module name", - "namespace name", - "operator - overloaded", - "parameter name", - "property name", // 40 - "preprocessor keyword", - "preprocessor text", - "punctuation", - "record class name", - "record struct name", - "regex - alternation", - "regex - anchor", - "regex - character class", - "regex - comment", - "regex - grouping", // 50 - "regex - other escape", - "regex - quantifier", - "regex - self escaped character", - "regex - text", - "string - escape character", - "struct name", - "text", - "type parameter name", - "string - verbatim", - "whitespace", // 60 - "xml doc comment - attribute name", - "xml doc comment - attribute quotes", - "xml doc comment - attribute value", - "xml doc comment - cdata section", - "xml doc comment - comment", - "xml doc comment - delimiter", - "xml doc comment - entity reference", - "xml doc comment - name", - "xml doc comment - processing instruction", - "xml doc comment - text", // 70 - "xml literal - attribute name", - "xml literal - attribute quotes", - "xml literal - attribute value", - "xml literal - cdata section", - "xml literal - comment", - "xml literal - delimiter", - "xml literal - embedded expression", - "xml literal - entity reference", - "xml literal - name", - "xml literal - processing instruction", // 80 - "xml literal - text", + new SemanticTokenType("namespace"), // 0 + new SemanticTokenType("type"), + new SemanticTokenType("class"), + new SemanticTokenType("enum"), + new SemanticTokenType("interface"), + new SemanticTokenType("struct"), + new SemanticTokenType("typeParameter"), + new SemanticTokenType("parameter"), + new SemanticTokenType("variable"), + new SemanticTokenType("property"), + new SemanticTokenType("enumMember"), // 10 + new SemanticTokenType("event"), + new SemanticTokenType("function"), + new SemanticTokenType("member"), + new SemanticTokenType("macro"), + new SemanticTokenType("keyword"), + new SemanticTokenType("modifier"), + new SemanticTokenType("comment"), + new SemanticTokenType("string"), + new SemanticTokenType("number"), + new SemanticTokenType("regexp"), // 20 + new SemanticTokenType("operator"), + new SemanticTokenType("class name"), + new SemanticTokenType("constant name"), + new SemanticTokenType("keyword - control"), + new SemanticTokenType("delegate name"), + new SemanticTokenType("enum member name"), + new SemanticTokenType("enum name"), + new SemanticTokenType("event name"), + new SemanticTokenType("excluded code"), + new SemanticTokenType("extension method name"), // 30 + new SemanticTokenType("field name"), + new SemanticTokenType("interface name"), + new SemanticTokenType("label name"), + new SemanticTokenType("local name"), + new SemanticTokenType("method name"), + new SemanticTokenType("module name"), + new SemanticTokenType("namespace name"), + new SemanticTokenType("operator - overloaded"), + new SemanticTokenType("parameter name"), + new SemanticTokenType("property name"), // 40 + new SemanticTokenType("preprocessor keyword"), + new SemanticTokenType("preprocessor text"), + new SemanticTokenType("punctuation"), + new SemanticTokenType("record class name"), + new SemanticTokenType("record struct name"), + new SemanticTokenType("regex - alternation"), + new SemanticTokenType("regex - anchor"), + new SemanticTokenType("regex - character class"), + new SemanticTokenType("regex - comment"), + new SemanticTokenType("regex - grouping"), // 50 + new SemanticTokenType("regex - other escape"), + new SemanticTokenType("regex - quantifier"), + new SemanticTokenType("regex - self escaped character"), + new SemanticTokenType("regex - text"), + new SemanticTokenType("string - escape character"), + new SemanticTokenType("struct name"), + new SemanticTokenType("text"), + new SemanticTokenType("type parameter name"), + new SemanticTokenType("string - verbatim"), + new SemanticTokenType("whitespace"), // 60 + new SemanticTokenType("xml doc comment - attribute name"), + new SemanticTokenType("xml doc comment - attribute quotes"), + new SemanticTokenType("xml doc comment - attribute value"), + new SemanticTokenType("xml doc comment - cdata section"), + new SemanticTokenType("xml doc comment - comment"), + new SemanticTokenType("xml doc comment - delimiter"), + new SemanticTokenType("xml doc comment - entity reference"), + new SemanticTokenType("xml doc comment - name"), + new SemanticTokenType("xml doc comment - processing instruction"), + new SemanticTokenType("xml doc comment - text"), // 70 + new SemanticTokenType("xml literal - attribute name"), + new SemanticTokenType("xml literal - attribute quotes"), + new SemanticTokenType("xml literal - attribute value"), + new SemanticTokenType("xml literal - cdata section"), + new SemanticTokenType("xml literal - comment"), + new SemanticTokenType("xml literal - delimiter"), + new SemanticTokenType("xml literal - embedded expression"), + new SemanticTokenType("xml literal - entity reference"), + new SemanticTokenType("xml literal - name"), + new SemanticTokenType("xml literal - processing instruction"), // 80 + new SemanticTokenType("xml literal - text"), RazorTagHelperElementString, RazorTagHelperAttributeString, RazorTransitionString, @@ -165,22 +165,22 @@ internal class RazorSemanticTokensLegend RazorComponentAttributeString, }; - private static readonly string[] s_tokenModifiers = new string[] { + private static readonly IReadOnlyList s_tokenModifiers = new SemanticTokenModifier[] { // Razor - "None", + new SemanticTokenModifier("None"), // C# Modifiers - "static", + new SemanticTokenModifier("static"), }; public static readonly IReadOnlyDictionary TokenTypesLegend = GetMap(TokenTypes); public static readonly SemanticTokensLegend Instance = new SemanticTokensLegend { - TokenModifiers = new Container(s_tokenModifiers), - TokenTypes = new Container(TokenTypes), + TokenModifiers = new Container(s_tokenModifiers), + TokenTypes = new Container(TokenTypes), }; - private static IReadOnlyDictionary GetMap(IReadOnlyList tokens) + private static IReadOnlyDictionary GetMap(IReadOnlyList tokens) { var result = new Dictionary(); for (var i = 0; i < tokens.Count; i++) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/SemanticTokensLegendParams.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/SemanticTokensLegendParams.cs index 93b568a2890..5474c83f245 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/SemanticTokensLegendParams.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Models/SemanticTokensLegendParams.cs @@ -1,9 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 + #nullable enable + using MediatR; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensEndpoint.cs index 63204c0bac6..ab9c15739d0 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensEndpoint.cs @@ -1,23 +1,21 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 + #nullable enable + using System; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models; using Microsoft.Extensions.Logging; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Document.Proposals; using OmniSharp.Extensions.LanguageServer.Protocol.Client.Capabilities; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Document; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { - internal class RazorSemanticTokensEndpoint : ISemanticTokensHandler, ISemanticTokensRangeHandler, ISemanticTokensDeltaHandler + internal class RazorSemanticTokensEndpoint : ISemanticTokensFullHandler, ISemanticTokensRangeHandler, ISemanticTokensDeltaHandler { - private SemanticTokensCapability? _capability; - private readonly ILogger _logger; private readonly RazorSemanticTokensInfoService _semanticTokensInfoService; @@ -76,7 +74,7 @@ public RazorSemanticTokensEndpoint( return edits; } - public SemanticTokensRegistrationOptions GetRegistrationOptions() + public SemanticTokensRegistrationOptions GetRegistrationOptions(SemanticTokensCapability capability, ClientCapabilities clientCapabilities) { return new SemanticTokensRegistrationOptions { @@ -90,11 +88,6 @@ public SemanticTokensRegistrationOptions GetRegistrationOptions() }; } - public void SetCapability(SemanticTokensCapability capability) - { - _capability = capability; - } - private async Task HandleAsync(TextDocumentIdentifier textDocument, CancellationToken cancellationToken, Range? range = null) { var tokens = await _semanticTokensInfoService.GetSemanticTokensAsync(textDocument, range, cancellationToken); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensLegendEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensLegendEndpoint.cs index 5ca9d57b646..12038b1a617 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensLegendEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/RazorSemanticTokensLegendEndpoint.cs @@ -1,11 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 + #nullable enable + using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/DefaultRazorSemanticTokensInfoService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/DefaultRazorSemanticTokensInfoService.cs index efc2a697ad0..2556fba9536 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/DefaultRazorSemanticTokensInfoService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/DefaultRazorSemanticTokensInfoService.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 #nullable enable using System; @@ -22,7 +21,6 @@ using Microsoft.Extensions.Logging; using OmniSharp.Extensions.LanguageServer.Protocol; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokenInfoService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokenInfoService.cs index e667fa8edec..fdbf46130cf 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokenInfoService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/RazorSemanticTokenInfoService.cs @@ -1,13 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 #nullable enable using System.Threading; using System.Threading.Tasks; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/SemanticTokensEditsDiffer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/SemanticTokensEditsDiffer.cs index f0c2873ffba..8198029609c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/SemanticTokensEditsDiffer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Semantic/Services/SemanticTokensEditsDiffer.cs @@ -1,13 +1,13 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#pragma warning disable CS0618 + #nullable enable + using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; namespace Microsoft.AspNetCore.Razor.LanguageServer.Semantic { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Serialization/JsonFileDeserializer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Serialization/JsonFileDeserializer.cs index a530fc8c4fc..f34738fa619 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Serialization/JsonFileDeserializer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Serialization/JsonFileDeserializer.cs @@ -14,13 +14,21 @@ internal abstract class JsonFileDeserializer private class DefaultJsonFileDeserializer : JsonFileDeserializer { + private readonly LspSerializer _serializer; + + public DefaultJsonFileDeserializer() + { + _serializer = new LspSerializer(); + _serializer.RegisterRazorConverters(); + } + public override TValue Deserialize(string filePath) where TValue : class { using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete); using var reader = new StreamReader(stream); try { - var deserializedValue = (TValue)Serializer.Instance.JsonSerializer.Deserialize(reader, typeof(TValue)); + var deserializedValue = (TValue)_serializer.JsonSerializer.Deserialize(reader, typeof(TValue)); return deserializedValue; } catch diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Serialization/LspSerializerExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Serialization/LspSerializerExtensions.cs new file mode 100644 index 00000000000..46a824d4218 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Serialization/LspSerializerExtensions.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Razor.LanguageServer.Common.Serialization; +using Microsoft.AspNetCore.Razor.LanguageServer.Completion; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; +using Microsoft.AspNetCore.Razor.LanguageServer.Diagnostics; +using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; +using Microsoft.AspNetCore.Razor.LanguageServer.Serialization; + +namespace Microsoft.AspNetCore.Razor.LanguageServer.Serialization +{ + internal static class LspSerializerExtensions + { + public static void RegisterRazorConverters(this LspSerializer serializer) + { + if (serializer is null) + { + throw new ArgumentNullException(nameof(serializer)); + } + + // In all of the below we add our converters to both the serializer settings and the actual + // JsonSerializer. The reasoning behind this choice is that OmniSharp framework is not consistent + // in using one over the other so we want to protect ourselves. + + serializer.Settings.Converters.RegisterRazorConverters(); + serializer.JsonSerializer.Converters.RegisterRazorConverters(); + + serializer.Settings.Converters.Add(PlatformAgnosticClientCapabilities.JsonConverter); + serializer.JsonSerializer.Converters.Add(PlatformAgnosticClientCapabilities.JsonConverter); + serializer.Settings.Converters.Add(PlatformAgnosticCompletionCapability.JsonConverter); + serializer.JsonSerializer.Converters.Add(PlatformAgnosticCompletionCapability.JsonConverter); + serializer.Settings.Converters.Add(OmniSharpVSCompletionContext.JsonConverter); + serializer.JsonSerializer.Converters.Add(OmniSharpVSCompletionContext.JsonConverter); + serializer.Settings.Converters.Add(OmniSharpVSDiagnostic.JsonConverter); + serializer.JsonSerializer.Converters.Add(OmniSharpVSDiagnostic.JsonConverter); + serializer.Settings.Converters.Add(OmniSharpVSCodeActionContext.JsonConverter); + serializer.JsonSerializer.Converters.Add(OmniSharpVSCodeActionContext.JsonConverter); + } + } +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Tooltip/DefaultLSPTagHelperTooltipFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Tooltip/DefaultLSPTagHelperTooltipFactory.cs index 030be51bb3e..d92a7b98dd7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Tooltip/DefaultLSPTagHelperTooltipFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Tooltip/DefaultLSPTagHelperTooltipFactory.cs @@ -77,10 +77,9 @@ public override bool TryCreateTooltip(AggregateBoundElementDescription elementDe tooltipContent = new MarkupContent { - Kind = GetMarkupKind() + Kind = GetMarkupKind(), + Value = descriptionBuilder.ToString(), }; - - tooltipContent.Value = descriptionBuilder.ToString(); return true; } @@ -147,10 +146,9 @@ public override bool TryCreateTooltip(AggregateBoundAttributeDescription attribu tooltipContent = new MarkupContent { - Kind = GetMarkupKind() + Kind = GetMarkupKind(), + Value = descriptionBuilder.ToString(), }; - - tooltipContent.Value = descriptionBuilder.ToString(); return true; } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/DefaultRazorLanguageServerCustomMessageTarget.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/DefaultRazorLanguageServerCustomMessageTarget.cs index 1b476ee7c17..8797d19010e 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/DefaultRazorLanguageServerCustomMessageTarget.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/DefaultRazorLanguageServerCustomMessageTarget.cs @@ -18,8 +18,8 @@ using Microsoft.VisualStudio.Threading; using Newtonsoft.Json.Linq; using OmniSharpConfigurationParams = OmniSharp.Extensions.LanguageServer.Protocol.Models.ConfigurationParams; -using SemanticTokens = OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals.SemanticTokens; -using SemanticTokensParams = OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals.SemanticTokensParams; +using SemanticTokens = OmniSharp.Extensions.LanguageServer.Protocol.Models.SemanticTokens; +using SemanticTokensParams = OmniSharp.Extensions.LanguageServer.Protocol.Models.SemanticTokensParams; using Task = System.Threading.Tasks.Task; namespace Microsoft.VisualStudio.LanguageServerClient.Razor @@ -278,12 +278,9 @@ public override async Task ResolveCodeActionsAsync(VSInter return results.FirstOrDefault(c => c.Result != null).Result; } - [Obsolete] -#pragma warning disable CS0809 // Obsolete member overrides non-obsolete member public override async Task ProvideSemanticTokensAsync( ProvideSemanticTokensParams semanticTokensParams, CancellationToken cancellationToken) -#pragma warning restore CS0809 // Obsolete member overrides non-obsolete member { if (semanticTokensParams is null) { @@ -304,7 +301,8 @@ public override async Task ProvideSemanticTokensA return new ProvideSemanticTokensResponse(result: null, csharpDoc.HostDocumentSyncVersion); } - semanticTokensParams.TextDocument.Uri = csharpDoc.Uri; + var csharpTextDocument = semanticTokensParams.TextDocument with { Uri = csharpDoc.Uri }; + semanticTokensParams = semanticTokensParams with { TextDocument = csharpTextDocument }; var newParams = new SemanticTokensParams { diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorLanguageServerCustomMessageTarget.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorLanguageServerCustomMessageTarget.cs index 73b2da38434..2a7ea22269d 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorLanguageServerCustomMessageTarget.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorLanguageServerCustomMessageTarget.cs @@ -42,9 +42,7 @@ internal abstract class RazorLanguageServerCustomMessageTarget // Called by the Razor Language Server to provide semantic tokens from the platform. [JsonRpcMethod(LanguageServerConstants.RazorProvideSemanticTokensEndpoint, UseSingleObjectParameterDeserialization = true)] -#pragma warning disable CS0618 // Type or member is obsolete public abstract Task ProvideSemanticTokensAsync(ProvideSemanticTokensParams semanticTokensParams, CancellationToken cancellationToken); -#pragma warning restore CS0618 // Type or member is obsolete // Called by the Razor Language Server to provide semantic tokens edits from the platform. [JsonRpcMethod(LanguageServerConstants.RazorProvideSemanticTokensEditsEndpoint, UseSingleObjectParameterDeserialization = true)] diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/AssemblyCodeBases.cs b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/AssemblyCodeBases.cs index 32d4b1f6675..1cc09befc9b 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/AssemblyCodeBases.cs +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/AssemblyCodeBases.cs @@ -26,3 +26,4 @@ [assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\Microsoft.Extensions.FileProviders.Physical.dll")] [assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\System.IO.Pipelines.dll")] [assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\System.Reactive.dll")] +[assembly: ProvideCodeBase(CodeBase = @"$PackageFolder$\System.Threading.Channels.dll")] diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.csproj b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.csproj index 4f3f0d1e356..514073263a7 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.csproj +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Microsoft.VisualStudio.RazorExtension.csproj @@ -146,6 +146,7 @@ + diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/source.extension.vsixmanifest b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/source.extension.vsixmanifest index 8e8b2e936de..98756a097ac 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/source.extension.vsixmanifest +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/source.extension.vsixmanifest @@ -58,6 +58,7 @@ + diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs index b6adbcbf3e6..ddaa97593c6 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndpointTest.cs @@ -46,11 +46,11 @@ public async Task Handle_NoDocument() { _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -79,11 +79,11 @@ public async Task Handle_UnsupportedDocument() { _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -111,11 +111,11 @@ public async Task Handle_NoProviders() { _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -146,11 +146,11 @@ public async Task Handle_OneRazorCodeActionProvider() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -183,11 +183,11 @@ public async Task Handle_OneCSharpCodeActionProvider() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -218,11 +218,11 @@ public async Task Handle_OneCodeActionProviderWithMultipleCodeActions() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -260,11 +260,11 @@ public async Task Handle_MultipleCodeActionProvidersWithMultipleCodeActions() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -302,11 +302,11 @@ public async Task Handle_MultipleProviders() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -337,11 +337,11 @@ public async Task Handle_OneNullReturningProvider() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -380,11 +380,11 @@ public async Task Handle_MultipleMixedProvider() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -417,11 +417,11 @@ public async Task Handle_MultipleMixedProvider_SupportsCodeActionResolveTrue() _supportsCodeActionResolve = true }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -464,11 +464,11 @@ public async Task Handle_MultipleMixedProvider_SupportsCodeActionResolveFalse() _supportsCodeActionResolve = false }; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; // Act @@ -509,11 +509,11 @@ public async Task GenerateRazorCodeActionContextAsync_WithSelectionRange() var initialRange = new Range(new Position(0, 1), new Position(0, 1)); var selectionRange = new Range(new Position(0, 5), new Position(0, 5)); - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = initialRange, - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() { SelectionRange = selectionRange, } @@ -549,11 +549,11 @@ public async Task GenerateRazorCodeActionContextAsync_WithoutSelectionRange() }; var initialRange = new Range(new Position(0, 1), new Position(0, 1)); - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = initialRange, - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() { SelectionRange = null } @@ -593,11 +593,11 @@ public async Task GetCSharpCodeActionsFromLanguageServerAsync_InvalidRangeMappin }; var initialRange = new Range(new Position(0, 1), new Position(0, 1)); - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = initialRange, - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; var context = await codeActionEndpoint.GenerateRazorCodeActionContextAsync(request, default); @@ -635,11 +635,11 @@ public async Task GetCSharpCodeActionsFromLanguageServerAsync_ReturnsCodeActions }; var initialRange = new Range(new Position(0, 1), new Position(0, 1)); - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = initialRange, - Context = new ExtendedCodeActionContext() + Context = new OmniSharpVSCodeActionContext() }; var context = await codeActionEndpoint.GenerateRazorCodeActionContextAsync(request, default); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionResolutionEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionResolutionEndpointTest.cs index 85ef89ac9db..484849243ad 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionResolutionEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionResolutionEndpointTest.cs @@ -443,7 +443,7 @@ internal MockCSharpCodeActionResolver(string action) public override Task ResolveAsync(CSharpCodeActionParams csharpParams, CodeAction codeAction, CancellationToken cancellationToken) { - codeAction.Edit = new WorkspaceEdit(); + codeAction = codeAction with { Edit = new WorkspaceEdit() }; return Task.FromResult(codeAction); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs index 7f125da0c46..2608849c3fb 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ComponentAccessibilityCodeActionProviderTest.cs @@ -6,7 +6,6 @@ using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Components; -using Microsoft.AspNetCore.Razor.LanguageServer.CodeActions.Models; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Editor.Razor; @@ -26,7 +25,7 @@ public async Task Handle_NoTagName_DoesNotProvideLightBulb() // Arrange var documentPath = "c:/Test.razor"; var contents = "<"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 1), new Position(0, 1)), @@ -50,7 +49,7 @@ public async Task Handle_InvalidSyntaxTree_NoStartNode() // Arrange var documentPath = "c:/Test.razor"; var contents = ""; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -75,7 +74,7 @@ public async Task Handle_CursorOutsideComponent() // Arrange var documentPath = "c:/Test.razor"; var contents = " "; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 0), new Position(0, 0)), @@ -99,7 +98,7 @@ public async Task Handle_ExistingComponent_SupportsFileCreationTrue_ReturnsResul // Arrange var documentPath = "c:/Test.razor"; var contents = ""; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 0), new Position(0, 0)), @@ -142,7 +141,7 @@ public async Task Handle_NewComponent_SupportsFileCreationTrue_ReturnsResult() // Arrange var documentPath = "c:/Test.razor"; var contents = ""; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 0), new Position(0, 0)), @@ -168,7 +167,7 @@ public async Task Handle_NewComponent_SupportsFileCreationFalse_ReturnsEmpty() // Arrange var documentPath = "c:/Test.razor"; var contents = ""; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 0), new Position(0, 0)), @@ -193,7 +192,7 @@ public async Task Handle_ExistingComponent_SupportsFileCreationFalse_ReturnsResu // Arrange var documentPath = "c:/Test.razor"; var contents = ""; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(new Position(0, 0), new Position(0, 0)), @@ -224,7 +223,7 @@ public async Task Handle_ExistingComponent_SupportsFileCreationFalse_ReturnsResu }); } - private static RazorCodeActionContext CreateRazorCodeActionContext(RazorCodeActionParams request, SourceLocation location, string filePath, string text, SourceSpan componentSourceSpan, bool supportsFileCreation = true) + private static RazorCodeActionContext CreateRazorCodeActionContext(CodeActionParams request, SourceLocation location, string filePath, string text, SourceSpan componentSourceSpan, bool supportsFileCreation = true) { var shortComponent = TagHelperDescriptorBuilder.Create(ComponentMetadata.Component.TagHelperKind, "Fully.Qualified.Component", "TestAssembly"); shortComponent.TagMatchingRule(rule => rule.TagName = "Component"); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs index 74be4bdde81..fab943dc916 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/Razor/ExtractToCodeBehindCodeActionProviderTest.cs @@ -27,7 +27,7 @@ public async Task Handle_InvalidFileKind() // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@code {}"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -52,7 +52,7 @@ public async Task Handle_OutsideCodeDirective() // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@code {}"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -76,7 +76,7 @@ public async Task Handle_InCodeDirectiveBlock_ReturnsNull() // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@code {}"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -100,7 +100,7 @@ public async Task Handle_InCodeDirectiveMalformed_ReturnsNull() // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@code"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -124,7 +124,7 @@ public async Task Handle_InCodeDirectiveWithMarkup_ReturnsNull() // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@code { void Test() {

Hello, world!

} }"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -148,7 +148,7 @@ public async Task Handle_InCodeDirective_SupportsFileCreationTrue_ReturnsResult( // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@code { private var x = 1; }"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -178,7 +178,7 @@ public async Task Handle_InCodeDirective_SupportsFileCreationFalse_ReturnsNull() // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@code { private var x = 1; }"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -202,7 +202,7 @@ public async Task Handle_InFunctionsDirective_SupportsFileCreationTrue_ReturnsRe // Arrange var documentPath = "c:/Test.razor"; var contents = "@page \"/test\"\n@functions { private var x = 1; }"; - var request = new RazorCodeActionParams() + var request = new CodeActionParams() { TextDocument = new TextDocumentIdentifier(new Uri(documentPath)), Range = new Range(), @@ -226,7 +226,7 @@ public async Task Handle_InFunctionsDirective_SupportsFileCreationTrue_ReturnsRe Assert.Equal(47, actionParams.RemoveEnd); } - private static RazorCodeActionContext CreateRazorCodeActionContext(RazorCodeActionParams request, SourceLocation location, string filePath, string text, bool supportsFileCreation = true) + private static RazorCodeActionContext CreateRazorCodeActionContext(CodeActionParams request, SourceLocation location, string filePath, string text, bool supportsFileCreation = true) { var codeDocument = TestRazorCodeDocument.CreateEmpty(); codeDocument.SetFileKind(FileKinds.Component); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/ExtendableServerCapabilitiesTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/ExtendableServerCapabilitiesTest.cs deleted file mode 100644 index cc2c98b7ed2..00000000000 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/ExtendableServerCapabilitiesTest.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -using System.Linq; -using Newtonsoft.Json; -using OmniSharp.Extensions.LanguageServer.Protocol.Server.Capabilities; -using Xunit; - -namespace Microsoft.AspNetCore.Razor.LanguageServer -{ - public class ExtendableServerCapabilitiesTest - { - [Fact] - public void Constructor_RegistrationExtensions_Populates() - { - // Arrange - var registrationExtension1 = new TestRegistrationExtension("test1"); - var registrationExtension2 = new TestRegistrationExtension("test2"); - var registrations = new IRegistrationExtension[] { registrationExtension1, registrationExtension2 }; - var baseCapability = new ServerCapabilities(); - - // Act - var extendableCapabilities = new ExtendableServerCapabilities(baseCapability, registrations); - - // Assert - Assert.Equal(new[] { "test1", "test2" }, extendableCapabilities.CapabilityExtensions.Keys.ToArray()); - } - - [Fact] - public void CapabilityExtensions_RoundTripsCorrectly() - { - // Arrange - var registrationExtension = new TestRegistrationExtension("test1"); - var registrations = new IRegistrationExtension[] { registrationExtension }; - var baseCapability = new ServerCapabilities(); - var extendableCapabilities = new ExtendableServerCapabilities(baseCapability, registrations) { - TextDocumentSync = new TextDocumentSync(TextDocumentSyncKind.Full), - }; - - // Act - var serialized = JsonConvert.SerializeObject(extendableCapabilities); - var deserialized = JsonConvert.DeserializeObject(serialized); - - // Assert - Assert.True(deserialized.Test1); - } - - private class VSCapabilities : ServerCapabilities - { - public bool Test1 { get; set; } - } - - private class TestRegistrationExtension : IRegistrationExtension - { - private readonly string _capabilityName; - - public TestRegistrationExtension(string capabilityName) - { - _capabilityName = capabilityName; - } - - public RegistrationExtensionResult GetRegistration() => new RegistrationExtensionResult(_capabilityName, true); - } - } -} diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Hover/DefaultRazorHoverInfoServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Hover/DefaultRazorHoverInfoServiceTest.cs index 1e5ff8a862d..19af2452aa6 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Hover/DefaultRazorHoverInfoServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Hover/DefaultRazorHoverInfoServiceTest.cs @@ -360,7 +360,7 @@ public void GetHoverInfo_TagHelper_Element_VSClient_ReturnVSHover() ((PlatformAgnosticClientCapabilities)clientCapabilities).SupportsVisualStudioExtensions = true; // Act - var vsHover = (VSHover)service.GetHoverInfo(codeDocument, location, clientCapabilities); + var vsHover = (OmniSharpVSHover)service.GetHoverInfo(codeDocument, location, clientCapabilities); // Assert Assert.False(vsHover.Contents.HasMarkupContent); @@ -394,7 +394,7 @@ public void GetHoverInfo_TagHelper_Attribute_VSClient_ReturnVSHover() ((PlatformAgnosticClientCapabilities)clientCapabilities).SupportsVisualStudioExtensions = true; // Act - var vsHover = (VSHover)service.GetHoverInfo(codeDocument, location, clientCapabilities); + var vsHover = (OmniSharpVSHover)service.GetHoverInfo(codeDocument, location, clientCapabilities); // Assert Assert.False(vsHover.Contents.HasMarkupContent); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentSynchronizationEndpointTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentSynchronizationEndpointTest.cs index 201e43dfd12..4b96e5613d6 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentSynchronizationEndpointTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorDocumentSynchronizationEndpointTest.cs @@ -114,7 +114,7 @@ public async Task Handle_DidChangeTextDocument_UpdatesDocument() var request = new DidChangeTextDocumentParams() { ContentChanges = new Container(change), - TextDocument = new VersionedTextDocumentIdentifier() + TextDocument = new OptionalVersionedTextDocumentIdentifier() { Uri = new Uri(documentPath), Version = 1337, diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/DefaultRazorSemanticTokenInfoServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/DefaultRazorSemanticTokenInfoServiceTest.cs index bfab6140e48..1dfa6495a6f 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/DefaultRazorSemanticTokenInfoServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/DefaultRazorSemanticTokenInfoServiceTest.cs @@ -22,7 +22,6 @@ using Moq.Protected; using OmniSharp.Extensions.JsonRpc; using OmniSharp.Extensions.LanguageServer.Protocol.Models; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; using Xunit; using OmniSharpRange = OmniSharp.Extensions.LanguageServer.Protocol.Models.Range; @@ -977,18 +976,18 @@ public void ApplyEditsToPreviousCSharpDoc_EnsureAccurateInsertionDeletionEdits() var textDocumentIdentifier = GetIdentifier(isRazor); // Act - var edits = (await service.GetSemanticTokensEditsAsync(textDocumentIdentifier, previousResultId, CancellationToken.None)).Value; + var edits = await service.GetSemanticTokensEditsAsync(textDocumentIdentifier, previousResultId, CancellationToken.None); // Assert if (expectDelta) { - AssertSemanticTokensEditsMatchesBaseline(edits); + AssertSemanticTokensEditsMatchesBaseline(edits!); - return (edits.Delta!.ResultId, service, clientMock!); + return (edits!.Delta!.ResultId, service, clientMock!); } else { - AssertSemanticTokensMatchesBaseline(edits.Full!.Data); + AssertSemanticTokensMatchesBaseline(edits!.Full!.Data); return (edits.Full.ResultId, service, clientMock!); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/SemanticTokenTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/SemanticTokenTestBase.cs index 7c7d0cb2485..6c07332d28e 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/SemanticTokenTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Semantic/SemanticTokenTestBase.cs @@ -13,7 +13,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Completion; using Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models; using Microsoft.CodeAnalysis; -using OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals; +using OmniSharp.Extensions.LanguageServer.Protocol.Models; using Xunit; using Xunit.Sdk; @@ -122,14 +122,14 @@ internal void AssertSemanticTokensEditsMatchesBaseline(SemanticTokensFullOrDelta var semanticEdits = GetBaselineDeltaTokens(baselineFileName); - if (semanticEdits!.Value.IsDelta && edits.IsDelta) + if (semanticEdits!.IsDelta && edits.IsDelta) { // We can't compare the ResultID because it's from a previous run - Assert.Equal(semanticEdits.Value.Delta?.Edits, edits.Delta?.Edits, SemanticEditComparer.Instance); + Assert.Equal(semanticEdits.Delta?.Edits, edits.Delta?.Edits, SemanticEditComparer.Instance); } - else if (semanticEdits.Value.IsFull && edits.IsFull) + else if (semanticEdits.IsFull && edits.IsFull) { - Assert.Equal(semanticEdits.Value.Full, edits.Full); + Assert.Equal(semanticEdits.Full, edits.Full); } else { @@ -155,7 +155,7 @@ internal void AssertSemanticTokensEditsMatchesBaseline(SemanticTokensFullOrDelta internal static RazorSemanticTokensEdit[] GetRazorEdits(SemanticTokensFullOrDelta? baselineDelta) #pragma warning restore CS0618 // Type or member is obsolete { - var edits = baselineDelta!.Value.Delta!.Edits.ToArray(); + var edits = baselineDelta!.Delta!.Edits.ToArray(); var razorSemanticTokenEdits = new RazorSemanticTokensEdit[edits.Length]; for (var i = 0; i < edits.Length; i++) { @@ -258,16 +258,10 @@ private static void GenerateSemanticBaseline(IEnumerable? actual, string ba if (strArray[0].Equals("Delta", StringComparison.Ordinal)) { - var delta = new SemanticTokensDelta(); var edits = new List(); var i = 1; while (i < strArray.Length - 1) { - var edit = new SemanticTokensEdit - { - Start = int.Parse(strArray[i], Thread.CurrentThread.CurrentCulture), - DeleteCount = int.Parse(strArray[i + 1], Thread.CurrentThread.CurrentCulture) - }; i += 3; var inArray = true; var data = new List(); @@ -285,10 +279,18 @@ private static void GenerateSemanticBaseline(IEnumerable? actual, string ba i++; } - edit.Data = data.ToImmutableArray(); + var edit = new SemanticTokensEdit + { + Start = int.Parse(strArray[i], Thread.CurrentThread.CurrentCulture), + DeleteCount = int.Parse(strArray[i + 1], Thread.CurrentThread.CurrentCulture), + Data = data.ToImmutableArray(), + }; edits.Add(edit); } - delta.Edits = edits; + var delta = new SemanticTokensDelta() + { + Edits = edits, + }; return new SemanticTokensFullOrDelta(delta); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Serialization/PlatformAgnosticClientCapabilitiesJsonConverterTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Serialization/PlatformAgnosticClientCapabilitiesJsonConverterTest.cs index 25fff212580..f07c8e915fd 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Serialization/PlatformAgnosticClientCapabilitiesJsonConverterTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Serialization/PlatformAgnosticClientCapabilitiesJsonConverterTest.cs @@ -3,8 +3,10 @@ using System.IO; using System.Linq; +using Microsoft.AspNetCore.Razor.LanguageServer.Serialization; using Newtonsoft.Json; using OmniSharp.Extensions.LanguageServer.Protocol.Models; +using OmniSharp.Extensions.LanguageServer.Protocol.Serialization; using Xunit; namespace Microsoft.AspNetCore.Razor.LanguageServer.Refactoring.Test @@ -75,11 +77,11 @@ public void ReadJson_ReadsValues() } }"; var stringReader = new StringReader(rawJson); - var serializer = OmniSharp.Extensions.LanguageServer.Protocol.Serialization.Serializer.Instance.JsonSerializer; - serializer.Converters.Add(PlatformAgnosticClientCapabilities.JsonConverter); + var serializer = new LspSerializer(); + serializer.RegisterRazorConverters(); // Act - var capabilities = serializer.Deserialize(new JsonTextReader(stringReader)); + var capabilities = serializer.JsonSerializer.Deserialize(new JsonTextReader(stringReader)); // Assert Assert.True(capabilities.Workspace.ApplyEdit); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/DefaultRazorLanguageServerCustomMessageTargetTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/DefaultRazorLanguageServerCustomMessageTargetTest.cs index d29b35670e9..2561d220ecb 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/DefaultRazorLanguageServerCustomMessageTargetTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/DefaultRazorLanguageServerCustomMessageTargetTest.cs @@ -428,14 +428,14 @@ public async Task ProvideSemanticTokensAsync_ReturnsSemanticTokensAsync() documentManager.Setup(manager => manager.TryGetDocument(testDocUri, out testDocument)) .Returns(true); - var expectedcSharpResults = new OmniSharp.Extensions.LanguageServer.Protocol.Models.Proposals.SemanticTokens(); + var expectedcSharpResults = new OmniSharp.Extensions.LanguageServer.Protocol.Models.SemanticTokens(); var requestInvoker = new Mock(MockBehavior.Strict); - requestInvoker.Setup(invoker => invoker.ReinvokeRequestOnServerAsync( + requestInvoker.Setup(invoker => invoker.ReinvokeRequestOnServerAsync( Methods.TextDocumentSemanticTokensFullName, LanguageServerKind.CSharp.ToLanguageServerName(), - It.IsAny(), + It.IsAny(), It.IsAny() - )).Returns(Task.FromResult(new ReinvokeResponse(_languageClient, expectedcSharpResults))); + )).Returns(Task.FromResult(new ReinvokeResponse(_languageClient, expectedcSharpResults))); var uIContextManager = new Mock(MockBehavior.Strict); var disposable = new Mock(MockBehavior.Strict);