Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cohosting OnAutoInsert endpoint #10776

Merged
merged 64 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
b9abac6
Factoring out AutoInsertService
alexgav Jul 19, 2024
330a670
Switch non-cohost endpoint to use new AutoInsertService
alexgav Jul 19, 2024
fe520b8
Adding Remote and OOB AutoInsertService classes and OnAutoInsertProvi…
alexgav Jul 21, 2024
c5506e6
Add common code for capabilities
alexgav Jul 26, 2024
3f74c03
Add cohost OnAutoInsert endpoint
alexgav Jul 26, 2024
85cf1f1
Parameter rename
alexgav Jul 27, 2024
be0e85f
Update src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/AutoInse…
alexgav Jul 27, 2024
3ee7479
Update src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/AutoInse…
alexgav Jul 27, 2024
5cb62c3
Update src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/AutoInse…
alexgav Jul 27, 2024
38c9436
Fixup after rebase
alexgav Jul 27, 2024
4a6d7f6
More post-build cleanup
alexgav Jul 27, 2024
09452b5
Move common HTML and C# auto-insert trigger chars per CR suggestion
alexgav Jul 27, 2024
447dd54
More cleanup after rebase
alexgav Jul 29, 2024
70430a4
Add IOnAutoInsertTiggerCharacterProvider per CR suggestion
alexgav Jul 29, 2024
02db4e4
Removing trigger characters property from RemoteAutoInsertService per…
alexgav Jul 29, 2024
b3ec796
Switch to using RemoteResponse
alexgav Aug 7, 2024
2813a97
Fixup bad resolve after rebase, and extra whitespace in RazorLangauge…
alexgav Aug 7, 2024
f19fd7f
Complete capabilities check in CohostingOnAutoInsertEndpoing registra…
alexgav Aug 8, 2024
1dbc2c2
Change input position type to serializable :LinePosition
alexgav Aug 8, 2024
c324f34
Fixing RemoteInsertTextEdit to use properly annotated (for serializat…
alexgav Aug 8, 2024
10c8c15
Support for delegating auto-insert to C#
alexgav Aug 9, 2024
c5dd51a
Fixup after rebase
alexgav Aug 9, 2024
2fd5c8a
Fixup AutoClosingTagOnAutoInsertProviderTest tests
alexgav Aug 9, 2024
75f73a0
Fixinfg up CloseTextTagOnAutoInsertProviderTest tests
alexgav Aug 10, 2024
2c40c10
Fixing up OnAutoInsertEndpointTest (which also tests the new AutoInse…
alexgav Aug 10, 2024
770808f
Fixing duplicate OnAutoInsert handler registration (bad merge after r…
alexgav Aug 10, 2024
bf7c45e
Fixes to MEF composition issue and capabilities check
alexgav Aug 10, 2024
ced0724
Fixing incorrect export type
alexgav Aug 12, 2024
52c7acb
Minor cleanup per CR suggestions
alexgav Aug 13, 2024
6808099
Switching parameters to RazorCodeDocument and removing async in a lot…
alexgav Aug 13, 2024
d72bbb0
Fixing build - removing unneeded using
alexgav Aug 14, 2024
4170302
Fix RemoteAutoInsertService logic to follow existing code (always pre…
alexgav Aug 14, 2024
5c36ad1
Check allowed trigger characters before delegating to other languages…
alexgav Aug 14, 2024
e695e4a
Plumbing through actual option values we need and using them
alexgav Aug 14, 2024
ca86e8f
Fixup After Rebase
alexgav Aug 21, 2024
0970a46
Consuming RazorFormattingService in remote OnAutoInsert service
alexgav Aug 21, 2024
8db5313
Fixing exception in RemoteProjectSnapshot.Configuration
alexgav Aug 22, 2024
2357c4a
Switch to PreferHtmlInAttributeValuesDocumentPositionInfoStrategy as …
alexgav Aug 22, 2024
536fe77
Cleanup usings
alexgav Aug 22, 2024
5e47c94
More usings cleanup
alexgav Aug 22, 2024
e2d4b65
PR feedback - minor cleanup and removal of InsertTextEdit type in fav…
alexgav Aug 22, 2024
614af2e
PR feedback - removing MEF usage from RemoteAdhocWorkspaceFactory, mi…
alexgav Aug 22, 2024
0f1d30d
PR feedback
alexgav Aug 22, 2024
01d3d80
Type and method renames, minor cleanup per PR feedback
alexgav Aug 22, 2024
7d61fbf
Renaming interface methods, removing unnecessary usage of FrozenSet
alexgav Aug 22, 2024
a7df9ef
Use ImmutableArray to store providers
alexgav Aug 23, 2024
34beda3
Switching to bool and out on IAutoInsertService and implementation
alexgav Aug 23, 2024
a4beaef
Cleaned up document position info calculation per PR feedback
alexgav Aug 23, 2024
4613364
Minor cleanup in RemoteAutoInsertService
alexgav Aug 23, 2024
bf389fb
Cleanup trigger character calculation in CohostOnAutoInsertEndpoint
alexgav Aug 23, 2024
c9e5130
Formatting changes, VsLspFactory usage
alexgav Aug 23, 2024
9d339ef
Revert to MEF DI in RemoteAdhocWorkspaceFactory/RemoteRazorFormatting…
alexgav Aug 23, 2024
a629cf3
Removing Rolsyn to VS LSP extension methods
alexgav Aug 23, 2024
46c9356
Switch to raw strings in tests and minor whitespace cleanup
alexgav Aug 23, 2024
0eab010
Rename per PR feedback suggestion to better indicate the purpose
alexgav Aug 24, 2024
7bb3d32
Cleanup formatting code document acquisition per PR feedback
alexgav Aug 27, 2024
e53bf51
Removing redundant assert as compiler is already doing the check
alexgav Aug 27, 2024
348f76f
Unnecessary assignment cleanup
alexgav Aug 27, 2024
c984b46
Misc PR feedback cleanup
alexgav Aug 28, 2024
3f9fe84
Made GetGeneratedOutputAsync an extension method per PR feedback
alexgav Aug 28, 2024
69105c1
Remaining MEF parameter attrivute formatting changes
alexgav Aug 28, 2024
137d9ad
Last of the PR feedback.
alexgav Aug 28, 2024
7715a4c
Fixing most unit test failures.
alexgav Aug 29, 2024
ffaa2ef
Fixing last 4 unit test failures
alexgav Aug 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eng/targets/Services.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
<ServiceHubService Include="Microsoft.VisualStudio.Razor.DocumentSymbol" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteDocumentSymbolService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.GoToDefinition" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteGoToDefinitionService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.Rename" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteRenameService+Factory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.AutoInsert" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteAutoInsertService+Factory" />
</ItemGroup>
</Project>

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// Licensed under the MIT license. See License.txt in the project root for license information.

using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -12,6 +14,7 @@
using Microsoft.AspNetCore.Razor.LanguageServer.Hosting;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.AspNetCore.Razor.Threading;
using Microsoft.CodeAnalysis.Razor.AutoInsert;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Formatting;
using Microsoft.CodeAnalysis.Razor.Logging;
Expand All @@ -26,21 +29,18 @@ internal class OnAutoInsertEndpoint(
LanguageServerFeatureOptions languageServerFeatureOptions,
IDocumentMappingService documentMappingService,
IClientConnection clientConnection,
IEnumerable<IOnAutoInsertProvider> onAutoInsertProvider,
IAutoInsertService autoInsertService,
RazorLSPOptionsMonitor optionsMonitor,
IAdhocWorkspaceFactory workspaceFactory,
IRazorFormattingService razorFormattingService,
ILoggerFactory loggerFactory)
: AbstractRazorDelegatingEndpoint<VSInternalDocumentOnAutoInsertParams, VSInternalDocumentOnAutoInsertResponseItem?>(languageServerFeatureOptions, documentMappingService, clientConnection, loggerFactory.GetOrCreateLogger<OnAutoInsertEndpoint>()), ICapabilitiesProvider
{
private static readonly HashSet<string> s_htmlAllowedTriggerCharacters = new(StringComparer.Ordinal) { "=", };
private static readonly HashSet<string> s_cSharpAllowedTriggerCharacters = new(StringComparer.Ordinal) { "'", "/", "\n" };

private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions;
private readonly RazorLSPOptionsMonitor _optionsMonitor = optionsMonitor;
private readonly IAdhocWorkspaceFactory _workspaceFactory = workspaceFactory;
private readonly IRazorFormattingService _razorFormattingService = razorFormattingService;
private readonly List<IOnAutoInsertProvider> _onAutoInsertProviders = onAutoInsertProvider.ToList();
private readonly IAutoInsertService _autoInsertService = autoInsertService;

protected override string CustomMessageTarget => CustomMessageNames.RazorOnAutoInsertEndpointName;

Expand All @@ -53,17 +53,17 @@ internal class OnAutoInsertEndpoint(

public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities)
{
var triggerCharacters = _onAutoInsertProviders.Select(provider => provider.TriggerCharacter);
var triggerCharacters = _autoInsertService.TriggerCharacters;

if (_languageServerFeatureOptions.SingleServerSupport)
{
triggerCharacters = triggerCharacters.Concat(s_htmlAllowedTriggerCharacters).Concat(s_cSharpAllowedTriggerCharacters);
triggerCharacters = [
.. triggerCharacters,
.. AutoInsertService.HtmlAllowedAutoInsertTriggerCharacters,
.. AutoInsertService.CSharpAllowedAutoInsertTriggerCharacters];
}

serverCapabilities.OnAutoInsertProvider = new VSInternalDocumentOnAutoInsertOptions()
{
TriggerCharacters = triggerCharacters.Distinct().ToArray()
};
serverCapabilities.EnableOnAutoInsert(triggerCharacters);
alexgav marked this conversation as resolved.
Show resolved Hide resolved
}

protected override async Task<VSInternalDocumentOnAutoInsertResponseItem?> TryHandleAsync(VSInternalDocumentOnAutoInsertParams request, RazorRequestContext requestContext, DocumentPositionInfo positionInfo, CancellationToken cancellationToken)
Expand All @@ -84,36 +84,18 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V

var character = request.Character;

using var applicableProviders = new PooledArrayBuilder<IOnAutoInsertProvider>();
foreach (var provider in _onAutoInsertProviders)
{
if (provider.TriggerCharacter == character)
{
applicableProviders.Add(provider);
}
}

if (applicableProviders.Count == 0)
if (_autoInsertService.TryResolveInsertion(
codeDocument,
request.Position,
character,
_optionsMonitor.CurrentValue.AutoClosingTags,
out var insertTextEdit))
{
// There's currently a bug in the LSP platform where other language clients OnAutoInsert trigger characters influence every language clients trigger characters.
// To combat this we need to preemptively return so we don't try having our providers handle characters that they can't.
return null;
}

var uri = request.TextDocument.Uri;
var position = request.Position;

using var formattingContext = FormattingContext.Create(uri, documentContext.Snapshot, codeDocument, request.Options, _workspaceFactory);
foreach (var provider in applicableProviders)
{
if (provider.TryResolveInsertion(position, formattingContext, out var textEdit, out var format))
return new VSInternalDocumentOnAutoInsertResponseItem()
{
return new VSInternalDocumentOnAutoInsertResponseItem()
{
TextEdit = textEdit,
TextEditFormat = format,
};
}
TextEdit = insertTextEdit.TextEdit,
TextEditFormat = insertTextEdit.TextEditFormat,
};
}

// No provider could handle the text edit.
Expand All @@ -130,7 +112,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V

if (positionInfo.LanguageKind == RazorLanguageKind.Html)
{
if (!s_htmlAllowedTriggerCharacters.Contains(request.Character))
if (!AutoInsertService.HtmlAllowedAutoInsertTriggerCharacters.Contains(request.Character))
{
Logger.LogInformation($"Inapplicable HTML trigger char {request.Character}.");
return SpecializedTasks.Null<IDelegatedParams>();
Expand All @@ -146,7 +128,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V
}
else if (positionInfo.LanguageKind == RazorLanguageKind.CSharp)
{
if (!s_cSharpAllowedTriggerCharacters.Contains(request.Character))
if (!AutoInsertService.CSharpAllowedAutoInsertTriggerCharacters.Contains(request.Character))
{
Logger.LogInformation($"Inapplicable C# trigger char {request.Character}.");
return SpecializedTasks.Null<IDelegatedParams>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.Razor.Formatting;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting;

internal sealed class LspFormattingCodeDocumentProvider : IFormattingCodeDocumentProvider
{
public Task<RazorCodeDocument> GetCodeDocumentAsync(IDocumentSnapshot snapshot)
{
var useDesignTimeGeneratedOutput = snapshot.Project.Configuration.LanguageServerFlags?.ForceRuntimeCodeGeneration ?? false;
return snapshot.GetGeneratedOutputAsync(useDesignTimeGeneratedOutput);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.Razor.SemanticTokens;
using Microsoft.VisualStudio.LanguageServer.Protocol;

namespace Microsoft.AspNetCore.Razor.LanguageServer.Hosting;

internal static class VSInternalServerCapabilitiesExtensions
internal static class LspInitializationHelpers
{
public static void EnableInlayHints(this VSInternalServerCapabilities serverCapabilities)
{
Expand Down Expand Up @@ -65,4 +67,21 @@ public static void EnableMapCodeProvider(this VSInternalServerCapabilities serve
{
serverCapabilities.MapCodeProvider = true;
}

public static void EnableOnAutoInsert(
this VSInternalServerCapabilities serverCapabilities,
IEnumerable<string> triggerCharacters)
{
serverCapabilities.OnAutoInsertProvider = new VSInternalDocumentOnAutoInsertOptions()
.EnableOnAutoInsert(triggerCharacters);
}

public static VSInternalDocumentOnAutoInsertOptions EnableOnAutoInsert(
this VSInternalDocumentOnAutoInsertOptions options,
IEnumerable<string> triggerCharacters)
{
options.TriggerCharacters = triggerCharacters.Distinct().ToArray();

return options;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.InlineCompletion;
internal sealed class InlineCompletionEndpoint(
IDocumentMappingService documentMappingService,
IClientConnection clientConnection,
IFormattingCodeDocumentProvider formattingCodeDocumentProvider,
IAdhocWorkspaceFactory adhocWorkspaceFactory,
ILoggerFactory loggerFactory)
: IRazorRequestHandler<VSInternalInlineCompletionRequest, VSInternalInlineCompletionList?>, ICapabilitiesProvider
Expand All @@ -39,6 +40,7 @@ internal sealed class InlineCompletionEndpoint(

private readonly IDocumentMappingService _documentMappingService = documentMappingService ?? throw new ArgumentNullException(nameof(documentMappingService));
private readonly IClientConnection _clientConnection = clientConnection ?? throw new ArgumentNullException(nameof(clientConnection));
private readonly IFormattingCodeDocumentProvider _formattingCodeDocumentProvider = formattingCodeDocumentProvider;
private readonly IAdhocWorkspaceFactory _adhocWorkspaceFactory = adhocWorkspaceFactory ?? throw new ArgumentNullException(nameof(adhocWorkspaceFactory));
private readonly ILogger _logger = loggerFactory.GetOrCreateLogger<InlineCompletionEndpoint>();

Expand Down Expand Up @@ -123,7 +125,13 @@ public TextDocumentIdentifier GetTextDocumentIdentifier(VSInternalInlineCompleti
continue;
}

using var formattingContext = FormattingContext.Create(request.TextDocument.Uri, documentContext.Snapshot, codeDocument, request.Options, _adhocWorkspaceFactory);
using var formattingContext = FormattingContext.Create(
request.TextDocument.Uri,
documentContext.Snapshot,
codeDocument,
request.Options,
_formattingCodeDocumentProvider,
_adhocWorkspaceFactory);
if (!TryGetSnippetWithAdjustedIndentation(formattingContext, item.Text, hostDocumentIndex, out var newSnippetText))
{
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.AspNetCore.Razor.LanguageServer.EndpointContracts;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Razor.ProjectSystem;
alexgav marked this conversation as resolved.
Show resolved Hide resolved
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.LanguageServer.Protocol;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
using Microsoft.AspNetCore.Razor.LanguageServer.FindAllReferences;
using Microsoft.AspNetCore.Razor.LanguageServer.Folding;
using Microsoft.AspNetCore.Razor.LanguageServer.Formatting;
using Microsoft.AspNetCore.Razor.LanguageServer.Hosting;
using Microsoft.AspNetCore.Razor.LanguageServer.Implementation;
using Microsoft.AspNetCore.Razor.LanguageServer.InlayHints;
Expand All @@ -24,7 +25,9 @@
using Microsoft.AspNetCore.Razor.LanguageServer.SignatureHelp;
using Microsoft.AspNetCore.Razor.LanguageServer.WrapWithTag;
using Microsoft.AspNetCore.Razor.Telemetry;
using Microsoft.CodeAnalysis.Razor.AutoInsert;
using Microsoft.CodeAnalysis.Razor.FoldingRanges;
using Microsoft.CodeAnalysis.Razor.Formatting;
using Microsoft.CodeAnalysis.Razor.GoToDefinition;
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Razor.Protocol.DocumentSymbols;
Expand Down Expand Up @@ -119,6 +122,8 @@ protected override ILspServices ConstructLspServices()
services.AddSingleton<IAdhocWorkspaceFactory, AdhocWorkspaceFactory>();
services.AddSingleton<IWorkspaceProvider, LspWorkspaceProvider>();

services.AddSingleton<IFormattingCodeDocumentProvider, LspFormattingCodeDocumentProvider>();

var featureOptions = _featureOptions ?? new DefaultLanguageServerFeatureOptions();
services.AddSingleton(featureOptions);

Expand All @@ -136,12 +141,14 @@ protected override ILspServices ConstructLspServices()
services.AddHoverServices();
services.AddTextDocumentServices(featureOptions);

// Auto insert
services.AddSingleton<IOnAutoInsertProvider, CloseTextTagOnAutoInsertProvider>();
services.AddSingleton<IOnAutoInsertProvider, AutoClosingTagOnAutoInsertProvider>();

if (!featureOptions.UseRazorCohostServer)
{
// Auto insert
services.AddSingleton<IOnAutoInsertProvider, CloseTextTagOnAutoInsertProvider>();
services.AddSingleton<IOnAutoInsertProvider, AutoClosingTagOnAutoInsertProvider>();

services.AddSingleton<IAutoInsertService, AutoInsertService>();

// Folding Range Providers
services.AddSingleton<IRazorFoldingRangeProvider, RazorCodeBlockFoldingProvider>();
services.AddSingleton<IRazorFoldingRangeProvider, RazorCSharpStatementFoldingProvider>();
Expand Down Expand Up @@ -178,7 +185,6 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption
services.AddTransient<IOnInitialized>(sp => sp.GetRequiredService<RazorConfigurationEndpoint>());

services.AddHandlerWithCapabilities<ImplementationEndpoint>();
services.AddHandlerWithCapabilities<OnAutoInsertEndpoint>();

if (!featureOptions.UseRazorCohostServer)
{
Expand All @@ -188,6 +194,7 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption
services.AddSingleton<IRenameService, RenameService>();
services.AddHandlerWithCapabilities<RenameEndpoint>();

services.AddHandlerWithCapabilities<OnAutoInsertEndpoint>();
services.AddHandlerWithCapabilities<DocumentHighlightEndpoint>();
services.AddHandlerWithCapabilities<SignatureHelpEndpoint>();
services.AddHandlerWithCapabilities<LinkedEditingRangeEndpoint>();
Expand Down
Loading