diff --git a/src/Razor/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Formatting/DocumentFormattingBenchmark.cs b/src/Razor/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Formatting/DocumentFormattingBenchmark.cs index 137a326bd73c0..8a78dd472923b 100644 --- a/src/Razor/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Formatting/DocumentFormattingBenchmark.cs +++ b/src/Razor/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/Formatting/DocumentFormattingBenchmark.cs @@ -84,7 +84,7 @@ public void Setup() var documentMappingService = new DocumentMappingService(filePathService, snapshotManager, EmptyLoggerFactory.Instance); var razorEditService = new RazorEditService(documentMappingService, clientSettingsManager, filePathService, snapshotManager, NoOpTelemetryReporter.Instance); - _formattingService = new RemoteRazorFormattingService( + _formattingService = new RazorFormattingService( documentMappingService, razorEditService, hostServicesProvider, diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs index dbfb7d7b2b2db..85bf85a96f075 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs @@ -62,7 +62,7 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie protected override Task HandleRequestAsync(DocumentFormattingParams request, TextDocument razorDocument, CancellationToken cancellationToken) { - var csharpSyntaxFormattingOptions = CSharpFormatter.GetCSharpSyntaxFormattingOptions(razorDocument.Project.Solution.Services, csharpSyntaxFormattingOptions: null); + var csharpSyntaxFormattingOptions = CSharpFormattingOptionsHelper.GetCSharpSyntaxFormattingOptions(razorDocument.Project.Solution.Services, csharpSyntaxFormattingOptions: null); return HandleRequestAsync(request, razorDocument, csharpSyntaxFormattingOptions, cancellationToken); } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostOnTypeFormattingEndpoint.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostOnTypeFormattingEndpoint.cs index f77fde5d2494e..a678f2443818c 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostOnTypeFormattingEndpoint.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostOnTypeFormattingEndpoint.cs @@ -15,6 +15,8 @@ using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.Workspaces.Settings; using Microsoft.CodeAnalysis.Text; +using System.Collections.Frozen; +using System; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -33,6 +35,10 @@ internal sealed class CohostOnTypeFormattingEndpoint( ILoggerFactory loggerFactory) : AbstractCohostDocumentEndpoint(incompatibleProjectService), IDynamicRegistrationProvider { + internal const string FirstTriggerCharacter = "}"; + internal static readonly string[] MoreTriggerCharacters = [";", "\n", "{"]; + internal static readonly FrozenSet AllTriggerCharacterSet = FrozenSet.ToFrozenSet([FirstTriggerCharacter, .. MoreTriggerCharacters], StringComparer.Ordinal); + private readonly IRemoteServiceInvoker _remoteServiceInvoker = remoteServiceInvoker; private readonly IHtmlRequestInvoker _requestInvoker = requestInvoker; private readonly IClientSettingsManager _clientSettingsManager = clientSettingsManager; @@ -51,8 +57,8 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie Method = Methods.TextDocumentOnTypeFormattingName, RegisterOptions = new DocumentOnTypeFormattingRegistrationOptions() { - FirstTriggerCharacter = RazorFormattingService.FirstTriggerCharacter, - MoreTriggerCharacter = RazorFormattingService.MoreTriggerCharacters + FirstTriggerCharacter = FirstTriggerCharacter, + MoreTriggerCharacter = MoreTriggerCharacters } }]; } @@ -72,7 +78,7 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie return null; } - if (!RazorFormattingService.AllTriggerCharacterSet.Contains(request.Character)) + if (!AllTriggerCharacterSet.Contains(request.Character)) { _logger.LogWarning($"Unexpected trigger character '{request.Character}'."); return null; @@ -112,7 +118,7 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie htmlChanges = htmlEdits.SelectAsArray(sourceText.GetTextChange); } - var csharpSyntaxFormattingOptions = CSharpFormatter.GetCSharpSyntaxFormattingOptions(razorDocument.Project.Solution.Services, csharpSyntaxFormattingOptions: null); + var csharpSyntaxFormattingOptions = CSharpFormattingOptionsHelper.GetCSharpSyntaxFormattingOptions(razorDocument.Project.Solution.Services, csharpSyntaxFormattingOptions: null); var options = RazorFormattingOptions.From(request.Options, clientSettings.AdvancedSettings.CodeBlockBraceOnNextLine, clientSettings.AdvancedSettings.AttributeIndentStyle, csharpSyntaxFormattingOptions); _logger.LogDebug($"Calling OOP with the {htmlChanges.Length} html edits, so it can fill in the rest"); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostRangeFormattingEndpoint.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostRangeFormattingEndpoint.cs index fe704f082ccf0..42621fbc8fc44 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostRangeFormattingEndpoint.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostRangeFormattingEndpoint.cs @@ -83,7 +83,7 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie var sourceText = await razorDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); var htmlChanges = htmlEdits.SelectAsArray(sourceText.GetTextChange); - var csharpSyntaxFormattingOptions = CSharpFormatter.GetCSharpSyntaxFormattingOptions(razorDocument.Project.Solution.Services, csharpSyntaxFormattingOptions: null); + var csharpSyntaxFormattingOptions = CSharpFormattingOptionsHelper.GetCSharpSyntaxFormattingOptions(razorDocument.Project.Solution.Services, csharpSyntaxFormattingOptions: null); var options = RazorFormattingOptions.From( request.Options, _clientSettingsManager.GetClientSettings().AdvancedSettings.CodeBlockBraceOnNextLine, diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/InlayHints/CohostInlayHintResolveEndpoint.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/InlayHints/CohostInlayHintResolveEndpoint.cs index 28ddd56020245..48b49695ba252 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/InlayHints/CohostInlayHintResolveEndpoint.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/InlayHints/CohostInlayHintResolveEndpoint.cs @@ -59,7 +59,7 @@ internal class CohostInlayHintResolveEndpoint( var hint = await _remoteServiceInvoker.TryInvokeAsync( razorDocument.Project.Solution, - (service, solutionInfo, cancellationToken) => service.ResolveHintAsync(solutionInfo, razorDocument.Id, request, cancellationToken), + (service, solutionInfo, cancellationToken) => service.ResolveHintAsync(solutionInfo, razorDocument.Id, request, razorData.InDeclDocument, cancellationToken), cancellationToken).ConfigureAwait(false); if (hint is null) diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs index f48ba6054bb87..1a124dbc0fc00 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs @@ -447,6 +447,7 @@ static string GetArgumentTypesLogString(VSInternalCompletionItem resolvedComplet var formattedTextChange = await formattingService.TryGetCSharpSnippetFormattingEditAsync( documentContext, changes, + declarationDocument: false, // PROTOTYPE(sonic): Pass in the right value to this options, cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Extensions/SourceTextExtensions.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Extensions/SourceTextExtensions.cs index f8e9ae9cd3a83..309f3d5772f3f 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Extensions/SourceTextExtensions.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Extensions/SourceTextExtensions.cs @@ -370,4 +370,33 @@ public static ImmutableArray GetTextChangesArray(this SourceText new return list.ToImmutableArray(); } + + /// + /// Sometimes the Html language server will send back an edit that contains a tilde, because the generated + /// document we send them has lots of tildes. In those cases, we need to do some extra work to compute the + /// minimal text edits + /// + public static TextEdit[] FixHtmlTextEdits(this SourceText htmlSourceText, TextEdit[] edits) + { + // Avoid computing a minimal diff if we don't need to + if (!edits.Any(static e => e.NewText.Contains('~'))) + return edits; + + var changes = edits.SelectAsArray(htmlSourceText.GetTextChange); + + var fixedChanges = htmlSourceText.MinimizeTextChanges(changes); + return fixedChanges.SelectAsPlainArray(htmlSourceText.GetTextEdit); + } + + public static SumType[] FixHtmlTextEdits(this SourceText htmlSourceText, SumType[] edits) + { + // Avoid computing a minimal diff if we don't need to + if (!edits.Any(static e => ((TextEdit)e).NewText.Contains('~'))) + return edits; + + var changes = edits.SelectAsArray(e => htmlSourceText.GetTextChange((TextEdit)e)); + + var fixedChanges = htmlSourceText.MinimizeTextChanges(changes); + return fixedChanges.SelectAsPlainArray>(c => htmlSourceText.GetTextEdit(c)); + } } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormattingOptionsHelper.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormattingOptionsHelper.cs new file mode 100644 index 0000000000000..ab41b3b2f9061 --- /dev/null +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormattingOptionsHelper.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Options; + +namespace Microsoft.CodeAnalysis.Razor.Formatting; + +internal static class CSharpFormattingOptionsHelper +{ + internal static CSharpSyntaxFormattingOptions GetCSharpSyntaxFormattingOptions( + SolutionServices services, + CSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptions) + { + csharpSyntaxFormattingOptions + ??= (CSharpSyntaxFormattingOptions)(services.GetService()?.GetSyntaxFormattingOptions(services.GetLanguageServices(LanguageNames.CSharp)) + ?? CSharpSyntaxFormattingOptions.Default); + + return csharpSyntaxFormattingOptions; + } + + internal static CSharpSyntaxFormattingOptions GetResolvedCSharpSyntaxFormattingOptions( + SolutionServices services, + RazorFormattingOptions options, + CSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptions = null) + { + csharpSyntaxFormattingOptions = GetCSharpSyntaxFormattingOptions( + services, + csharpSyntaxFormattingOptions ?? options.CSharpSyntaxFormattingOptions); + + return csharpSyntaxFormattingOptions with + { + LineFormatting = csharpSyntaxFormattingOptions.LineFormatting with + { + UseTabs = !options.InsertSpaces, + TabSize = options.TabSize, + IndentationSize = options.TabSize, + NewLine = CSharpSyntaxFormattingOptions.Default.NewLine + } + }; + } +} diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IRazorFormattingService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IRazorFormattingService.cs index 8a210bc63b3a8..20433a681b8b7 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IRazorFormattingService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IRazorFormattingService.cs @@ -33,23 +33,27 @@ Task> GetCSharpOnTypeFormattingChangesAsync( RazorFormattingOptions options, int hostDocumentIndex, char triggerCharacter, + bool declarationDocument, CancellationToken cancellationToken); Task TryGetSingleCSharpEditAsync( DocumentContext documentContext, TextChange csharpEdit, + bool declarationDocument, RazorFormattingOptions options, CancellationToken cancellationToken); Task TryGetCSharpCodeActionEditAsync( DocumentContext documentContext, ImmutableArray csharpEdits, + bool declarationDocument, RazorFormattingOptions options, CancellationToken cancellationToken); Task TryGetCSharpSnippetFormattingEditAsync( DocumentContext documentContext, ImmutableArray csharpEdits, + bool declarationDocument, RazorFormattingOptions options, CancellationToken cancellationToken); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/AbstractDefinitionService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/AbstractDefinitionService.cs deleted file mode 100644 index 9b149909b224a..0000000000000 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/AbstractDefinitionService.cs +++ /dev/null @@ -1,194 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.IO; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis.Razor.DocumentMapping; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; -using Microsoft.CodeAnalysis.Razor.Workspaces; -using Microsoft.CodeAnalysis.Text; -using CSharpSyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind; - -namespace Microsoft.CodeAnalysis.Razor.GoToDefinition; - -internal abstract class AbstractDefinitionService( - IRazorComponentSearchEngine componentSearchEngine, - ITagHelperSearchEngine? tagHelperSearchEngine, - IDocumentMappingService documentMappingService, - ILogger logger) : IDefinitionService -{ - private readonly IRazorComponentSearchEngine _componentSearchEngine = componentSearchEngine; - private readonly ITagHelperSearchEngine? _tagHelperSearchEngine = tagHelperSearchEngine; - private readonly IDocumentMappingService _documentMappingService = documentMappingService; - private readonly ILogger _logger = logger; - - public async Task GetDefinitionAsync( - IDocumentSnapshot documentSnapshot, - DocumentPositionInfo positionInfo, - ISolutionQueryOperations solutionQueryOperations, - bool includeMvcTagHelpers, - CancellationToken cancellationToken) - { - if (!includeMvcTagHelpers && !documentSnapshot.FileKind.IsComponent()) - { - _logger.LogInformation($"'{documentSnapshot.FileKind}' is not a component type."); - return null; - } - - var codeDocument = await documentSnapshot.GetGeneratedOutputAsync(cancellationToken).ConfigureAwait(false); - - if (!RazorComponentDefinitionHelpers.TryGetBoundTagHelpers(codeDocument, positionInfo.HostDocumentIndex, _logger, out var boundTagHelperResults)) - { - _logger.LogInformation($"Could not retrieve bound tag helper information."); - return null; - } - - if (includeMvcTagHelpers) - { - Debug.Assert(_tagHelperSearchEngine is not null, "If includeMvcTagHelpers is true, _tagHelperSearchEngine must not be null."); - - var tagHelperLocations = await _tagHelperSearchEngine.TryLocateTagHelperDefinitionsAsync(boundTagHelperResults, documentSnapshot, solutionQueryOperations, cancellationToken).ConfigureAwait(false); - if (tagHelperLocations is { Length: > 0 }) - { - return tagHelperLocations; - } - } - - // For Razor components, there can only ever be one tag helper result - var (boundTagHelper, boundAttribute) = boundTagHelperResults[0]; - - var componentDocument = await _componentSearchEngine - .TryLocateComponentAsync(boundTagHelper, solutionQueryOperations, cancellationToken) - .ConfigureAwait(false); - - if (componentDocument is null) - { - _logger.LogInformation($"Could not locate component document."); - return null; - } - - var componentFilePath = componentDocument.FilePath; - - _logger.LogInformation($"Definition found at file path: {componentFilePath}"); - - var range = await GetNavigateRangeAsync(componentDocument, boundAttribute, cancellationToken).ConfigureAwait(false); - - return [LspFactory.CreateLocation(componentFilePath, range)]; - } - - private async Task GetNavigateRangeAsync(IDocumentSnapshot documentSnapshot, BoundAttributeDescriptor? attributeDescriptor, CancellationToken cancellationToken) - { - if (attributeDescriptor is not null) - { - _logger.LogInformation($"Attempting to get definition from an attribute directly."); - - var range = await RazorComponentDefinitionHelpers - .TryGetPropertyRangeAsync(documentSnapshot, attributeDescriptor.PropertyName, _documentMappingService, _logger, cancellationToken) - .ConfigureAwait(false); - - if (range is not null) - { - return range; - } - } - - // When navigating from a start or end tag, we just take the user to the top of the file. - // If we were trying to navigate to a property, and we couldn't find it, we can at least take - // them to the file for the component. If the property was defined in a partial class they can - // at least then press F7 to go there. - return LspFactory.DefaultRange; - } - - public async Task TryGetDefinitionFromStringLiteralAsync( - IDocumentSnapshot documentSnapshot, - Position position, - CancellationToken cancellationToken) - { - _logger.LogDebug($"Attempting to get definition from string literal at position {position}."); - - // Get the C# syntax tree to analyze the string literal - var syntaxTree = await documentSnapshot.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); - var sourceText = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); - - // Convert position to absolute index - var absoluteIndex = sourceText.GetRequiredAbsoluteIndex(position); - - // Find the token at the current position - var token = root.FindToken(absoluteIndex); - - // Check if we're in a string literal - if (token.IsKind(CSharpSyntaxKind.StringLiteralToken)) - { - var literalText = token.ValueText; - _logger.LogDebug($"Found string literal: {literalText}"); - - // Try to resolve the file path - if (TryResolveFilePath(documentSnapshot, literalText, out var resolvedPath)) - { - _logger.LogDebug($"Resolved file path: {resolvedPath}"); - return [LspFactory.CreateLocation(resolvedPath, LspFactory.DefaultRange)]; - } - } - - return null; - } - - private bool TryResolveFilePath(IDocumentSnapshot documentSnapshot, string filePath, out string resolvedPath) - { - resolvedPath = string.Empty; - - if (string.IsNullOrWhiteSpace(filePath)) - { - return false; - } - - // Only process if it looks like a Razor file path - if (!filePath.IsRazorFilePath()) - { - return false; - } - - var project = documentSnapshot.Project; - - // Handle tilde paths (~/ or ~\) - these are relative to the project root - if (filePath is ['~', '/' or '\\', ..]) - { - var projectDirectory = Path.GetDirectoryName(project.FilePath); - if (projectDirectory is null) - { - return false; - } - - // Remove the tilde and normalize path separators - var relativePath = filePath.Substring(2).Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); - var candidatePath = Path.GetFullPath(Path.Combine(projectDirectory, relativePath)); - - if (project.ContainsDocument(candidatePath)) - { - resolvedPath = candidatePath; - return true; - } - } - - // Handle relative paths - relative to the current document - var currentDocumentDirectory = Path.GetDirectoryName(documentSnapshot.FilePath); - if (currentDocumentDirectory is not null) - { - var normalizedPath = filePath.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); - var candidatePath = Path.GetFullPath(Path.Combine(currentDocumentDirectory, normalizedPath)); - - if (project.ContainsDocument(candidatePath)) - { - resolvedPath = candidatePath; - return true; - } - } - - return false; - } -} diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ITagHelperSearchEngine.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ITagHelperSearchEngine.cs index 97a28c65c3631..3a658dc978b46 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ITagHelperSearchEngine.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ITagHelperSearchEngine.cs @@ -4,7 +4,7 @@ using System.Collections.Immutable; using System.Threading; using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Razor.GoToDefinition; +using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.Razor.ProjectSystem; namespace Microsoft.CodeAnalysis.Razor.Workspaces; @@ -13,3 +13,5 @@ internal interface ITagHelperSearchEngine { Task TryLocateTagHelperDefinitionsAsync(ImmutableArray boundTagHelpers, IDocumentSnapshot documentSnapshot, ISolutionQueryOperations solutionQueryOperations, CancellationToken cancellationToken); } + +internal sealed record BoundTagHelperResult(TagHelperDescriptor ElementDescriptor, BoundAttributeDescriptor? AttributeDescriptor); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs index d9ca99c85c7fb..8593c32cbeec6 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs @@ -30,9 +30,6 @@ internal interface IDocumentSnapshot /// /// Gets the Roslyn syntax tree for the generated C# for this Razor document /// - /// - /// ⚠️ Should be used sparingly in language server scenarios. - /// ValueTask GetCSharpSyntaxTreeAsync(bool declarationDocument, CancellationToken cancellationToken); bool TryGetText([NotNullWhen(true)] out SourceText? result); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/InlayHints/InlayHintDataWrapper.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/InlayHints/InlayHintDataWrapper.cs index 98351bd8a42f9..41f2f57d91fbf 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/InlayHints/InlayHintDataWrapper.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/InlayHints/InlayHintDataWrapper.cs @@ -3,4 +3,4 @@ namespace Microsoft.CodeAnalysis.Razor.Protocol.InlayHints; -internal record class InlayHintDataWrapper(TextDocumentIdentifier TextDocument, object? OriginalData, Position OriginalPosition); +internal record class InlayHintDataWrapper(TextDocumentIdentifier TextDocument, object? OriginalData, Position OriginalPosition, bool InDeclDocument); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteInlayHintService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteInlayHintService.cs index 52135f95cfc1f..fe30d136c22d8 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteInlayHintService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteInlayHintService.cs @@ -10,5 +10,5 @@ internal interface IRemoteInlayHintService : IRemoteJsonService { ValueTask GetInlayHintsAsync(JsonSerializableRazorSolutionWrapper solutionInfo, JsonSerializableDocumentId razorDocumentId, InlayHintParams inlayHintParams, bool displayAllOverride, CancellationToken cancellationToken); - ValueTask ResolveHintAsync(JsonSerializableRazorSolutionWrapper solutionInfo, JsonSerializableDocumentId razorDocumentId, InlayHint inlayHint, CancellationToken cancellationToken); + ValueTask ResolveHintAsync(JsonSerializableRazorSolutionWrapper solutionInfo, JsonSerializableDocumentId razorDocumentId, InlayHint inlayHint, bool inDeclDocument, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/SR.resx b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/SR.resx index 638a1fe1f226b..e2e91b97e33c3 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/SR.resx +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/SR.resx @@ -136,24 +136,6 @@ Line '{0}' outside of the {1} range of '{2}' was queried. The document may not be up to date. - - A format operation is being abandoned because it would add or delete non-whitespace content. - - - Edit at {0} adds the non-whitespace content '{1}'. - - - Edit at {0} deletes the non-whitespace content '{1}'. - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - - - Diagnostics before: - - - Diagnostics after: - Razor language services not configured properly, missing language service '{0}'. @@ -197,9 +179,6 @@ {0} Keyword - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - ✅ Widely available across major browsers{0} {0} is " (Baseline since YYYY)" or empty diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.cs.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.cs.xlf index feaeee861fc76..a414ab8ea2bb1 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.cs.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.cs.xlf @@ -32,16 +32,6 @@ Atributy direktivy Blazor - - Diagnostics after: - Diagnostika po: - - - - Diagnostics before: - Diagnostika před: - - directive direktiva @@ -54,31 +44,6 @@ [Tab] pro navigaci mezi elementy, [Enter] pro dokončení - - Edit at {0} adds the non-whitespace content '{1}'. - Úprava na {0} přidá neprázdný obsah {1}. - - - - Edit at {0} deletes the non-whitespace content '{1}'. - Úprava na {0} odstraní neprázdný obsah {1}. - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Operace formátování je ukončována, protože by zavedla nebo odebrala jednu z více diagnostik. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Operace formátování je ukončována, protože by přidala nebo odstranila neprázdný obsah. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Chyba formátování Práce se přerušuje, aby nedošlo k poškození souboru, prosím nahlaste tento problém. Více informací zde: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Editor Razor využívá Generátor zdroje Razor, který vyžaduje, aby soubory *.razor a *.cshtml v projektu byly AdditionalFiles. {0} nejspíš pochází z: {1} a neobsahuje žádné dokumenty Razor, které jsou AdditionalFiles, takže možnosti úprav budou omezené. Používá sadu Razor SDK? Pro tento projekt se nebudou protokolovat žádné další zprávy. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.de.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.de.xlf index 47150b14b26ed..9204ba99a7c3c 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.de.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.de.xlf @@ -32,16 +32,6 @@ Attribute für Blazor-Direktiven - - Diagnostics after: - Diagnose nach: - - - - Diagnostics before: - Diagnose vor: - - directive Direktive @@ -54,31 +44,6 @@ [Registerkarte] ein, um zwischen Elementen zu navigieren, [EINGABETASTE], um den Vorgang abzuschließen - - Edit at {0} adds the non-whitespace content '{1}'. - Das Bearbeiten bei {0} fügt den Nicht-Leerraum-Inhalt "{1}" hinzu. - - - - Edit at {0} deletes the non-whitespace content '{1}'. - Das Bearbeiten bei {0} löscht den Nicht-Leerraum-Inhalt "{1}". - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Ein Formatierungsvorgang wird abgebrochen, weil er eine oder mehrere Diagnosen einführen oder entfernen würde. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Ein Formatierungsvorgang wird abgebrochen, da er Nicht-Leerraum-Inhalte hinzufügen oder löschen würde. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Formatierungsfehler Die weitere Bearbeitung wird abgebrochen, um die Datei nicht zu beschädigen. Melden Sie dieses Problem. Weitere Informationen unter https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Der Razor-Editor verwendet den Razor-Quellgenerator, der *.razor- und *.cshtml-Dateien als AdditionalFiles im Projekt erfordert. {0} scheint von „{1}“ zu stammen, das keine Razor-Dokumente enthält, die "AdditionalFiles" sind, sodass die Bearbeitungserfahrung eingeschränkt ist. Wird das Razor SDK verwendet? Für dieses Projekt werden keine weiteren Nachrichten protokolliert. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.es.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.es.xlf index bea3924ab7bee..7ea6af6811b42 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.es.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.es.xlf @@ -32,16 +32,6 @@ Atributos de directiva de Blazor - - Diagnostics after: - Diagnósticos después de: - - - - Diagnostics before: - Diagnósticos antes de: - - directive directiva @@ -54,31 +44,6 @@ [Tab] para navegar entre elementos, [Entrar] para completar - - Edit at {0} adds the non-whitespace content '{1}'. - Editar en {0}agregar el contenido que no es un espacio en blanco "{1}" . - - - - Edit at {0} deletes the non-whitespace content '{1}'. - Editar en {0} eliminar el contenido que no es un espacio en blanco "{1}" . - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Se está abandonando una operación de formato porque introduciría o quitaría uno de más diagnósticos. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Se está abandonando una operación de formato porque agregaría o eliminaría contenido que no es un espacio en blanco. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Error de formato. Si abandona el trabajo adicional para no dañar el archivo, notifique este problema. Consulte: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. El editor de Razor usa Razor Source Generator, que requiere que los archivos *.razor y *.cshtml sean AdditionalFiles en el proyecto. {0} parece venir de "{1}", que no tiene documentos de Razor que sean AdditionalFiles, por lo que la experiencia de edición será limitada. ¿Usa el SDK de Razor? No se registrarán más mensajes para este proyecto. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.fr.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.fr.xlf index 81eb2a1ed945b..4c9437eb0e78b 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.fr.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.fr.xlf @@ -32,16 +32,6 @@ Attributs de directive Blazor - - Diagnostics after: - Diagnostics après : - - - - Diagnostics before: - Diagnostics avant : - - directive directif @@ -54,31 +44,6 @@ [Tab] pour naviguer entre les éléments, [Entrée] pour terminer - - Edit at {0} adds the non-whitespace content '{1}'. - Modifier à {0} ajoute le contenu autre qu’un espace « {1} ». - - - - Edit at {0} deletes the non-whitespace content '{1}'. - Modifier à {0} supprime le contenu autre qu’un espace « {1} ». - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Une opération de formatage est en cours d’abandon, car elle introduit ou supprime un ou plusieurs diagnostics. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Une opération de formatage est en cours d’abandon, car elle ajouterait ou supprimerait du contenu qui n’est pas un espace blanc. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Erreur de mise en forme. Abandon du travail pour éviter de corrompre le fichier, veuillez signaler ce problème. Voir : https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. L’éditeur Razor utilise le générateur de source Razor, qui requiert que les fichiers *.razor et *.cshtml soient AdditionalFiles dans le projet. {0} semble provenir de '{1}', qui ne contient aucun document Razor qui sont des AdditionalFiles. L’expérience d’édition sera donc limitée. Utilise-t-il le kit de développement logiciel (SDK) Razor ? Aucun autre message ne sera enregistré pour ce projet. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.it.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.it.xlf index 538d9cc2b63ed..bb7e88e16e0ae 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.it.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.it.xlf @@ -32,16 +32,6 @@ Attributo per la direttiva Blazor - - Diagnostics after: - Diagnostica dopo: - - - - Diagnostics before: - Diagnostica prima di: - - directive direttiva @@ -54,31 +44,6 @@ [TAB] per spostarsi tra gli elementi, [INVIO] per completare - - Edit at {0} adds the non-whitespace content '{1}'. - La modifica in {0} aggiunge contenuti diversi da spazi vuoti '{1}'. - - - - Edit at {0} deletes the non-whitespace content '{1}'. - La modifica in {0} elimina contenuti diversi da spazi vuoti '{1}'. - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - È in corso l'abbandono di un'operazione di formato perché comporterebbe l'introduzione o la rimozione di una o più operazioni di diagnostica. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - È in corso l'abbandono di un'operazione di formattazione perché aggiungerebbe o eliminerebbe contenuto diverso da spazi vuoti. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Errore di formattazione. Per evitare di danneggiare il file, interrompere l'operazione e segnalare il problema. Vedere: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. L'editor Razor usa il generatore di origine Razor, che richiede che i file *.razor e *.cshtml siano AdditionalFiles nel progetto. {0} sembra provenire da '{1}', che non contiene documenti Razor classificati come AdditionalFiles, quindi l'esperienza di modifica sarà limitata. Si sta utilizzando Razor SDK? Non verranno registrati altri messaggi per questo progetto. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ja.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ja.xlf index d7f0bc5dec09e..0804a9b2f62fd 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ja.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ja.xlf @@ -32,16 +32,6 @@ Blazor ディレクティブ属性 - - Diagnostics after: - 次の時間が経過した後の診断: - - - - Diagnostics before: - 次の時間以前の診断: - - directive ディレクティブ @@ -54,31 +44,6 @@ [Tab] を挿入して要素間を移動し、[Enter] を押して完了します - - Edit at {0} adds the non-whitespace content '{1}'. - {0} で編集すると空白以外のスペース '{1}' が追加されます。 - - - - Edit at {0} deletes the non-whitespace content '{1}'. - {0} で削除すると空白以外のスペース '{1}' が追加されます。 - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - 書式設定操作は、さらに診断の 1 つを導入または削除するため、破棄されています。 - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - 書式設定操作は、空白以外のコンテンツを追加または削除するため、破棄されています。 - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - 書式設定エラーです。ファイルを破損しないようにこれ以上の作業を中止してください。この問題を報告してください。参照: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Razor エディターは Razor ソース ジェネレーターを利用します。これには、*.razor および *.cshtml ファイルがプロジェクトの AddedFiles である必要があります。{0} は、'{1}' から取得されたようですが、これには AddedFiles である Razor ドキュメントがないため、編集エクスペリエンスが制限されます。Razor SDK を使用していますか?このプロジェクトのメッセージはこれ以上ログに記録されません。 diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ko.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ko.xlf index 1030ffd5f626b..5b34a4d8d87b3 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ko.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ko.xlf @@ -32,16 +32,6 @@ Blazor 지시문 특성 - - Diagnostics after: - 다음 이후 진단: - - - - Diagnostics before: - 다음 이전 진단: - - directive 지시문 @@ -54,31 +44,6 @@ 요소 간에 탐색하려면 [Tab], 완료하려면 [Enter] - - Edit at {0} adds the non-whitespace content '{1}'. - {0}에서 편집은 공백이 아닌 콘텐츠 '{1}'을(를) 추가합니다. - - - - Edit at {0} deletes the non-whitespace content '{1}'. - {0}에서 편집은 공백이 아닌 콘텐츠 '{1}'을(를) 삭제합니다. - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - 서식 작업이 중단되는 이유는 진단 중 하나를 더 도입하거나 제거할 수 있기 때문입니다. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - 공백이 아닌 콘텐츠를 추가하거나 삭제하기 때문에 형식 작업이 중단됩니다. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - 서식 오류입니다. 파일이 손상되지 않도록 추가 작업을 중단합니다. 이 문제를 보고하세요. 참조: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Razor 편집기는 프로젝트의 AdditionalFiles이 *.razor 및 *.cshtml 파일이어야 하는 Razor 원본 생성기를 사용합니다. {0}은(는) AdditionalFiles인 Razor 문서가 포함되지 않은 '{1}'에서 가져왔으므로 편집 환경이 제한됩니다. Razor SDK를 사용하고 계십니까? 이 프로젝트에 대해 더 이상 메시지가 기록되지 않습니다. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pl.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pl.xlf index f5a8f14ff79e8..7d46d4f050d9a 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pl.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pl.xlf @@ -32,16 +32,6 @@ Atrybut dyrektywy Blazor - - Diagnostics after: - Diagnostyka po: - - - - Diagnostics before: - Diagnostyka przed: - - directive dyrektywa @@ -54,31 +44,6 @@ klawisz [Tab], aby przechodzić pomiędzy elementami, klawisz [Enter], aby zakończyć - - Edit at {0} adds the non-whitespace content '{1}'. - Edycja na stronie {0} dodaje zawartość bez białych znaków „{1}”. - - - - Edit at {0} deletes the non-whitespace content '{1}'. - Edycja na stronie {0} usuwa zawartość bez białych znaków „{1}”. - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Operacja formatowania jest porzucana, ponieważ spowodowałaby wprowadzenie lub usunięcie jednej z większej liczby diagnostyki. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Operacja formatowania jest porzucana, ponieważ doda lub usunie zawartość bez białych znaków. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Błąd formatowania. Porzucanie dalszej pracy, aby nie uszkodzić pliku, zgłoś ten problem. Zobacz: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Edytor Razor korzysta z generatora źródła Razor, który wymaga, aby pliki *.razor i *.cshtml były plikami AdditionalFiles w projekcie. Wygląda na to, że {0} pochodzi z folderu „{1}”, który nie zawiera dokumentów usługi Razor będących plikami AdditionalFiles, więc środowisko edycji będzie ograniczone. Czy używa zestawu Razor SDK? Dla tego projektu nie będą rejestrowane żadne inne wiadomości. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pt-BR.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pt-BR.xlf index 09269d15cf720..298addf270b3b 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pt-BR.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pt-BR.xlf @@ -32,16 +32,6 @@ Atributos da diretiva Blazor - - Diagnostics after: - Diagnóstico após: - - - - Diagnostics before: - Diagnóstico antes: - - directive diretiva @@ -54,31 +44,6 @@ [Tab] para navegar entre elementos, [Enter] para concluir - - Edit at {0} adds the non-whitespace content '{1}'. - Editar em {0} adiciona o conteúdo que não é espaço em branco ''{1}''. - - - - Edit at {0} deletes the non-whitespace content '{1}'. - Editar em {0} exclui o conteúdo que não é espaço em branco ''{1}''. - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Uma operação de formato está sendo abandonada porque introduziria ou removeria um ou mais diagnósticos. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Uma operação de formato está sendo abandonada porque adicionaria ou excluiria conteúdo que não é espaço em branco. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Erro de formatação. Interrompendo o trabalho para não corromper o arquivo. Reporte esse problema. Consulte: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. O editor Razor utiliza o Razor Source Generator, que exige que arquivos \*.razor e \*.cshtml sejam especificados como AdditionalFiles no projeto. {0} parece vir de '{1}', que não contém documentos Razor como AdditionalFiles, portanto, a experiência de edição será limitada. Está usando o SDK do Razor? Nenhuma outra mensagem será registrada para este projeto. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ru.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ru.xlf index d2a124fe1b5eb..52f862a5cfcc4 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ru.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ru.xlf @@ -32,16 +32,6 @@ Атрибуты директивы Blazor - - Diagnostics after: - Диагностика после: - - - - Diagnostics before: - Диагностика до: - - directive директива @@ -54,31 +44,6 @@ [TAB] для перемещения между элементами, нажмите [ВВОД] для завершения - - Edit at {0} adds the non-whitespace content '{1}'. - Редактирование {0} добавляет содержимое, не являющееся пробелами "{1}". - - - - Edit at {0} deletes the non-whitespace content '{1}'. - Редактирование {0} удаляет содержимое, не являющееся пробелами "{1}". - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Операция форматирования отменяется, поскольку она вводит или удаляет одну или несколько диагностик. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Операция форматирования отменяется, поскольку она может добавить или удалить содержимое, отличное от пробелов. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Ошибка форматирования. Дальнейшая работа прекращается, чтобы не повредить файл. Сообщите об этой проблеме. См.: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Редактор Razor использует генератор источника Razor, который требует, чтобы файлы *.razor и *.cshtml были файлами AdditionalFile в проекте. {0} поступает из "{1}", где нет документов Razor, которые являются файлами AdditionalFile, поэтому возможности редактирования будут ограничены. Используется ли пакет SDK Razor? Для этого проекта больше не будут регистрироваться сообщения в журнале. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.tr.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.tr.xlf index d37493b8e0470..2f01db9460ec3 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.tr.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.tr.xlf @@ -32,16 +32,6 @@ Blazor yönergesi öznitelikleri - - Diagnostics after: - Şundan sonraki tanılama: - - - - Diagnostics before: - Şundan önceki tanılama: - - directive yönerge @@ -54,31 +44,6 @@ Öğeler arasında gezinmek için [Tab], tamamlamak için [Enter] - - Edit at {0} adds the non-whitespace content '{1}'. - {0} konumunda düzenleme, '{1}' boşluk dışı içeriğini ekler. - - - - Edit at {0} deletes the non-whitespace content '{1}'. - {0} konumunda düzenleme, '{1}' boşluk dışı içeriğini siler. - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - Bir veya daha fazla tanılamayı ortaya çıkarabileceği veya kaldırabileceği için biçimlendirme işlemi bırakılıyor. - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - Boşluk dışı içeriği ekleyebileceği veya silebileceği için biçimlendirme işlemi bırakıl. - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - Biçimlendirme hatası. Dosyanın bozulmaması için çalışmaya devam etmeyin ve lütfen bu sorunu bildirin. Bkz.: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Razor düzenleyici, *.razor ve *.cshtml dosyalarının projede AdditionalFiles olmasını gerektiren Razor Kaynak Oluşturucuyu kullanır. {0}, AdditionalFile olan herhangi bir Razor belgesine sahip olmayan '{1}' dosyasından geliyor gibi görünüyor, bu nedenle düzenleme deneyimi sınırlı olacaktır. Razor SDK'sını kullanıyor mu? Bu proje için başka mesajlar günlüğe kaydedilmeyecektir. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hans.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hans.xlf index 04452359a1e6a..99cc4412e3cc2 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hans.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hans.xlf @@ -32,16 +32,6 @@ Blazor 指令特性 - - Diagnostics after: - 诊断后: - - - - Diagnostics before: - 诊断前: - - directive 指令 @@ -54,31 +44,6 @@ 按 [Tab] 在元素之间导航,按 [Enter] 以完成 - - Edit at {0} adds the non-whitespace content '{1}'. - 于 {0} 编辑,添加非空格内容“{1}”。 - - - - Edit at {0} deletes the non-whitespace content '{1}'. - 于 {0} 编辑,删除非空格内容“{1}”。 - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - 正在放弃格式操作,因为它会引入或删除其他诊断之一。 - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - 正在放弃格式操作,因为它会添加或删除非空格内容。 - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - 格式错误。为避免文件损坏,已停止后续操作,请报告此问题。详情请见:https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Razor 编辑器使用 Razor 源生成器,这要求 *.razor 和 *.cshtml 文件是项目中的 AdditionalFile。{0} 似乎来自“{1}”,其中不包含任何为 AdditionalFile 的 Razor 文档,因此编辑体验将受到限制。它使用的是 Razor SDK 吗?对于此项目,将不会记录更多消息。 diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hant.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hant.xlf index 3eab73cc139dc..5e638c6f5b554 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hant.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hant.xlf @@ -32,16 +32,6 @@ Blazor 指示詞屬性 - - Diagnostics after: - 在以下事項之後的診斷: - - - - Diagnostics before: - 在以下事項之前的診斷: - - directive 指示詞 @@ -54,31 +44,6 @@ [Tab] 在元素之間瀏覽,[Enter] 完成 - - Edit at {0} adds the non-whitespace content '{1}'. - 在 {0} 處編輯將新增非空白內容 '{1}'。 - - - - Edit at {0} deletes the non-whitespace content '{1}'. - 在 {0} 處編輯將刪除非空白內容 '{1}'。 - - - - A format operation is being abandoned because it would introduce or remove one of more diagnostics. - 將放棄格式化作業,因為它將引入或移除一個或多個診斷。 - - - - A format operation is being abandoned because it would add or delete non-whitespace content. - 將放棄格式化作業,因為它將新增或删除非空白內容。 - - - - Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue - 格式錯誤。為避免檔案損壞,已停止後續作業,請回報此問題。詳情請參閱: https://aka.ms/razor-formatting-issue - - The Razor editor utilizes the Razor Source Generator, which requires *.razor and *.cshtml files to be AdditionalFiles in the project. {0} appears to come from '{1}', which has no Razor documents that are AdditionalFiles, so the editing experience will be limited. Is it using the Razor SDK? No more messages will be logged for this project. Razor 編輯器會使用 Razor 原始碼產生器,其需要在專案中將 *.razor 和 *.cshtml 檔案設為 AdditionalFiles。{0} 似乎來自 '{1}',其沒有設為 AdditionalFiles 的 Razor 文件,因此編輯體驗將會受到限制。是否使用 Razor SDK?系統將不會再記錄此專案的任何訊息。 diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs index b2678b8f2e9aa..7aafff2f406ae 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/AutoInsert/RemoteAutoInsertService.cs @@ -173,12 +173,14 @@ private async ValueTask TryResolveInsertionInCSharpAsync( ? await _razorFormattingService.TryGetCSharpSnippetFormattingEditAsync( remoteDocumentContext, [csharpTextChange], + declarationDocument: false, // PROTOTYPE(sonic): Pass in the right value to this options, cancellationToken) .ConfigureAwait(false) : await _razorFormattingService.TryGetSingleCSharpEditAsync( remoteDocumentContext, csharpTextChange, + declarationDocument: false, // PROTOTYPE(sonic): Pass in the right value to this options, cancellationToken) .ConfigureAwait(false); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs index 35c2ecc5fe325..46802453cc774 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/CSharp/CSharpCodeActionResolver.cs @@ -76,6 +76,7 @@ public async Task ResolveAsync( var formattedChange = await _razorFormattingService.TryGetCSharpCodeActionEditAsync( editDocumentContext, csharpTextChanges, + declarationDocument: false, // PROTOTYPE(sonic): Pass in the right value to this formattingOptions, cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Html/HtmlCodeActionHelpers.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Html/HtmlCodeActionHelpers.cs index 31a79e3ec43e2..e8595aee8e6e1 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Html/HtmlCodeActionHelpers.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Html/HtmlCodeActionHelpers.cs @@ -4,8 +4,8 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Razor.DocumentMapping; -using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; namespace Microsoft.CodeAnalysis.Razor.CodeActions; @@ -23,7 +23,7 @@ internal static async Task MapAndFixHtmlCodeActionEditAsync(IRazorEditService ra foreach (var edit in codeAction.Edit.EnumerateTextDocumentEdits()) { - edit.Edits = FormattingUtilities.FixHtmlTextEdits(htmlSourceText, edit.Edits); + edit.Edits = htmlSourceText.FixHtmlTextEdits(edit.Edits); } } } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/ExtractToComponentCodeActionResolver.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/ExtractToComponentCodeActionResolver.cs index 05ff091012649..a57379fb2eacc 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/ExtractToComponentCodeActionResolver.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/ExtractToComponentCodeActionResolver.cs @@ -19,6 +19,7 @@ using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Razor; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; namespace Microsoft.CodeAnalysis.Remote.Razor.CodeActions; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/GenerateEventHandlerCodeActionResolver.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/GenerateEventHandlerCodeActionResolver.cs index 7cec116f595ed..4778ab0504de4 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/GenerateEventHandlerCodeActionResolver.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/GenerateEventHandlerCodeActionResolver.cs @@ -19,6 +19,7 @@ using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; @@ -125,7 +126,9 @@ await GetCodeBehindSyntaxTreeAsync(documentContext, codeBehindPath, cancellation // to create a code block if one doesn't exist, or put the method in an existing one, and it will also ensure the method gets properly formatted. var csharpSourceText = code.GetCSharpSourceText(); var csharpTextChanges = edits.SelectAsArray(csharpSourceText.GetTextChange); - var formattedChange = await _razorFormattingService.TryGetCSharpCodeActionEditAsync(documentContext, csharpTextChanges, options, cancellationToken).ConfigureAwait(false); + var formattedChange = await _razorFormattingService.TryGetCSharpCodeActionEditAsync(documentContext, csharpTextChanges, + declarationDocument: false, // PROTOTYPE(sonic): Pass in the right value to this + options, cancellationToken).ConfigureAwait(false); if (formattedChange is not { } razorChange) { return null; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/WrapAttributesCodeActionResolver.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/WrapAttributesCodeActionResolver.cs index ab61078be3e9b..c9653e73c30d4 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/WrapAttributesCodeActionResolver.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/Razor/WrapAttributesCodeActionResolver.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.Razor.CodeActions.Models; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DevTools/RemoteDevToolsService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DevTools/RemoteDevToolsService.cs index 3eb9d5045a3cc..723c5145438c4 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DevTools/RemoteDevToolsService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DevTools/RemoteDevToolsService.cs @@ -6,9 +6,9 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol.DevTools; using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -66,10 +66,16 @@ public ValueTask GetFormattingDocumentTextAsync( async context => { var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false); - var csharpSyntaxTree = await context.Snapshot.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + var csharpSyntaxTree = await context.Snapshot.GetCSharpSyntaxTreeAsync(declarationDocument: false, cancellationToken).ConfigureAwait(false); + var declSyntaxTree = codeDocument.GetCSharpDocument(declarationDocument: true) is not null + ? await context.Snapshot.GetCSharpSyntaxTreeAsync(declarationDocument: true, cancellationToken).ConfigureAwait(false) + : null; var csharpSyntaxRoot = await csharpSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + var declSyntaxRoot = declSyntaxTree is not null + ? await declSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false) + : null; #pragma warning disable CS0618 // Type or member is obsolete - return CSharpFormattingPass.GetFormattingDocumentContentsForSyntaxVisualizer(codeDocument, csharpSyntaxRoot, DocumentMappingService); + return CSharpFormattingPass.GetFormattingDocumentContentsForSyntaxVisualizer(codeDocument, csharpSyntaxRoot, declSyntaxRoot, DocumentMappingService); #pragma warning restore CS0618 // Type or member is obsolete }, cancellationToken); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentMapping/RazorEditService_Members.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentMapping/RazorEditService_Members.cs index 58bb0517398cc..1f8f9c9274f1d 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentMapping/RazorEditService_Members.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentMapping/RazorEditService_Members.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Text; using RoslynSyntaxNode = Microsoft.CodeAnalysis.SyntaxNode; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/FoldingRangeService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/FoldingRangeService.cs index 197372e0d2554..98c9740cd411b 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/FoldingRangeService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/FoldingRangeService.cs @@ -27,7 +27,7 @@ internal sealed class FoldingRangeService( private readonly IEnumerable _foldingRangeProviders = foldingRangeProviders; private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); - public ImmutableArray GetFoldingRanges(RazorCodeDocument codeDocument, FoldingRange[] csharpRanges, ImmutableArray htmlRanges, CancellationToken cancellationToken) + public ImmutableArray GetFoldingRanges(RazorCodeDocument codeDocument, FoldingRange[] csharpRanges, FoldingRange[]? declCSharpRanges, ImmutableArray htmlRanges, CancellationToken cancellationToken) { using var _ = ArrayBuilderPool.GetPooledObject(out var mappedRanges); @@ -35,20 +35,30 @@ public ImmutableArray GetFoldingRanges(RazorCodeDocument codeDocum // but we will at least have one per html range so can avoid some initial resizing of the backing data store. mappedRanges.SetCapacityIfLarger(htmlRanges.Length); - var csharpDocument = codeDocument.GetRequiredImplCSharpDocument(); + AddMappedCSharpRanges(csharpRanges, declarationDocument: false); + AddMappedCSharpRanges(declCSharpRanges, declarationDocument: true); - foreach (var foldingRange in csharpRanges) + void AddMappedCSharpRanges(FoldingRange[]? ranges, bool declarationDocument) { - var span = GetLinePositionSpan(foldingRange); + if (ranges is null) + { + return; + } - if (_documentMappingService.TryMapToRazorDocumentRange(csharpDocument, span, out var mappedSpan)) + var csharpDocument = codeDocument.GetRequiredCSharpDocument(declarationDocument); + foreach (var foldingRange in ranges) { - foldingRange.StartLine = mappedSpan.Start.Line; - foldingRange.StartCharacter = mappedSpan.Start.Character; - foldingRange.EndLine = mappedSpan.End.Line; - foldingRange.EndCharacter = mappedSpan.End.Character; + var span = GetLinePositionSpan(foldingRange); + + if (_documentMappingService.TryMapToRazorDocumentRange(csharpDocument, span, out var mappedSpan)) + { + foldingRange.StartLine = mappedSpan.Start.Line; + foldingRange.StartCharacter = mappedSpan.Start.Character; + foldingRange.EndLine = mappedSpan.End.Line; + foldingRange.EndCharacter = mappedSpan.End.Character; - mappedRanges.Add(foldingRange); + mappedRanges.Add(foldingRange); + } } } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/IFoldingRangeService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/IFoldingRangeService.cs index a3b55f57ba730..96d36fac0f12e 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/IFoldingRangeService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/IFoldingRangeService.cs @@ -9,5 +9,5 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.FoldingRanges; internal interface IFoldingRangeService { - ImmutableArray GetFoldingRanges(RazorCodeDocument codeDocument, FoldingRange[] csharpRanges, ImmutableArray htmlRanges, CancellationToken cancellationToken); + ImmutableArray GetFoldingRanges(RazorCodeDocument codeDocument, FoldingRange[] csharpRanges, FoldingRange[]? declCSharpRanges, ImmutableArray htmlRanges, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs index 4391a65a3057a..fd50ce8f4c3ec 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/RemoteFoldingRangeService.cs @@ -41,18 +41,22 @@ private async ValueTask> GetFoldingRangesAsyn ImmutableArray htmlRanges, CancellationToken cancellationToken) { - var generatedDocument = await context.Snapshot - .GetGeneratedDocumentAsync(cancellationToken) - .ConfigureAwait(false); - var lineFoldingOnly = _clientCapabilitiesService.ClientCapabilities.TextDocument?.FoldingRange?.LineFoldingOnly ?? false; - var globalOptions = generatedDocument.Project.Solution.Services.ExportProvider.GetService(); + var globalOptions = context.TextDocument.Project.Solution.Services.ExportProvider.GetService(); + + var generatedDocument = await context.Snapshot.GetGeneratedDocumentAsync(declarationDocument: false, cancellationToken).ConfigureAwait(false); var csharpRanges = await FoldingRangesHandler.GetFoldingRangesAsync(globalOptions, generatedDocument, lineFoldingOnly, cancellationToken).ConfigureAwait(false); + FoldingRange[]? declCSharpRanges = null; + if (await context.Snapshot.TryGetGeneratedDocumentAsync(declarationDocument: true, cancellationToken).ConfigureAwait(false) is SourceGeneratedDocument declGeneratedDocument) + { + declCSharpRanges = await FoldingRangesHandler.GetFoldingRangesAsync(globalOptions, declGeneratedDocument, lineFoldingOnly, cancellationToken).ConfigureAwait(false); + } + var convertedHtml = htmlRanges.SelectAsArray(RemoteFoldingRange.ToLspFoldingRange); var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false); - return _foldingRangeService.GetFoldingRanges(codeDocument, csharpRanges, convertedHtml, cancellationToken) + return _foldingRangeService.GetFoldingRanges(codeDocument, csharpRanges, declCSharpRanges, convertedHtml, cancellationToken) .SelectAsArray(RemoteFoldingRange.FromLspFoldingRange); } } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormatter.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/CSharpFormatter.cs similarity index 90% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormatter.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/CSharpFormatter.cs index cae41d2912c37..591b5afc22a13 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/CSharpFormatter.cs @@ -13,47 +13,15 @@ using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Indentation; -using Microsoft.CodeAnalysis.Options; +using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed class CSharpFormatter { private const string MarkerId = "RazorMarker"; - internal static CSharpSyntaxFormattingOptions GetCSharpSyntaxFormattingOptions( - SolutionServices services, - CSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptions) - { - csharpSyntaxFormattingOptions - ??= (CSharpSyntaxFormattingOptions)(services.GetService()?.GetSyntaxFormattingOptions(services.GetLanguageServices(LanguageNames.CSharp)) - ?? CSharpSyntaxFormattingOptions.Default); - - return csharpSyntaxFormattingOptions; - } - - internal static CSharpSyntaxFormattingOptions GetResolvedCSharpSyntaxFormattingOptions( - SolutionServices services, - RazorFormattingOptions options, - CSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptions = null) - { - csharpSyntaxFormattingOptions = GetCSharpSyntaxFormattingOptions( - services, - csharpSyntaxFormattingOptions ?? options.CSharpSyntaxFormattingOptions); - - return csharpSyntaxFormattingOptions with - { - LineFormatting = csharpSyntaxFormattingOptions.LineFormatting with - { - UseTabs = !options.InsertSpaces, - TabSize = options.TabSize, - IndentationSize = options.TabSize, - NewLine = CSharpSyntaxFormattingOptions.Default.NewLine - } - }; - } - internal static IndentationOptions GetIndentationOptions( SolutionServices services, RazorFormattingOptions options, @@ -61,7 +29,7 @@ internal static IndentationOptions GetIndentationOptions( FormattingOptions2.IndentStyle indentStyle, CSharpSyntaxFormattingOptions? csharpSyntaxFormattingOptions = null) { - var resolvedCSharpSyntaxFormattingOptions = GetResolvedCSharpSyntaxFormattingOptions( + var resolvedCSharpSyntaxFormattingOptions = CSharpFormattingOptionsHelper.GetResolvedCSharpSyntaxFormattingOptions( services, options, csharpSyntaxFormattingOptions); @@ -107,7 +75,7 @@ private static async Task> GetCSharpIndentationCoreAsync( // At this point, we have added all the necessary markers and attached annotations. // Let's invoke the C# formatter and hope for the best. - var formattingOptions = GetResolvedCSharpSyntaxFormattingOptions( + var formattingOptions = CSharpFormattingOptionsHelper.GetResolvedCSharpSyntaxFormattingOptions( hostWorkspaceServices.SolutionServices, context.Options); var formattedRoot = Formatter.Format( @@ -318,7 +286,7 @@ static bool IgnoreInitializerExpression(InitializerExpressionSyntax initializer, using var changes = new PooledArrayBuilder(); - var syntaxTree = await context.CurrentSnapshot.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + var syntaxTree = await context.CurrentSnapshot.GetCSharpSyntaxTreeAsync(context.CSharpDocument.IsDeclarationDocument, cancellationToken).ConfigureAwait(false); var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var previousMarkerOffset = 0; @@ -360,7 +328,7 @@ static bool IgnoreInitializerExpression(InitializerExpressionSyntax initializer, } } - var changedText = context.CSharpSourceText.WithChanges(changes.ToImmutable()); + var changedText = context.CSharpDocument.Text.WithChanges(changes.ToImmutable()); return (indentationMap, syntaxTree.WithChangedText(changedText)); } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattedDocument.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattedDocument.cs similarity index 84% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattedDocument.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattedDocument.cs index 1b9872152d308..3d1b0302ad5ab 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattedDocument.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattedDocument.cs @@ -4,6 +4,6 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal readonly record struct FormattedDocument(SourceText SourceText, ImmutableArray LineInfo); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingBlockKind.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingBlockKind.cs similarity index 85% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingBlockKind.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingBlockKind.cs index 2ecdeba3b0b38..c927565efd296 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingBlockKind.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingBlockKind.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal enum FormattingBlockKind { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingContext.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingContext.cs similarity index 94% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingContext.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingContext.cs index ead39bbbfa742..32a344073c5fb 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingContext.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingContext.cs @@ -9,22 +9,27 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Syntax; using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed class FormattingContext { private ImmutableArray? _formattingSpans; private IReadOnlyDictionary? _indentations; + private readonly RazorCSharpDocument? _csharpDocument; + private FormattingContext( IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, + bool? declarationDocument, IDocumentSnapshot currentSnapshot, RazorFormattingOptions options, IFormattingLogger? logger, @@ -40,6 +45,11 @@ private FormattingContext( IncludeCSharpLanguageFeatureEdits = includeCSharpLanguageFeatureEdits; HostDocumentIndex = hostDocumentIndex; TriggerCharacter = triggerCharacter; + + if (declarationDocument is { } declDoc) + { + _csharpDocument = codeDocument.GetRequiredCSharpDocument(declDoc); + } } public static bool SkipValidateComponents { get; set; } @@ -55,7 +65,7 @@ private FormattingContext( public SourceText SourceText => CodeDocument.Source.Text; - public SourceText CSharpSourceText => CodeDocument.GetCSharpSourceText(); + public RazorCSharpDocument CSharpDocument => _csharpDocument.AssumeNotNull("Cannot get C# source text when declaration document is not specified."); public string NewLineString => Environment.NewLine; @@ -240,6 +250,7 @@ public async Task WithTextAsync(SourceText changedText, Cance var newContext = new FormattingContext( OriginalSnapshot, codeDocument, + _csharpDocument?.IsDeclarationDocument, currentSnapshot: changedSnapshot, Options, Logger, @@ -271,6 +282,7 @@ private static void DEBUG_ValidateComponents(RazorCodeDocument oldCodeDocument, public static FormattingContext CreateForOnTypeFormatting( IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, + bool? declarationDocument, RazorFormattingOptions options, IFormattingLogger? logger, bool includeCSharpLanguageFeatureEdits, @@ -280,6 +292,7 @@ public static FormattingContext CreateForOnTypeFormatting( return new FormattingContext( originalSnapshot, codeDocument, + declarationDocument, currentSnapshot: originalSnapshot, options, logger, @@ -297,6 +310,7 @@ public static FormattingContext Create( return new FormattingContext( originalSnapshot, codeDocument, + declarationDocument: null, currentSnapshot: originalSnapshot, options, logger, diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingLogger.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingLogger.cs similarity index 95% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingLogger.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingLogger.cs index 2c467a1449934..83317ccb7a6c4 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingLogger.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingLogger.cs @@ -7,7 +7,7 @@ using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed class FormattingLogger(string logFolder) : IFormattingLogger { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingLoggerFactory.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingLoggerFactory.cs similarity index 87% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingLoggerFactory.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingLoggerFactory.cs index 25d166e452bcb..59032e21248ac 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingLoggerFactory.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingLoggerFactory.cs @@ -2,11 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Composition; using System.IO; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; -internal class FormattingLoggerFactory : IFormattingLoggerFactory +[Export(typeof(IFormattingLoggerFactory)), Shared] +internal sealed class FormattingLoggerFactory : IFormattingLoggerFactory { private const string LogDirEnvVar = "RazorFormattingLogPath"; private static string? BaseLogDir { get; } = Environment.GetEnvironmentVariable(LogDirEnvVar); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingSpan.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingSpan.cs similarity index 93% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingSpan.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingSpan.cs index cae8539161eb6..c59b194bf82bd 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingSpan.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingSpan.cs @@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed record class FormattingSpan( TextSpan Span, diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingSpanKind.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingSpanKind.cs similarity index 81% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingSpanKind.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingSpanKind.cs index 42dfecfdb37d1..d002a9b20be1c 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingSpanKind.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingSpanKind.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal enum FormattingSpanKind { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingUtilities.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingUtilities.cs similarity index 95% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingUtilities.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingUtilities.cs index ed1abfce3f1ba..0b3e6ea737ba9 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingUtilities.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingUtilities.cs @@ -2,16 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.Linq; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal static class FormattingUtilities { @@ -208,35 +206,6 @@ static ImmutableArray GetLineRanges(string text) } } - /// - /// Sometimes the Html language server will send back an edit that contains a tilde, because the generated - /// document we send them has lots of tildes. In those cases, we need to do some extra work to compute the - /// minimal text edits - /// - public static TextEdit[] FixHtmlTextEdits(SourceText htmlSourceText, TextEdit[] edits) - { - // Avoid computing a minimal diff if we don't need to - if (!edits.Any(static e => e.NewText.Contains('~'))) - return edits; - - var changes = edits.SelectAsArray(htmlSourceText.GetTextChange); - - var fixedChanges = htmlSourceText.MinimizeTextChanges(changes); - return fixedChanges.SelectAsPlainArray(htmlSourceText.GetTextEdit); - } - - internal static SumType[] FixHtmlTextEdits(SourceText htmlSourceText, SumType[] edits) - { - // Avoid computing a minimal diff if we don't need to - if (!edits.Any(static e => ((TextEdit)e).NewText.Contains('~'))) - return edits; - - var changes = edits.SelectAsArray(e => htmlSourceText.GetTextChange((TextEdit)e)); - - var fixedChanges = htmlSourceText.MinimizeTextChanges(changes); - return fixedChanges.SelectAsPlainArray>(c => htmlSourceText.GetTextEdit(c)); - } - public static void GetOriginalDocumentChangesFromLineInfo(FormattingContext context, SourceText originalText, ImmutableArray formattedLineInfo, SourceText formattedText, ILogger logger, Func? shouldKeepInsertedNewlineAtPosition, ref PooledArrayBuilder formattingChanges, out int lastFormattedTextLine) { var iFormatted = 0; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingVisitor.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingVisitor.cs similarity index 99% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingVisitor.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingVisitor.cs index 5a392347cbb0a..4932ae51ea71b 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/FormattingVisitor.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/FormattingVisitor.cs @@ -10,7 +10,7 @@ using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.AspNetCore.Razor.Language.Syntax; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingLogger.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingLogger.cs similarity index 86% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingLogger.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingLogger.cs index 2d5c32380b058..2bea42b48b547 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingLogger.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingLogger.cs @@ -3,7 +3,7 @@ using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal interface IFormattingLogger { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingLoggerFactory.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingLoggerFactory.cs similarity index 82% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingLoggerFactory.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingLoggerFactory.cs index 1ef008ea4552f..3e5ce9082ca05 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingLoggerFactory.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingLoggerFactory.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal interface IFormattingLoggerFactory { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingPass.cs similarity index 88% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingPass.cs index 96e185871a239..bb4a88004d47f 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingPass.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal interface IFormattingPass { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingValidationPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingValidationPass.cs similarity index 88% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingValidationPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingValidationPass.cs index 8dbdb39d0f4af..6935d3f4428d2 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IFormattingValidationPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IFormattingValidationPass.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal interface IFormattingValidationPass { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IndentCache.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IndentCache.cs similarity index 98% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IndentCache.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IndentCache.cs index 55833c35cab6d..279dfcfe91684 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IndentCache.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IndentCache.cs @@ -6,7 +6,7 @@ #endif using Microsoft.AspNetCore.Razor; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal static class IndentCache { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IndentationContext.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IndentationContext.cs similarity index 95% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IndentationContext.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IndentationContext.cs index 0ef3a2dae0a40..44895f428c389 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/IndentationContext.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/IndentationContext.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed record class IndentationContext( FormattingSpan FirstSpan, diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/LineInfo.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/LineInfo.cs similarity index 97% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/LineInfo.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/LineInfo.cs index 0d0bf2221948c..4a2ab71a06e01 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/LineInfo.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/LineInfo.cs @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; /// /// Represents the state of a line in the generated C# document. diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.CSharpDocumentGenerator.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpFormattingPass.CSharpDocumentGenerator.cs similarity index 95% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.CSharpDocumentGenerator.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpFormattingPass.CSharpDocumentGenerator.cs index 486e445066fc8..5374f0280dd5a 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.CSharpDocumentGenerator.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpFormattingPass.CSharpDocumentGenerator.cs @@ -1,7 +1,8 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Linq; @@ -12,14 +13,16 @@ using Microsoft.AspNetCore.Razor.Language.Syntax; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.CSharp.Formatting; +using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.DocumentMapping; +using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Settings; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode; using RazorSyntaxToken = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxToken; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal partial class CSharpFormattingPass { @@ -83,13 +86,13 @@ internal partial class CSharpFormattingPass /// private sealed class CSharpDocumentGenerator { - public static FormattedDocument Generate(RazorCodeDocument codeDocument, SyntaxNode csharpSyntaxRoot, RazorFormattingOptions options, IDocumentMappingService documentMappingService) + public static FormattedDocument Generate(RazorCodeDocument codeDocument, SyntaxNode csharpSyntaxRoot, SyntaxNode? declSyntaxRoot, RazorFormattingOptions options, IDocumentMappingService documentMappingService) { using var _1 = StringBuilderPool.GetPooledObject(out var builder); using var _2 = ArrayBuilderPool.GetPooledObject(out var lineInfoBuilder); lineInfoBuilder.SetCapacityIfLarger(codeDocument.Source.Text.Lines.Count); - var generator = new Generator(codeDocument, csharpSyntaxRoot, options, builder, lineInfoBuilder, documentMappingService); + var generator = new Generator(codeDocument, csharpSyntaxRoot, declSyntaxRoot, options, builder, lineInfoBuilder, documentMappingService); generator.Generate(); @@ -147,6 +150,7 @@ public static bool TryParseAdditionalLineComment(TextLine line, out int start, o private sealed class Generator( RazorCodeDocument codeDocument, SyntaxNode csharpSyntaxRoot, + SyntaxNode? declSyntaxRoot, RazorFormattingOptions options, StringBuilder builder, ImmutableArray.Builder lineInfoBuilder, @@ -158,6 +162,7 @@ private sealed class Generator( private readonly SourceText _sourceText = codeDocument.Source.Text; private readonly RazorCodeDocument _codeDocument = codeDocument; private readonly SyntaxNode _csharpSyntaxRoot = csharpSyntaxRoot; + private readonly SyntaxNode? _declSyntaxRoot = declSyntaxRoot; private readonly bool _insertSpaces = options.InsertSpaces; private readonly int _tabSize = options.TabSize; private readonly AttributeIndentStyle _attributeIndentStyle = options.AttributeIndentStyle; @@ -165,7 +170,6 @@ private sealed class Generator( private readonly StringBuilder _builder = builder; private readonly ImmutableArray.Builder _lineInfoBuilder = lineInfoBuilder; private readonly IDocumentMappingService _documentMappingService = documentMappingService; - private readonly RazorCSharpDocument _csharpDocument = codeDocument.GetImplCSharpDocument().AssumeNotNull(); private TextLine _currentLine; private int _currentFirstNonWhitespacePosition; @@ -198,7 +202,7 @@ public void Generate() using var _ = StringBuilderPool.GetPooledObject(out var additionalLinesBuilder); var root = _codeDocument.GetRequiredSyntaxRoot(); - var sourceMappings = _codeDocument.GetRequiredImplCSharpDocument().SourceMappingsSortedByOriginal; + var sourceMappings = GetAllSourceMappingOriginalSpans(); var iMapping = 0; foreach (var line in _sourceText.Lines) { @@ -216,7 +220,7 @@ public void Generate() // If there are C# mappings on this line, we want to output additional lines that represent the C# blocks. while (iMapping < sourceMappings.Length) { - var originalSpan = sourceMappings[iMapping].OriginalSpan; + var originalSpan = sourceMappings[iMapping]; if (originalSpan.AbsoluteIndex < _currentFirstNonWhitespacePosition) { iMapping++; @@ -264,6 +268,29 @@ public void Generate() _builder.AppendLine(additionalLinesBuilder.ToString()); } + /// + /// Source mappings are stored separately for each C# document, but for the purposes of finding C# code in the middle of a line + /// of Razor code, we want to treat them as one combined list sorted by their position in the original Razor document. As long + /// as we know which C# document they came from, we can still find the relevant syntax nodes in the C# syntax tree. + /// + private ImmutableArray GetAllSourceMappingOriginalSpans() + { + var csharpDoc = _codeDocument.GetRequiredCSharpDocument(declarationDocument: false); + + using var _ = HashSetPool.GetPooledObject(out var mappings); + mappings.AddRange(csharpDoc.SourceMappingsSortedByOriginal.Select(static m => m.OriginalSpan)); + + if (_declSyntaxRoot is not null) + { + var declDoc = _codeDocument.GetRequiredCSharpDocument(declarationDocument: true); + mappings.AddRange(declDoc.SourceMappingsSortedByOriginal.Select(static m => m.OriginalSpan)); + } + + // We assume that if there is a location in a Razor document that maps to both C# documents, it's because it maps to the + // same construct (ie, a using directive that appears in both C# documents) and so we can just include one. + return mappings.OrderAsArray(static (lhs, rhs) => lhs.AbsoluteIndex.CompareTo(rhs.AbsoluteIndex)); + } + private void AddAdditionalLineFormattingContent(StringBuilder additionalLinesBuilder, RazorSyntaxNode node, SourceSpan originalSpan) { // Rather than bother to store more data about the formatted file, since we don't actually know where @@ -561,12 +588,17 @@ private LineInfo VisitCSharpLiteral(RazorSyntaxNode node, RazorSyntaxToken lastT // If we're here, it means this is a "normal" line of C#, so we can just emit it as is. The exception to this is // when we're inside a string literal. We still want to emit it as is, but we need to make sure we tell the formatter // to ignore any existing indentation too. - if (_documentMappingService.TryMapToCSharpDocumentPosition(_csharpDocument, _currentToken.SpanStart, out _, out var csharpIndex) && - _csharpSyntaxRoot.FindNode(new TextSpan(csharpIndex, 0), getInnermostNodeForTie: true) is { } csharpNode && - csharpNode.IsStringLiteral(multilineOnly: true)) + if (_documentMappingService.TryMapToCSharpDocumentLinePosition(_codeDocument, _currentToken.SpanStart, out _, out var csharpIndex, out var inDeclDocument)) { - _builder.AppendLine(_currentLine.ToString()); - return CreateLineInfo(processIndentation: false, processFormatting: true, checkForNewLines: true); + var csharpSyntaxRoot = inDeclDocument + ? _declSyntaxRoot.AssumeNotNull() + : _csharpSyntaxRoot; + if (csharpSyntaxRoot.FindNode(new TextSpan(csharpIndex, 0), getInnermostNodeForTie: true) is { } csharpNode && + csharpNode.IsStringLiteral(multilineOnly: true)) + { + _builder.AppendLine(_currentLine.ToString()); + return CreateLineInfo(processIndentation: false, processFormatting: true, checkForNewLines: true); + } } return EmitCurrentLineAsCSharp(); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpFormattingPass.cs similarity index 87% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpFormattingPass.cs index 0ee3e26240860..bea8a602b3d31 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpFormattingPass.cs @@ -1,4 +1,4 @@ - + // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. @@ -12,12 +12,13 @@ using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Razor.DocumentMapping; +using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.TextDifferencing; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed partial class CSharpFormattingPass( IHostServicesProvider hostServicesProvider, @@ -33,14 +34,21 @@ public async Task> ExecuteAsync(FormattingContext con // Process changes from previous passes var changedText = context.SourceText.WithChanges(changes); var changedContext = await context.WithTextAsync(changedText, cancellationToken).ConfigureAwait(false); - context.Logger?.LogObject("SourceMappings", changedContext.CodeDocument.GetRequiredImplCSharpDocument().SourceMappingsSortedByGenerated); + context.Logger?.LogObject("ImplSourceMappings", changedContext.CodeDocument.GetRequiredCSharpDocument(declarationDocument: false).SourceMappingsSortedByGenerated); + + SyntaxNode? declSyntaxRoot = null; + if (changedContext.CodeDocument.GetCSharpDocument(declarationDocument: true) is { } declarationDocument) + { + var declSyntaxTree = await changedContext.CurrentSnapshot.GetCSharpSyntaxTreeAsync(declarationDocument: true, cancellationToken).ConfigureAwait(false); + declSyntaxRoot = await declSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + } - var csharpSyntaxTrue = await changedContext.CurrentSnapshot.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var csharpSyntaxRoot = await csharpSyntaxTrue.GetRootAsync(cancellationToken).ConfigureAwait(false); + var csharpSyntaxTree = await changedContext.CurrentSnapshot.GetCSharpSyntaxTreeAsync(declarationDocument: false, cancellationToken).ConfigureAwait(false); + var csharpSyntaxRoot = await csharpSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); // To format C# code we generate a C# document that represents the indentation semantics the user would be // expecting in their Razor file. See the doc comments on CSharpDocumentGenerator for more info - var generatedDocument = CSharpDocumentGenerator.Generate(changedContext.CodeDocument, csharpSyntaxRoot, context.Options, _documentMappingService); + var generatedDocument = CSharpDocumentGenerator.Generate(changedContext.CodeDocument, csharpSyntaxRoot, declSyntaxRoot, context.Options, _documentMappingService); var generatedCSharpText = generatedDocument.SourceText; context.Logger?.LogSourceText("FormattingDocument", generatedCSharpText); @@ -143,7 +151,7 @@ private async Task FormatCSharpAsync(SourceText generatedCSharpText, }; } - var formattingOptions = CSharpFormatter.GetResolvedCSharpSyntaxFormattingOptions( + var formattingOptions = CSharpFormattingOptionsHelper.GetResolvedCSharpSyntaxFormattingOptions( helper.HostWorkspaceServices.SolutionServices, options, csharpSyntaxFormattingOptions); @@ -158,6 +166,6 @@ private async Task FormatCSharpAsync(SourceText generatedCSharpText, } [Obsolete("Only for the syntax visualizer, do not call")] - internal static string GetFormattingDocumentContentsForSyntaxVisualizer(RazorCodeDocument codeDocument, SyntaxNode csharpSyntaxRoot, IDocumentMappingService documentMappingService) - => CSharpDocumentGenerator.Generate(codeDocument, csharpSyntaxRoot, new(), documentMappingService).SourceText.ToString(); + internal static string GetFormattingDocumentContentsForSyntaxVisualizer(RazorCodeDocument codeDocument, SyntaxNode csharpSyntaxRoot, SyntaxNode? declSyntaxRoot, IDocumentMappingService documentMappingService) + => CSharpDocumentGenerator.Generate(codeDocument, csharpSyntaxRoot, declSyntaxRoot, new(), documentMappingService).SourceText.ToString(); } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpOnTypeFormattingPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpOnTypeFormattingPass.cs similarity index 98% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpOnTypeFormattingPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpOnTypeFormattingPass.cs index 115635498dd90..24ea7943225f0 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpOnTypeFormattingPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/CSharpOnTypeFormattingPass.cs @@ -27,7 +27,7 @@ using Microsoft.VisualStudio.Threading; using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; /// /// Gets edits in C# files, and returns edits to Razor files, with nicely formatted Html @@ -49,18 +49,19 @@ public async Task> ExecuteAsync(FormattingContext con // Normalize and re-map the C# edits. var codeDocument = context.CodeDocument; - var csharpText = codeDocument.GetCSharpSourceText(); + var csharpDocument = context.CSharpDocument; + var csharpText = csharpDocument.Text; if (changes.Length == 0) { - if (!_documentMappingSerivce.TryMapToCSharpDocumentPosition(codeDocument.GetRequiredImplCSharpDocument(), context.HostDocumentIndex, out _, out var projectedIndex)) + if (!_documentMappingSerivce.TryMapToCSharpDocumentPosition(csharpDocument, context.HostDocumentIndex, out _, out var projectedIndex)) { _logger.LogWarning($"Failed to map to projected position for document {context.OriginalSnapshot.FilePath}."); return []; } // Ask C# for formatting changes. - var document = roslynWorkspaceHelper.CreateCSharpDocument(context.CodeDocument); + var document = roslynWorkspaceHelper.CreateCSharpDocument(context.CSharpDocument); var formattingService = document.Project.Services.GetRequiredService(); var documentSyntax = await ParsedDocument.CreateAsync(document, cancellationToken).ConfigureAwait(false); @@ -117,7 +118,7 @@ public async Task> ExecuteAsync(FormattingContext con var mappedChanges = await _razorEditService.MapCSharpEditsAsync( normalizedChanges.SelectAsArray(static c => c.ToRazorTextChange()), context.CurrentSnapshot, - declarationDocument: false, // PROTOTYPE: Still to fix + declarationDocument: csharpDocument.IsDeclarationDocument, context.IncludeCSharpLanguageFeatureEdits, directlyMappedEditFilter: change => ShouldKeepDirectlyMappedEdit(context, indent, change), cancellationToken).ConfigureAwait(false); @@ -133,7 +134,7 @@ public async Task> ExecuteAsync(FormattingContext con var originalText = codeDocument.Source.Text; context.Logger?.LogSourceText("OriginalRazor", originalText); - context.Logger?.LogMessage($"Source Mappings:\r\n{RenderSourceMappings(context.CodeDocument)}"); + context.Logger?.LogMessage($"Source Mappings:\r\n{RenderSourceMappings(context.CSharpDocument)}"); // Apply the format on type edits sent over by the client. var formattedText = ApplyChangesAndTrackChange(originalText, filteredChanges, out _, out var spanAfterFormatting); @@ -282,7 +283,7 @@ private static int LineDelta(SourceText text, IEnumerable changes, o private static ImmutableArray CleanupDocument(FormattingContext context, LinePositionSpan spanAfterFormatting) { var text = context.SourceText; - var csharpDocument = context.CodeDocument.GetRequiredImplCSharpDocument(); + var csharpDocument = context.CSharpDocument; using var changes = new PooledArrayBuilder(); foreach (var mapping in csharpDocument.SourceMappingsSortedByOriginal) @@ -561,7 +562,7 @@ private async Task> AdjustIndentationAsync(Formatting // 2. The indentation due to Razor and HTML constructs var text = context.SourceText; - var csharpDocument = context.CodeDocument.GetRequiredImplCSharpDocument(); + var csharpDocument = context.CSharpDocument; // To help with figuring out the correct indentation, first we will need the indentation // that the C# formatter wants to apply in the following locations, @@ -1148,14 +1149,14 @@ owner.Parent is CSharpCodeBlockSyntax codeBlock && } } - private static string RenderSourceMappings(RazorCodeDocument codeDocument) + private static string RenderSourceMappings(RazorCSharpDocument csharpDocument) { using var pooledBuilder = AspNetCore.Razor.PooledObjects.StringBuilderPool.GetPooledObject(); var builder = pooledBuilder.Object; - var documentText = codeDocument.Source.Text.ToString(); + var documentText = csharpDocument.CodeDocument.Source.Text.ToString(); var lastIndex = 0; - foreach (var mapping in codeDocument.GetRequiredImplCSharpDocument().SourceMappingsSortedByOriginal) + foreach (var mapping in csharpDocument.SourceMappingsSortedByOriginal) { var originalStart = mapping.OriginalSpan.AbsoluteIndex; var originalEnd = originalStart + mapping.OriginalSpan.Length; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/FormattingContentValidationPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/FormattingContentValidationPass.cs similarity index 97% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/FormattingContentValidationPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/FormattingContentValidationPass.cs index cc9377744f72e..ccd61a0c3a7e8 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/FormattingContentValidationPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/FormattingContentValidationPass.cs @@ -11,7 +11,7 @@ using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed class FormattingContentValidationPass(ILoggerFactory loggerFactory) : IFormattingValidationPass { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/FormattingDiagnosticValidationPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/FormattingDiagnosticValidationPass.cs similarity index 98% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/FormattingDiagnosticValidationPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/FormattingDiagnosticValidationPass.cs index 6b17d2425fd6a..671af1a21dae1 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/FormattingDiagnosticValidationPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/FormattingDiagnosticValidationPass.cs @@ -13,7 +13,7 @@ using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed class FormattingDiagnosticValidationPass(ILoggerFactory loggerFactory) : IFormattingValidationPass { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/HtmlFormattingPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/HtmlFormattingPass.cs similarity index 92% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/HtmlFormattingPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/HtmlFormattingPass.cs index 3516e2214d79d..2a83b896117ec 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/HtmlFormattingPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/HtmlFormattingPass.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Immutable; @@ -11,13 +11,14 @@ using Microsoft.AspNetCore.Razor.Language.Syntax; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.TextDifferencing; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed partial class HtmlFormattingPass( IDocumentMappingService documentMappingService, @@ -87,11 +88,16 @@ public async Task> ExecuteAsync(FormattingContext con private async Task> FilterIncomingChangesAsync(FormattingContext context, ImmutableArray changes, CancellationToken cancellationToken) { var codeDocument = context.CodeDocument; - var csharpDocument = codeDocument.GetRequiredImplCSharpDocument(); var originalText = codeDocument.Source.Text; - var csharpSyntaxTree = await context.OriginalSnapshot.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); + var csharpSyntaxTree = await context.OriginalSnapshot.GetCSharpSyntaxTreeAsync(declarationDocument: false, cancellationToken).ConfigureAwait(false); var csharpSyntaxRoot = await csharpSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + SyntaxNode? declSyntaxRoot = null; + if (context.CodeDocument.GetCSharpDocument(declarationDocument: true) is { } declarationDocument) + { + var declSyntaxTree = await context.OriginalSnapshot.GetCSharpSyntaxTreeAsync(declarationDocument: true, cancellationToken).ConfigureAwait(false); + declSyntaxRoot = await declSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + } // Apply all changes to create the formatted document var formattedText = originalText.WithChanges(changes); @@ -193,11 +199,17 @@ ImmutableArray FilterChangesInStringLiterals(ImmutableArray /// Gets edits in Html files, and returns edits to Razor files, with nicely formatted Html diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/RazorFormattingPass.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/RazorFormattingPass.cs similarity index 99% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/RazorFormattingPass.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/RazorFormattingPass.cs index 307efdf114770..5b790e5b0d661 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/RazorFormattingPass.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/RazorFormattingPass.cs @@ -20,7 +20,7 @@ using RazorSyntaxNodeList = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxList; using RazorSyntaxNodeOrToken = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNodeOrToken; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed class RazorFormattingPass : IFormattingPass { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/RoslynWorkspaceHelper.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/RoslynWorkspaceHelper.cs similarity index 82% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/RoslynWorkspaceHelper.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/RoslynWorkspaceHelper.cs index 93c5a739ae10c..ae586307905b9 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/RoslynWorkspaceHelper.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/Passes/RoslynWorkspaceHelper.cs @@ -6,7 +6,7 @@ using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Razor.Workspaces; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal sealed class RoslynWorkspaceHelper(IHostServicesProvider hostServicesProvider) : IDisposable { @@ -14,11 +14,10 @@ internal sealed class RoslynWorkspaceHelper(IHostServicesProvider hostServicesPr public HostWorkspaceServices HostWorkspaceServices => _lazyWorkspace.Value.Services; - public Document CreateCSharpDocument(RazorCodeDocument codeDocument) + public Document CreateCSharpDocument(RazorCSharpDocument csharpDocument) { var project = _lazyWorkspace.Value.CurrentSolution.AddProject("TestProject", "TestProject", LanguageNames.CSharp); - var csharpSourceText = codeDocument.GetCSharpSourceText(); - return project.AddDocument("TestDocument", csharpSourceText); + return project.AddDocument("TestDocument", csharpDocument.Text); } private static AdhocWorkspace CreateWorkspace(IHostServicesProvider hostServicesProvider) diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/RazorFormattingService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RazorFormattingService.cs similarity index 93% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/RazorFormattingService.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RazorFormattingService.cs index d90b3576893ea..988ffafb674a6 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/RazorFormattingService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RazorFormattingService.cs @@ -1,10 +1,11 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Frozen; using System.Collections.Generic; using System.Collections.Immutable; +using System.Composition; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -13,20 +14,18 @@ using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor.DocumentMapping; +using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; -internal class RazorFormattingService : IRazorFormattingService +[Export(typeof(IRazorFormattingService)), Shared] +internal sealed class RazorFormattingService : IRazorFormattingService { - public const string FirstTriggerCharacter = "}"; - public static readonly string[] MoreTriggerCharacters = [";", "\n", "{"]; - public static readonly FrozenSet AllTriggerCharacterSet = FrozenSet.ToFrozenSet([FirstTriggerCharacter, .. MoreTriggerCharacters], StringComparer.Ordinal); - private static readonly FrozenSet s_csharpTriggerCharacterSet = FrozenSet.ToFrozenSet(["}", ";"], StringComparer.Ordinal); private static readonly FrozenSet s_htmlTriggerCharacterSet = FrozenSet.ToFrozenSet(["\n", "{", "}", ";"], StringComparer.Ordinal); @@ -37,6 +36,7 @@ internal class RazorFormattingService : IRazorFormattingService private IFormattingLoggerFactory _formattingLoggerFactory; + [ImportingConstructor] public RazorFormattingService( IDocumentMappingService documentMappingService, IRazorEditService razorEditService, @@ -86,7 +86,7 @@ public async Task> GetDocumentFormattingChangesAsync( var sourceText = codeDocument.Source.Text; if (range is { } span) { - if (codeDocument.GetRequiredImplCSharpDocument().Diagnostics.Any(d => d.Span != SourceSpan.Undefined && span.OverlapsWith(sourceText.GetLinePositionSpan(d.Span)))) + if (codeDocument.GetRequiredCSharpDocument(declarationDocument: false).Diagnostics.Any(d => d.Span != SourceSpan.Undefined && span.OverlapsWith(sourceText.GetLinePositionSpan(d.Span)))) { return []; } @@ -135,7 +135,7 @@ public async Task> GetDocumentFormattingChangesAsync( return originalText.MinimizeTextChanges(normalizedChanges); } - public async Task> GetCSharpOnTypeFormattingChangesAsync(DocumentContext documentContext, RazorFormattingOptions options, int hostDocumentIndex, char triggerCharacter, CancellationToken cancellationToken) + public async Task> GetCSharpOnTypeFormattingChangesAsync(DocumentContext documentContext, RazorFormattingOptions options, int hostDocumentIndex, char triggerCharacter, bool declarationDocument, CancellationToken cancellationToken) { var documentSnapshot = documentContext.Snapshot; @@ -144,6 +144,7 @@ public async Task> GetCSharpOnTypeFormattingChangesAs return await ApplyFormattedChangesAsync( documentSnapshot, codeDocument, + declarationDocument, generatedDocumentChanges: [], options, hostDocumentIndex, @@ -166,6 +167,7 @@ public async Task> GetHtmlOnTypeFormattingChangesAsyn return await ApplyFormattedChangesAsync( documentSnapshot, codeDocument, + declarationDocument: null, htmlChanges, options, hostDocumentIndex, @@ -178,7 +180,7 @@ public async Task> GetHtmlOnTypeFormattingChangesAsyn cancellationToken: cancellationToken).ConfigureAwait(false); } - public async Task TryGetSingleCSharpEditAsync(DocumentContext documentContext, TextChange csharpEdit, RazorFormattingOptions options, CancellationToken cancellationToken) + public async Task TryGetSingleCSharpEditAsync(DocumentContext documentContext, TextChange csharpEdit, bool declarationDocument, RazorFormattingOptions options, CancellationToken cancellationToken) { var documentSnapshot = documentContext.Snapshot; // Since we've been provided with an edit from the C# generated doc, forcing design time would make things not line up @@ -187,6 +189,7 @@ public async Task> GetHtmlOnTypeFormattingChangesAsyn var razorChanges = await ApplyFormattedChangesAsync( documentSnapshot, codeDocument, + declarationDocument, [csharpEdit], options, hostDocumentIndex: 0, @@ -203,7 +206,7 @@ public async Task> GetHtmlOnTypeFormattingChangesAsyn : null; } - public async Task TryGetCSharpCodeActionEditAsync(DocumentContext documentContext, ImmutableArray csharpChanges, RazorFormattingOptions options, CancellationToken cancellationToken) + public async Task TryGetCSharpCodeActionEditAsync(DocumentContext documentContext, ImmutableArray csharpChanges, bool declarationDocument, RazorFormattingOptions options, CancellationToken cancellationToken) { var documentSnapshot = documentContext.Snapshot; // Since we've been provided with edits from the C# generated doc, forcing design time would make things not line up @@ -212,6 +215,7 @@ public async Task> GetHtmlOnTypeFormattingChangesAsyn var razorChanges = await ApplyFormattedChangesAsync( documentSnapshot, codeDocument, + declarationDocument, csharpChanges, options, hostDocumentIndex: 0, @@ -228,7 +232,7 @@ public async Task> GetHtmlOnTypeFormattingChangesAsyn : null; } - public async Task TryGetCSharpSnippetFormattingEditAsync(DocumentContext documentContext, ImmutableArray csharpChanges, RazorFormattingOptions options, CancellationToken cancellationToken) + public async Task TryGetCSharpSnippetFormattingEditAsync(DocumentContext documentContext, ImmutableArray csharpChanges, bool declarationDocument, RazorFormattingOptions options, CancellationToken cancellationToken) { csharpChanges = WrapCSharpSnippets(csharpChanges); @@ -239,6 +243,7 @@ public async Task> GetHtmlOnTypeFormattingChangesAsyn var razorChanges = await ApplyFormattedChangesAsync( documentSnapshot, codeDocument, + declarationDocument, csharpChanges, options, hostDocumentIndex: 0, @@ -272,6 +277,7 @@ public bool TryGetOnTypeFormattingTriggerKind(RazorCodeDocument codeDocument, in private async Task> ApplyFormattedChangesAsync( IDocumentSnapshot documentSnapshot, RazorCodeDocument codeDocument, + bool? declarationDocument, ImmutableArray generatedDocumentChanges, RazorFormattingOptions options, int hostDocumentIndex, @@ -290,7 +296,7 @@ private async Task> ApplyFormattedChangesAsync( var logger = _formattingLoggerFactory.CreateLogger(documentSnapshot.FilePath, formattingType); logger?.LogObject("FileKind", documentSnapshot.FileKind); logger?.LogObject("Options", options); - logger?.LogObject("Parameters", new { hostDocumentIndex, triggerCharacter, collapseChanges, includeCSharpLanguageFeatureEdits, validate }); + logger?.LogObject("Parameters", new { hostDocumentIndex, triggerCharacter, collapseChanges, includeCSharpLanguageFeatureEdits, validate, declarationDocument }); logger?.LogObject("GeneratedDocumentChanges", generatedDocumentChanges); logger?.LogSourceText("InitialDocument", codeDocument.Source.Text); LogSyntaxTree(logger, codeDocument); @@ -298,6 +304,7 @@ private async Task> ApplyFormattedChangesAsync( var context = FormattingContext.CreateForOnTypeFormatting( documentSnapshot, codeDocument, + declarationDocument, options, logger, includeCSharpLanguageFeatureEdits: includeCSharpLanguageFeatureEdits, diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteFormattingLoggerFactory.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteFormattingLoggerFactory.cs deleted file mode 100644 index 4f7412481ee8d..0000000000000 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteFormattingLoggerFactory.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Composition; -using Microsoft.CodeAnalysis.Razor.Formatting; - -namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; - -[Export(typeof(IFormattingLoggerFactory)), Shared] -internal sealed class RemoteFormattingLoggerFactory : FormattingLoggerFactory -{ -} diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteFormattingService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteFormattingService.cs index 67c5db13e78bc..e4613e66d5ee8 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteFormattingService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteFormattingService.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Threading; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Remote; @@ -94,8 +95,13 @@ private async ValueTask> GetOnTypeFormattingEditsAsyn return await _formattingService.GetHtmlOnTypeFormattingChangesAsync(context, htmlChanges, options, hostDocumentIndex, triggerCharacter[0], cancellationToken).ConfigureAwait(false); } + if (!DocumentMappingService.TryMapToCSharpDocumentLinePosition(codeDocument, hostDocumentIndex, out _, out _, out var inDeclDocument)) + { + return []; + } + Debug.Assert(triggerCharacterKind is RazorLanguageKind.CSharp); - return await _formattingService.GetCSharpOnTypeFormattingChangesAsync(context, options, hostDocumentIndex, triggerCharacter[0], cancellationToken).ConfigureAwait(false); + return await _formattingService.GetCSharpOnTypeFormattingChangesAsync(context, options, hostDocumentIndex, triggerCharacter[0], inDeclDocument, cancellationToken).ConfigureAwait(false); } public ValueTask GetOnTypeFormattingTriggerKindAsync( diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteRazorFormattingService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteRazorFormattingService.cs deleted file mode 100644 index 77652b2a563d0..0000000000000 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/RemoteRazorFormattingService.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Composition; -using Microsoft.CodeAnalysis.Razor.DocumentMapping; -using Microsoft.CodeAnalysis.Razor.Formatting; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.CodeAnalysis.Razor.Workspaces; - -namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; - -[Export(typeof(IRazorFormattingService)), Shared] -[method: ImportingConstructor] -internal sealed class RemoteRazorFormattingService(IDocumentMappingService documentMappingService, IRazorEditService razorEditService, IHostServicesProvider hostServicesProvider, IFormattingLoggerFactory formattingLoggerFactory, ILoggerFactory loggerFactory) - : RazorFormattingService(documentMappingService, razorEditService, hostServicesProvider, formattingLoggerFactory, loggerFactory) -{ -} diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/SnippetFormatter.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/SnippetFormatter.cs similarity index 97% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/SnippetFormatter.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/SnippetFormatter.cs index 46bbe91ba97cf..a7bfd152a5edd 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/SnippetFormatter.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Formatting/SnippetFormatter.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.Text; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal static class SnippetFormatter { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/DefinitionService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/DefinitionService.cs index 5087e7764274e..877eaa9a6cb09 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/DefinitionService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/DefinitionService.cs @@ -2,10 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Composition; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.DocumentMapping; -using Microsoft.CodeAnalysis.Razor.GoToDefinition; using Microsoft.CodeAnalysis.Razor.Logging; +using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Workspaces; +using Microsoft.CodeAnalysis.Text; +using CSharpSyntaxKind = Microsoft.CodeAnalysis.CSharp.SyntaxKind; namespace Microsoft.CodeAnalysis.Remote.Razor.GoToDefinition; @@ -13,9 +21,179 @@ namespace Microsoft.CodeAnalysis.Remote.Razor.GoToDefinition; [method: ImportingConstructor] internal sealed class DefinitionService( IRazorComponentSearchEngine componentSearchEngine, + ITagHelperSearchEngine? tagHelperSearchEngine, IDocumentMappingService documentMappingService, - ITagHelperSearchEngine tagHelperSearchEngine, - ILoggerFactory loggerFactory) - : AbstractDefinitionService(componentSearchEngine, tagHelperSearchEngine, documentMappingService, loggerFactory.GetOrCreateLogger()) + ILoggerFactory loggerFactory) : IDefinitionService { + private readonly IRazorComponentSearchEngine _componentSearchEngine = componentSearchEngine; + private readonly ITagHelperSearchEngine? _tagHelperSearchEngine = tagHelperSearchEngine; + private readonly IDocumentMappingService _documentMappingService = documentMappingService; + private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); + + public async Task GetDefinitionAsync( + IDocumentSnapshot documentSnapshot, + DocumentPositionInfo positionInfo, + ISolutionQueryOperations solutionQueryOperations, + bool includeMvcTagHelpers, + CancellationToken cancellationToken) + { + if (!includeMvcTagHelpers && !documentSnapshot.FileKind.IsComponent()) + { + _logger.LogInformation($"'{documentSnapshot.FileKind}' is not a component type."); + return null; + } + + var codeDocument = await documentSnapshot.GetGeneratedOutputAsync(cancellationToken).ConfigureAwait(false); + + if (!RazorComponentDefinitionHelpers.TryGetBoundTagHelpers(codeDocument, positionInfo.HostDocumentIndex, _logger, out var boundTagHelperResults)) + { + _logger.LogInformation($"Could not retrieve bound tag helper information."); + return null; + } + + if (includeMvcTagHelpers) + { + Debug.Assert(_tagHelperSearchEngine is not null, "If includeMvcTagHelpers is true, _tagHelperSearchEngine must not be null."); + + var tagHelperLocations = await _tagHelperSearchEngine.TryLocateTagHelperDefinitionsAsync(boundTagHelperResults, documentSnapshot, solutionQueryOperations, cancellationToken).ConfigureAwait(false); + if (tagHelperLocations is { Length: > 0 }) + { + return tagHelperLocations; + } + } + + // For Razor components, there can only ever be one tag helper result + var (boundTagHelper, boundAttribute) = boundTagHelperResults[0]; + + var componentDocument = await _componentSearchEngine + .TryLocateComponentAsync(boundTagHelper, solutionQueryOperations, cancellationToken) + .ConfigureAwait(false); + + if (componentDocument is null) + { + _logger.LogInformation($"Could not locate component document."); + return null; + } + + var componentFilePath = componentDocument.FilePath; + + _logger.LogInformation($"Definition found at file path: {componentFilePath}"); + + var range = await GetNavigateRangeAsync(componentDocument, boundAttribute, cancellationToken).ConfigureAwait(false); + + return [LspFactory.CreateLocation(componentFilePath, range)]; + } + + private async Task GetNavigateRangeAsync(IDocumentSnapshot documentSnapshot, BoundAttributeDescriptor? attributeDescriptor, CancellationToken cancellationToken) + { + if (attributeDescriptor is not null) + { + _logger.LogInformation($"Attempting to get definition from an attribute directly."); + + var range = await RazorComponentDefinitionHelpers + .TryGetPropertyRangeAsync(documentSnapshot, attributeDescriptor.PropertyName, _documentMappingService, _logger, cancellationToken) + .ConfigureAwait(false); + + if (range is not null) + { + return range; + } + } + + // When navigating from a start or end tag, we just take the user to the top of the file. + // If we were trying to navigate to a property, and we couldn't find it, we can at least take + // them to the file for the component. If the property was defined in a partial class they can + // at least then press F7 to go there. + return LspFactory.DefaultRange; + } + + public async Task TryGetDefinitionFromStringLiteralAsync( + IDocumentSnapshot documentSnapshot, + Position position, + bool inDeclDocument, + CancellationToken cancellationToken) + { + _logger.LogDebug($"Attempting to get definition from string literal at position {position}."); + + // Get the C# syntax tree to analyze the string literal + var syntaxTree = await documentSnapshot.GetCSharpSyntaxTreeAsync(inDeclDocument, cancellationToken).ConfigureAwait(false); + var root = await syntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + var sourceText = await syntaxTree.GetTextAsync(cancellationToken).ConfigureAwait(false); + + // Convert position to absolute index + var absoluteIndex = sourceText.GetRequiredAbsoluteIndex(position); + + // Find the token at the current position + var token = root.FindToken(absoluteIndex); + + // Check if we're in a string literal + if (token.IsKind(CSharpSyntaxKind.StringLiteralToken)) + { + var literalText = token.ValueText; + _logger.LogDebug($"Found string literal: {literalText}"); + + // Try to resolve the file path + if (TryResolveFilePath(documentSnapshot, literalText, out var resolvedPath)) + { + _logger.LogDebug($"Resolved file path: {resolvedPath}"); + return [LspFactory.CreateLocation(resolvedPath, LspFactory.DefaultRange)]; + } + } + + return null; + } + + private bool TryResolveFilePath(IDocumentSnapshot documentSnapshot, string filePath, out string resolvedPath) + { + resolvedPath = string.Empty; + + if (string.IsNullOrWhiteSpace(filePath)) + { + return false; + } + + // Only process if it looks like a Razor file path + if (!filePath.IsRazorFilePath()) + { + return false; + } + + var project = documentSnapshot.Project; + + // Handle tilde paths (~/ or ~\) - these are relative to the project root + if (filePath is ['~', '/' or '\\', ..]) + { + var projectDirectory = Path.GetDirectoryName(project.FilePath); + if (projectDirectory is null) + { + return false; + } + + // Remove the tilde and normalize path separators + var relativePath = filePath.Substring(2).Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); + var candidatePath = Path.GetFullPath(Path.Combine(projectDirectory, relativePath)); + + if (project.ContainsDocument(candidatePath)) + { + resolvedPath = candidatePath; + return true; + } + } + + // Handle relative paths - relative to the current document + var currentDocumentDirectory = Path.GetDirectoryName(documentSnapshot.FilePath); + if (currentDocumentDirectory is not null) + { + var normalizedPath = filePath.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); + var candidatePath = Path.GetFullPath(Path.Combine(currentDocumentDirectory, normalizedPath)); + + if (project.ContainsDocument(candidatePath)) + { + resolvedPath = candidatePath; + return true; + } + } + + return false; + } } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/IDefinitionService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/IDefinitionService.cs similarity index 90% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/IDefinitionService.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/IDefinitionService.cs index 3fcd2ed6fbf8d..25c993f151153 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/IDefinitionService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/IDefinitionService.cs @@ -6,7 +6,7 @@ using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.ProjectSystem; -namespace Microsoft.CodeAnalysis.Razor.GoToDefinition; +namespace Microsoft.CodeAnalysis.Remote.Razor.GoToDefinition; /// /// Go to Definition support for Razor tag helpers (Mvc tag helpers and components). @@ -23,5 +23,6 @@ internal interface IDefinitionService Task TryGetDefinitionFromStringLiteralAsync( IDocumentSnapshot documentSnapshot, Position position, + bool inDeclDocument, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/RazorComponentDefinitionHelpers.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/RazorComponentDefinitionHelpers.cs similarity index 92% rename from src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/RazorComponentDefinitionHelpers.cs rename to src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/RazorComponentDefinitionHelpers.cs index d7d55e00c24a7..acb3b7227512e 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/GoToDefinition/RazorComponentDefinitionHelpers.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/RazorComponentDefinitionHelpers.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; @@ -19,9 +19,7 @@ using RazorSyntaxNode = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxNode; using RazorSyntaxToken = Microsoft.AspNetCore.Razor.Language.Syntax.SyntaxToken; -namespace Microsoft.CodeAnalysis.Razor.GoToDefinition; - -internal sealed record BoundTagHelperResult(TagHelperDescriptor ElementDescriptor, BoundAttributeDescriptor? AttributeDescriptor); +namespace Microsoft.CodeAnalysis.Remote.Razor.GoToDefinition; internal static class RazorComponentDefinitionHelpers { @@ -171,17 +169,22 @@ static bool TryGetTagName(RazorSyntaxNode node, out RazorSyntaxToken tagName) // will error, but allowing them to Go To Def on that property regardless, actually helps // them fix the error. - var csharpSyntaxTree = await documentSnapshot.GetCSharpSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var root = await csharpSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var codeDocument = await documentSnapshot.GetGeneratedOutputAsync(cancellationToken).ConfigureAwait(false); + // By definition, properties will be part of the declaration document when it exists. + // Legacy documents don't have a declaration document, so they fall back to the implementation document. + var csharpDocument = codeDocument.GetCSharpDocument(declarationDocument: true) + ?? codeDocument.GetRequiredCSharpDocument(declarationDocument: false); + + var csharpSyntaxTree = await documentSnapshot.GetCSharpSyntaxTreeAsync(csharpDocument.IsDeclarationDocument, cancellationToken).ConfigureAwait(false); + var root = await csharpSyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); + if (root.TryGetClassDeclaration(out var classDeclaration)) { var property = classDeclaration .Members .OfType() - .Where(p => p.Identifier.ValueText.Equals(propertyName, StringComparison.Ordinal)) - .FirstOrDefault(); + .FirstOrDefault(p => p.Identifier.ValueText.Equals(propertyName, StringComparison.Ordinal)); if (property is null) { @@ -190,7 +193,6 @@ static bool TryGetTagName(RazorSyntaxNode node, out RazorSyntaxToken tagName) return null; } - var csharpDocument = codeDocument.GetRequiredImplCSharpDocument(); var range = csharpDocument.Text.GetRange(property.Identifier.Span); if (documentMappingService.TryMapToRazorDocumentRange(csharpDocument, range, out var originalRange)) { diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/RemoteGoToDefinitionService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/RemoteGoToDefinitionService.cs index 9e1a7a8de1c1b..739581f87eb4d 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/RemoteGoToDefinitionService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/GoToDefinition/RemoteGoToDefinitionService.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; @@ -9,11 +10,11 @@ using Microsoft.CodeAnalysis.MetadataAsSource; using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Razor; -using Microsoft.CodeAnalysis.Razor.GoToDefinition; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Remote.Razor.DocumentMapping; +using Microsoft.CodeAnalysis.Remote.Razor.GoToDefinition; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; using static Microsoft.CodeAnalysis.Razor.Remote.RemoteResponse; @@ -100,6 +101,7 @@ protected override IRemoteGoToDefinitionService CreateService(in ServiceArgs arg var stringLiteralLocations = await _definitionService.TryGetDefinitionFromStringLiteralAsync( context.Snapshot, positionInfo.Position, + positionInfo.InDeclDocument, cancellationToken) .ConfigureAwait(false); @@ -117,7 +119,7 @@ protected override IRemoteGoToDefinitionService CreateService(in ServiceArgs arg // Finally, call into C#. var generatedDocument = await context.Snapshot - .GetGeneratedDocumentAsync(cancellationToken) + .GetGeneratedDocumentAsync(positionInfo.InDeclDocument, cancellationToken) .ConfigureAwait(false); var locations = await GetDefinitionsAsync( @@ -135,6 +137,7 @@ protected override IRemoteGoToDefinitionService CreateService(in ServiceArgs arg // Map the C# locations back to the Razor file. using var mappedLocations = new PooledArrayBuilder(locations.Length); + using var _ = HashSetPool<(Uri DocumentUri, LinePositionSpan Range)>.GetPooledObject(out var seenLocations); foreach (var location in locations) { @@ -144,6 +147,12 @@ protected override IRemoteGoToDefinitionService CreateService(in ServiceArgs arg .MapToHostDocumentUriAndRangeAsync(context.Snapshot, uri, range.ToLinePositionSpan(), cancellationToken) .ConfigureAwait(false); + // Impl and decl generated documents can both contain a generated class declaration that maps to the same Razor location. + if (!seenLocations.Add((mappedDocumentUri, mappedRange))) + { + continue; + } + var mappedLocation = LspFactory.CreateLocation(mappedDocumentUri.CreateDocumentUriFromSystemUri(), mappedRange); mappedLocations.Add(mappedLocation); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs index 1c1a61de6cf2e..ee58a72fa5061 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlayHints/RemoteInlayHintService.cs @@ -42,94 +42,116 @@ protected override IRemoteInlayHintService CreateService(in ServiceArgs args) private async ValueTask GetInlayHintsAsync(RemoteDocumentContext context, InlayHintParams inlayHintParams, bool displayAllOverride, CancellationToken cancellationToken) { var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false); - var csharpDocument = codeDocument.GetRequiredImplCSharpDocument(); var span = inlayHintParams.Range.ToLinePositionSpan(); cancellationToken.ThrowIfCancellationRequested(); - var overlappingSpans = DocumentMappingService.GetCSharpSpansOverlappingRazorSpan(csharpDocument, span); + using var inlayHintsBuilder = new PooledArrayBuilder(); + var sawCSharpSpan = false; + var seenHints = new HashSet<(LinePosition Position, string? Label)>(); + + await AddInlayHintsAsync(codeDocument.GetRequiredCSharpDocument(declarationDocument: false), cancellationToken).ConfigureAwait(false); - if (overlappingSpans.IsEmpty) + if (codeDocument.GetCSharpDocument(declarationDocument: true) is { } declCSharpDocument) { - // There's no C# in the range. - return null; + await AddInlayHintsAsync(declCSharpDocument, cancellationToken).ConfigureAwait(false); } - var generatedDocument = await context.Snapshot - .GetGeneratedDocumentAsync(cancellationToken) - .ConfigureAwait(false); - - var textDocument = inlayHintParams.TextDocument.WithUri(generatedDocument.GetURI()); - - using var inlayHintsBuilder = new PooledArrayBuilder(); - var razorSourceText = codeDocument.Source.Text; - var csharpSourceText = codeDocument.GetCSharpSourceText(); - var root = codeDocument.GetRequiredSyntaxRoot(); + return !sawCSharpSpan + ? null + : inlayHintsBuilder.ToArray(); - foreach (var csharpSpan in overlappingSpans) + async ValueTask AddInlayHintsAsync(RazorCSharpDocument csharpDocument, CancellationToken cancellationToken) { - var range = csharpSpan.ToRange(); - var hints = await GetInlayHintsAsync(generatedDocument, textDocument, range, displayAllOverride, _cacheProvider.GetCache(), cancellationToken).ConfigureAwait(false); - if (hints is null) + var overlappingSpans = DocumentMappingService.GetCSharpSpansOverlappingRazorSpan(csharpDocument, span); + + if (overlappingSpans.IsEmpty) { - continue; + // There's no C# in the range for this generated document. + return; } - foreach (var hint in hints) - { - if (csharpSourceText.TryGetAbsoluteIndex(hint.Position.ToLinePosition(), out var absoluteIndex) && - DocumentMappingService.TryMapToRazorDocumentPosition(csharpDocument, absoluteIndex, out var hostDocumentPosition, out var hostDocumentIndex)) - { - // We know this C# maps to Razor, but does it map to Razor that we like? + sawCSharpSpan = true; - // We don't want inlay hints in tag helper attributes - var node = root.FindInnermostNode(hostDocumentIndex); - if (node?.FirstAncestorOrSelf() is not null) - { - continue; - } + var inDeclDocument = csharpDocument.IsDeclarationDocument; + var generatedDocument = await context.Snapshot + .GetGeneratedDocumentAsync(inDeclDocument, cancellationToken) + .ConfigureAwait(false); - // Inlay hints in directives are okay, eg '@attribute [Description(description: "Desc")]', but if the hint is going to be - // at the very start of the directive, we want to strip any TextEdit as it would make for an invalid document. eg: '// @page template: "/"' - if (node?.SpanStart == hostDocumentIndex && - node.FirstAncestorOrSelf(static n => n.IsDirectiveKind(DirectiveKind.SingleLine)) is not null) - { - hint.TextEdits = null; - } + var textDocument = inlayHintParams.TextDocument.WithUri(generatedDocument.GetURI()); - if (hint.TextEdits is not null) - { - var changes = hint.TextEdits.SelectAsArray(csharpSourceText.GetTextChange); - var textChanges = await _razorEditService.MapCSharpEditsAsync(changes, context.Snapshot, cancellationToken).ConfigureAwait(false); + var razorSourceText = codeDocument.Source.Text; + var csharpSourceText = csharpDocument.Text; + var root = codeDocument.GetRequiredSyntaxRoot(); - var textEdits = textChanges.SelectAsArray(razorSourceText.GetTextEdit); + foreach (var csharpSpan in overlappingSpans) + { + var range = csharpSpan.ToRange(); + var hints = await GetInlayHintsAsync(generatedDocument, textDocument, range, displayAllOverride, _cacheProvider.GetCache(), cancellationToken).ConfigureAwait(false); + if (hints is null) + { + continue; + } - hint.TextEdits = ImmutableCollectionsMarshal.AsArray(textEdits); + foreach (var hint in hints) + { + if (csharpSourceText.TryGetAbsoluteIndex(hint.Position.ToLinePosition(), out var absoluteIndex) && + DocumentMappingService.TryMapToRazorDocumentPosition(csharpDocument, absoluteIndex, out var hostDocumentPosition, out var hostDocumentIndex)) + { + // We know this C# maps to Razor, but does it map to Razor that we like? + + // We don't want inlay hints in tag helper attributes + var node = root.FindInnermostNode(hostDocumentIndex); + if (node?.FirstAncestorOrSelf() is not null) + { + continue; + } + + // Inlay hints in directives are okay, eg '@attribute [Description(description: "Desc")]', but if the hint is going to be + // at the very start of the directive, we want to strip any TextEdit as it would make for an invalid document. eg: '// @page template: "/"' + if (node?.SpanStart == hostDocumentIndex && + node.FirstAncestorOrSelf(static n => n.IsDirectiveKind(DirectiveKind.SingleLine)) is not null) + { + hint.TextEdits = null; + } + + if (hint.TextEdits is not null) + { + var changes = hint.TextEdits.SelectAsArray(csharpSourceText.GetTextChange); + var textChanges = await _razorEditService.MapCSharpEditsAsync(changes, inDeclDocument, context.Snapshot, cancellationToken).ConfigureAwait(false); + + var textEdits = textChanges.SelectAsArray(razorSourceText.GetTextEdit); + + hint.TextEdits = ImmutableCollectionsMarshal.AsArray(textEdits); + } + + if (!seenHints.Add((hostDocumentPosition, hint.Label.First))) + { + continue; + } + + hint.Data = new InlayHintDataWrapper(inlayHintParams.TextDocument, hint.Data, hint.Position, inDeclDocument); + hint.Position = hostDocumentPosition.ToPosition(); + + inlayHintsBuilder.Add(hint); } - - hint.Data = new InlayHintDataWrapper(inlayHintParams.TextDocument, hint.Data, hint.Position); - hint.Position = hostDocumentPosition.ToPosition(); - - inlayHintsBuilder.Add(hint); } } } - - return inlayHintsBuilder.ToArray(); } - public ValueTask ResolveHintAsync(JsonSerializableRazorSolutionWrapper solutionInfo, JsonSerializableDocumentId razorDocumentId, InlayHint inlayHint, CancellationToken cancellationToken) + public ValueTask ResolveHintAsync(JsonSerializableRazorSolutionWrapper solutionInfo, JsonSerializableDocumentId razorDocumentId, InlayHint inlayHint, bool inDeclDocument, CancellationToken cancellationToken) => RunServiceAsync( solutionInfo, razorDocumentId, - context => ResolveInlayHintAsync(context, inlayHint, cancellationToken), + context => ResolveInlayHintAsync(context, inlayHint, inDeclDocument, cancellationToken), cancellationToken); - private async ValueTask ResolveInlayHintAsync(RemoteDocumentContext context, InlayHint inlayHint, CancellationToken cancellationToken) + private async ValueTask ResolveInlayHintAsync(RemoteDocumentContext context, InlayHint inlayHint, bool inDeclDocument, CancellationToken cancellationToken) { var generatedDocument = await context.Snapshot - .GetGeneratedDocumentAsync(cancellationToken) + .GetGeneratedDocumentAsync(inDeclDocument, cancellationToken) .ConfigureAwait(false); return await ResolveInlayHintAsync(generatedDocument, inlayHint, _cacheProvider.GetCache(), cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlineCompletion/RemoteInlineCompletionService.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlineCompletion/RemoteInlineCompletionService.cs index 191b91abb46b7..0e38f6f9fd8e7 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlineCompletion/RemoteInlineCompletionService.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/InlineCompletion/RemoteInlineCompletionService.cs @@ -7,6 +7,7 @@ using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperSearchEngine.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperSearchEngine.cs index 46e541fa388c0..80f6df393f3e4 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperSearchEngine.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperSearchEngine.cs @@ -10,7 +10,6 @@ using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.LanguageServer; -using Microsoft.CodeAnalysis.Razor.GoToDefinition; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/SR.resx b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/SR.resx index 3e94cca94ac11..c72fb5e4cac05 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/SR.resx +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/SR.resx @@ -202,4 +202,25 @@ Unknown mapping behavior + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + A format operation is being abandoned because it would add or delete non-whitespace content. + + + Diagnostics after: + + + Diagnostics before: + + + Edit at {0} adds the non-whitespace content '{1}'. + + + Edit at {0} deletes the non-whitespace content '{1}'. + \ No newline at end of file diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.cs.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.cs.xlf index e4a0baa95c758..062fd81addef6 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.cs.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.cs.xlf @@ -27,6 +27,16 @@ Vytvořit komponentu ze značky + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. Dokument nepatří do tohoto projektu. @@ -37,6 +47,16 @@ Dokument není dokument Razor. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Extrahovat blok do kódu na pozadí @@ -52,6 +72,21 @@ Extrahovat do {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Generovat asynchronní obslužnou rutinu události {0} diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.de.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.de.xlf index ccbf277a59349..a47dd114967d6 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.de.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.de.xlf @@ -27,6 +27,16 @@ Komponente aus Tag erstellen + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. Das Dokument gehört nicht zu diesem Projekt. @@ -37,6 +47,16 @@ Das Dokument ist kein Razor-Dokument. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Block auf CodeBehind extrahieren @@ -52,6 +72,21 @@ In {0}.css extrahieren + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Asynchronen Ereignishandler "{0}" generieren diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.es.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.es.xlf index 88d39e2d3b26b..8d9ecedca16a6 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.es.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.es.xlf @@ -27,6 +27,16 @@ Crear un componente a partir de la etiqueta + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. El documento no pertenece a este proyecto. @@ -37,6 +47,16 @@ El documento no es un documento de Razor. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Extraer el bloque al código subyacente @@ -52,6 +72,21 @@ Extraer a {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Generar controlador de eventos asincrónicos ''{0}'' diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.fr.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.fr.xlf index 8af9f9aee5d21..ebc92064761f0 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.fr.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.fr.xlf @@ -27,6 +27,16 @@ Créer un composant à partir de la balise + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. Le document n’appartient pas à ce projet. @@ -37,6 +47,16 @@ Le document n’est pas un document Razor. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Extraire le bloc vers le code-behind @@ -52,6 +72,21 @@ Extraire vers {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Générer le gestionnaire d’événements asynchrone « {0} » diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.it.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.it.xlf index 79f12683f6302..53b3b393c4d72 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.it.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.it.xlf @@ -27,6 +27,16 @@ Crea componente da tag + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. Il documento non appartiene a questo progetto. @@ -37,6 +47,16 @@ Il documento non è un documento Razor. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Estrai il blocco in code-behind @@ -52,6 +72,21 @@ Estrarre in {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Genera gestore dell'evento '{0}' asincrono diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ja.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ja.xlf index 0a5478bfed90f..e8cfabcef68bf 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ja.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ja.xlf @@ -27,6 +27,16 @@ タグからコンポーネントを作成する + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. ドキュメントはこのプロジェクトに属していません。 @@ -37,6 +47,16 @@ ドキュメントは Razor ドキュメントではありません。 + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind ブロック抽出から分離コード @@ -52,6 +72,21 @@ {0}.css に抽出する + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' 非同期イベント ハンドラー '{0}' の生成 diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ko.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ko.xlf index 5a7b6d4c58a3b..21d4bd3c0747d 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ko.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ko.xlf @@ -27,6 +27,16 @@ 태그에서 구성 요소 만들기 + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. 문서가 이 프로젝트에 속하지 않습니다. @@ -37,6 +47,16 @@ 문서가 Razor 문서가 아닙니다. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind 코드 숨김에 블록 추출 @@ -52,6 +72,21 @@ {0}.css로 추출 + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' 비동기 이벤트 처리기 '{0}' 생성 diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pl.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pl.xlf index 782cb2d68dd36..72f50e7138c82 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pl.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pl.xlf @@ -27,6 +27,16 @@ Utwórz składnik z tagu + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. Dokument nie należy do tego projektu. @@ -37,6 +47,16 @@ Dokument nie jest dokumentem Razor. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Wyodrębnij blok do kodu znajdującego się poza @@ -52,6 +72,21 @@ Wyodrębnij do {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Generuj asynchroniczny program obsługi zdarzeń „{0}” diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pt-BR.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pt-BR.xlf index 6cc396831814a..c9005be1999f9 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pt-BR.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.pt-BR.xlf @@ -27,6 +27,16 @@ Criar componente a partir da marca + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. O documento não pertence a esse projeto. @@ -37,6 +47,16 @@ O documento não é um documento Razor. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Extrair o bloco para codificar atrás @@ -52,6 +72,21 @@ Extrair para {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Gerar Manipulador de Eventos Assíncronos '{0}' diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ru.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ru.xlf index 148fea685881b..25298be41cffb 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ru.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.ru.xlf @@ -27,6 +27,16 @@ Создание компонента из тега + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. Документ не принадлежит этому проекту. @@ -37,6 +47,16 @@ Документ не является документом Razor. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Извлечь блок в код программной части @@ -52,6 +72,21 @@ Извлечь в {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' Создать обработчик асинхронных событий "{0}" diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.tr.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.tr.xlf index 6296c5412974b..7880792f1f114 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.tr.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.tr.xlf @@ -27,6 +27,16 @@ Etiketten bileşen oluştur + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. Belge bu projeye ait değil. @@ -37,6 +47,16 @@ Belge Razor belgesi değil. + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind Bloğu arkadaki koda ayıkla @@ -52,6 +72,21 @@ {0}.css'a ayıkla + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' '{0}' Asenkron Olay İşleyicisini Oluştur diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hans.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hans.xlf index a5a9386853c20..e619eaa244539 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hans.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hans.xlf @@ -27,6 +27,16 @@ 从标记创建组件 + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. 文档不属于此项目。 @@ -37,6 +47,16 @@ 文档不是 Razor 文档。 + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind 将块提取到代码隐藏中 @@ -52,6 +72,21 @@ 提取到 {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' 生成异步事件处理程序“{0}” diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hant.xlf b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hant.xlf index d8bfd15074d5c..4a67a8ef7fe97 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hant.xlf +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Resources/xlf/SR.zh-Hant.xlf @@ -27,6 +27,16 @@ 從標籤建立元件 + + Diagnostics after: + Diagnostics after: + + + + Diagnostics before: + Diagnostics before: + + Document does not belong to this project. 文件不屬於此專案。 @@ -37,6 +47,16 @@ 文件並非 Razor 文件。 + + Edit at {0} adds the non-whitespace content '{1}'. + Edit at {0} adds the non-whitespace content '{1}'. + + + + Edit at {0} deletes the non-whitespace content '{1}'. + Edit at {0} deletes the non-whitespace content '{1}'. + + Extract block to code behind 擷取區塊以在後方編碼 @@ -52,6 +72,21 @@ 擷取為 {0}.css + + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + A format operation is being abandoned because it would introduce or remove one of more diagnostics. + + + + A format operation is being abandoned because it would add or delete non-whitespace content. + A format operation is being abandoned because it would add or delete non-whitespace content. + + + + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + Formatting error. Abandoning further work to not corrupt the file, please report this issue. See: https://aka.ms/razor-formatting-issue + + Generate Async Event Handler '{0}' 產生非同步事件處理常式 '{0}' diff --git a/src/Razor/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostWrapWithTagEndpoint.cs b/src/Razor/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostWrapWithTagEndpoint.cs index 93a787cfbf46c..51df3c32acbec 100644 --- a/src/Razor/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostWrapWithTagEndpoint.cs +++ b/src/Razor/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostWrapWithTagEndpoint.cs @@ -8,10 +8,9 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Razor.CohostingShared; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Cohost; -using Microsoft.CodeAnalysis.Razor.Formatting; +using Microsoft.CodeAnalysis.Razor.CohostingShared; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Remote; @@ -92,7 +91,7 @@ internal sealed class CohostWrapWithTagEndpoint( } var htmlSourceText = htmlDocument.Snapshot.AsText(); - htmlResponse.TextEdits = FormattingUtilities.FixHtmlTextEdits(htmlSourceText, edits); + htmlResponse.TextEdits = htmlSourceText.FixHtmlTextEdits(edits); } return htmlResponse; diff --git a/src/Razor/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Formatting/TestFormattingLoggerFactory.cs b/src/Razor/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Cohosting/Formatting/TestFormattingLoggerFactory.cs similarity index 97% rename from src/Razor/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Formatting/TestFormattingLoggerFactory.cs rename to src/Razor/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Cohosting/Formatting/TestFormattingLoggerFactory.cs index c7aca59f8cdda..16ee538b11797 100644 --- a/src/Razor/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Formatting/TestFormattingLoggerFactory.cs +++ b/src/Razor/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Cohosting/Formatting/TestFormattingLoggerFactory.cs @@ -8,7 +8,7 @@ using Xunit; using Xunit.Abstractions; -namespace Microsoft.CodeAnalysis.Razor.Formatting; +namespace Microsoft.CodeAnalysis.Remote.Razor.Formatting; internal class TestFormattingLoggerFactory(ITestOutputHelper testOutputHelper) : IFormattingLoggerFactory { diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs index 4a3472f144d22..6aa2650633d38 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs @@ -207,7 +207,7 @@ public Task Section_Invalid() """, fileKind: RazorFileKind.Legacy); - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] public Task CSharpCodeInCodeBlocks() => VerifyFoldingRangesAsync("""
@@ -222,7 +222,23 @@ public void M() {{|implementation: }|] """); - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] + public Task CSharpCodeInCodeBlocks_Legacy() + => VerifyFoldingRangesAsync(""" +
+ Hello @_name +
+ + @functions {[| + private string _name = "Dave"; + + public void M() {{|implementation: + }|} + }|] + """, + fileKind: RazorFileKind.Legacy); + + [Fact] public Task HtmlAndCSharp() => VerifyFoldingRangesAsync("""
{|html: @@ -241,7 +257,27 @@ public void M() {{|implementation: }|] """); - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] + public Task HtmlAndCSharp_Legacy() + => VerifyFoldingRangesAsync(""" +
{|html: + Hello @_name + +
{|html: + Nests aren't just for birds! +
|} +
|} + + @functions {[| + private string _name = "Dave"; + + public void M() {{|implementation: + }|} + }|] + """, + fileKind: RazorFileKind.Legacy); + + [Fact] public Task CSharp_LineFoldingOnly() => VerifyFoldingRangesAsync("""
{|html: @@ -257,9 +293,26 @@ class C { public void M1() {{|implementation: """, lineFoldingOnly: true); - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] + public Task CSharp_LineFoldingOnly_Legacy() + => VerifyFoldingRangesAsync(""" +
{|html: + Hello @_name +
|} + + @functions {[| + class C { public void M1() {{|implementation: + var x = 1; + |} } + } + }|] + """, + fileKind: RazorFileKind.Legacy, + lineFoldingOnly: true); + + [Fact] public Task CSharp_NotLineFoldingOnly() - => VerifyFoldingRangesAsync(""" + => VerifyFoldingRangesAsync("""
{|html: Hello @_name
|} @@ -271,9 +324,26 @@ class C { public void M1() {[| }|] }|] """, - lineFoldingOnly: false); + lineFoldingOnly: false); - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] + public Task CSharp_NotLineFoldingOnly_Legacy() + => VerifyFoldingRangesAsync(""" +
{|html: + Hello @_name +
|} + + @functions {[| + class C { public void M1() {[| + var x = 1; + } + }|] + }|] + """, + fileKind: RazorFileKind.Legacy, + lineFoldingOnly: false); + + [Fact] public Task IfElseStatements_LineFoldingOnly() => VerifyFoldingRangesAsync("""
@@ -303,9 +373,40 @@ void M(){|implementation: """, lineFoldingOnly: true); - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] + public Task IfElseStatements_LineFoldingOnly_Legacy() + => VerifyFoldingRangesAsync(""" +
+ @if (true) {[| +
+ Hello World +
+ } else {[| +
+ Goodbye World +
+ |] } + |] } +
+ + @functions[| + { + void M(){|implementation: + { + if (true) {[| + |] var x = 1; + } else {[| + var y = 2; + |] } + |} } + }|] + """, + fileKind: RazorFileKind.Legacy, + lineFoldingOnly: true); + + [Fact] public Task CSharpExpressionBodiedMethods() - => VerifyFoldingRangesAsync(""" + => VerifyFoldingRangesAsync("""

hello!

@code {[| diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostGoToDefinitionEndpointTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostGoToDefinitionEndpointTest.cs index bff56cf7afc38..f67ac1f86d42d 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostGoToDefinitionEndpointTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostGoToDefinitionEndpointTest.cs @@ -39,7 +39,7 @@ public async Task CSharp_Method() await VerifyGoToDefinitionAsync(input); } - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] public async Task CSharp_Local() { var input = """ @@ -60,7 +60,7 @@ string GetX() await VerifyGoToDefinitionAsync(input); } - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] public async Task CSharp_MetadataReference() { var input = """ @@ -159,7 +159,7 @@ public async Task Component() Assert.Equal(range, location.Range); } - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] public async Task Component_FromCSharp() { TestCode input = """ diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostInlayHintEndpointTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostInlayHintEndpointTest.cs index 131ac2b39e846..88f9c1a36a36e 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostInlayHintEndpointTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostInlayHintEndpointTest.cs @@ -7,6 +7,7 @@ using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; +using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.LanguageServer; using Microsoft.CodeAnalysis.Testing; @@ -20,7 +21,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; public class CohostInlayHintEndpointTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper) { - [RoslynConditionalFact(typeof(IsEnglishLocal), AlwaysSkip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [RoslynConditionalFact(typeof(IsEnglishLocal))] public Task InlayHints() => VerifyInlayHintsAsync( input: """ @@ -62,7 +63,50 @@ private void M(string thisIsMyString) """); - [RoslynConditionalFact(typeof(IsEnglishLocal), AlwaysSkip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [RoslynConditionalFact(typeof(IsEnglishLocal))] + public Task InlayHints_Legacy() + => VerifyInlayHintsAsync( + input: """ + +
+ + @functions { + private void M(string thisIsMyString) + { + var {|int:x|} = 5; + + var {|string:y|} = "Hello"; + + M({|thisIsMyString:"Hello"|}); + } + } + + """, + toolTipMap: new Dictionary + { + { "int", "struct System.Int32" }, + { "string", "class System.String" }, + { "thisIsMyString", "(parameter) string thisIsMyStr" } + }, + output: """ + +
+ + @functions { + private void M(string thisIsMyString) + { + int x = 5; + + string y = "Hello"; + + M(thisIsMyString: "Hello"); + } + } + + """, + fileKind: RazorFileKind.Legacy); + + [RoslynConditionalFact(typeof(IsEnglishLocal))] public Task InlayHints_DisplayAllOverride() => VerifyInlayHintsAsync( input: """ @@ -105,6 +149,121 @@ private void M(string thisIsMyString) """, displayAllOverride: true); + [RoslynConditionalFact(typeof(IsEnglishLocal))] + public Task InlayHints_DisplayAllOverride_Legacy() + => VerifyInlayHintsAsync( + input: """ + +
+ + @functions { + private void M(string thisIsMyString) + { + {|int:var|} x = 5; + + {|string:var|} y = "Hello"; + + M({|thisIsMyString:"Hello"|}); + } + } + + """, + toolTipMap: new Dictionary + { + { "int", "struct System.Int32" }, + { "string", "class System.String" }, + { "thisIsMyString", "(parameter) string thisIsMyStr" } + }, + output: """ + +
+ + @functions { + private void M(string thisIsMyString) + { + int x = 5; + + string y = "Hello"; + + M(thisIsMyString: "Hello"); + } + } + + """, + displayAllOverride: true, + fileKind: RazorFileKind.Legacy); + + [RoslynConditionalFact(typeof(IsEnglishLocal))] + public Task InlayHints_ExplicitStatementAndCodeBlock() + => VerifyInlayHintsAsync( + input: """ +
+ @{ + var {|string:x|} = "asdf"; + } + + @code { + private void M() + { + var {|int:y|} = 1; + } + } + """, + toolTipMap: new Dictionary + { + { "int", "struct System.Int32" }, + { "string", "class System.String" } + }, + output: """ +
+ @{ + string x = "asdf"; + } + + @code { + private void M() + { + int y = 1; + } + } + """); + + [RoslynConditionalFact(typeof(IsEnglishLocal))] + public Task InlayHints_ExplicitStatementAndCodeBlock_Legacy() + => VerifyInlayHintsAsync( + input: """ +
+ @{ + var {|string:x|} = "asdf"; + } + + @functions { + private void M() + { + var {|int:y|} = 1; + } + } + """, + toolTipMap: new Dictionary + { + { "int", "struct System.Int32" }, + { "string", "class System.String" } + }, + output: """ +
+ @{ + string x = "asdf"; + } + + @functions { + private void M() + { + int y = 1; + } + } + """, + fileKind: RazorFileKind.Legacy); + [Fact] public Task InlayHints_ComponentAttributes() => VerifyInlayHintsAsync( @@ -154,7 +313,7 @@ public async Task InlayHints_InvalidRange(int startLine, int starChar, int endLi Assert.Null(hints); } - [RoslynConditionalFact(typeof(IsEnglishLocal), AlwaysSkip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [RoslynConditionalFact(typeof(IsEnglishLocal))] public Task PageDirective() => VerifyInlayHintsAsync( input: """ @@ -174,7 +333,7 @@ public Task PageDirective() """); - [RoslynConditionalFact(typeof(IsEnglishLocal), AlwaysSkip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [RoslynConditionalFact(typeof(IsEnglishLocal))] public Task AttributeDirective() => VerifyInlayHintsAsync( input: """ @@ -194,10 +353,31 @@ @attribute [System.ComponentModel.Description(description: "Desc")] """); - private async Task VerifyInlayHintsAsync(string input, Dictionary toolTipMap, string output, bool displayAllOverride = false) + [RoslynConditionalFact(typeof(IsEnglishLocal))] + public Task AttributeDirective_Legacy() + => VerifyInlayHintsAsync( + input: """ + @attribute [System.ComponentModel.Description({|description:"Desc"|})] + +
+ + """, + toolTipMap: new Dictionary + { + { "description", "(parameter) string description" }, + }, + output: """ + @attribute [System.ComponentModel.Description(description: "Desc")] + +
+ + """, + fileKind: RazorFileKind.Legacy); + + private async Task VerifyInlayHintsAsync(string input, Dictionary toolTipMap, string output, bool displayAllOverride = false, RazorFileKind? fileKind = null) { TestFileMarkupParser.GetSpans(input, out input, out ImmutableDictionary> spansDict); - var document = CreateProjectAndRazorDocument(input); + var document = CreateProjectAndRazorDocument(input, fileKind); var inputText = await document.GetTextAsync(DisposalToken); var endpoint = new CohostInlayHintEndpoint(IncompatibleProjectService, RemoteServiceInvoker); diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTest.cs index 665dfe31b5bc3..07defa0396f99 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTest.cs @@ -5,8 +5,8 @@ using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis.CSharp.Formatting; -using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Settings; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Xunit; using Xunit.Abstractions; @@ -123,6 +123,76 @@ await RunFormattingTestAsync( """"); } + [Fact] + public async Task MultilineRawStringLiteral_CodeBlock() + { + await RunFormattingTestAsync( + input: """" +
+ @code + { + private string _x = """ + Nieuw + + + Aanmaak scherm + + + + +
+ Opslaan + Annuleren +
+
+ """; + } + """", + htmlFormatted: """" +
+ @code + { + private string _x = """ + Nieuw + + + Aanmaak scherm + + + + +
+ Opslaan + Annuleren +
+
+ """; + } + """", + expected: """" +
+ @code + { + private string _x = """ + Nieuw + + + Aanmaak scherm + + + + +
+ Opslaan + Annuleren +
+
+ """; + } + """", + validateHtmlFormattedMatchesWebTools: false); + } + [Fact] [WorkItem("https://developercommunity.visualstudio.com/t/Razor-Formatting-Feature-internal-error/11041869")] public async Task TextAndTagOnSameLine() @@ -11665,7 +11735,7 @@ await RunFormattingTestAsync( fileKind: RazorFileKind.Legacy); } - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] public async Task MultilineExplicitExpression() { await RunFormattingTestAsync( @@ -11755,7 +11825,7 @@ await RunFormattingTestAsync( """); } - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] public async Task MultilineExplicitExpression_IsStable() { // This test explicitly validates that the expected output from the above test results in stable formatting. diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTestBase.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTestBase.cs index 986dd436da882..6a51540431bd1 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTestBase.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/DocumentFormattingTestBase.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; @@ -21,6 +21,7 @@ using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost.Formatting; diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingContentValidationPassTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingContentValidationPassTest.cs index 30e88b2231882..7fa5eb4a35e0f 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingContentValidationPassTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingContentValidationPassTest.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Text; using Moq; using Xunit; diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingDiagnosticValidationPassTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingDiagnosticValidationPassTest.cs index 96d27275aeb6e..00b8fe454a9ab 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingDiagnosticValidationPassTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/FormattingDiagnosticValidationPassTest.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; using Xunit; diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingPassTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingPassTest.cs index aa5b45a9acb01..422b98107880d 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingPassTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingPassTest.cs @@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Formatting; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Text; using Xunit; diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingTest.cs index afd3c092a6218..c20607efef72a 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/HtmlFormattingTest.cs @@ -8,6 +8,7 @@ using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Settings; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Xunit; using Xunit.Abstractions; using AssertEx = Roslyn.Test.Utilities.AssertEx; diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/RazorFormattingServiceTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/RazorFormattingServiceTest.cs index 48e41442a078b..03bbfef33e9a1 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/RazorFormattingServiceTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Formatting/RazorFormattingServiceTest.cs @@ -4,7 +4,7 @@ using System.Collections.Immutable; using System.Linq; using Microsoft.AspNetCore.Razor.Test.Common; -using Microsoft.CodeAnalysis.Razor.Formatting; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Text; using Xunit; using Xunit.Abstractions; @@ -44,7 +44,7 @@ public void AllTriggerCharacters_IncludesCSharpTriggerCharacters() { foreach (var character in RazorFormattingService.TestAccessor.GetCSharpTriggerCharacterSet()) { - Assert.Contains(character, RazorFormattingService.AllTriggerCharacterSet.ToList()); + Assert.Contains(character, CohostOnTypeFormattingEndpoint.AllTriggerCharacterSet.ToList()); } } @@ -53,7 +53,7 @@ public void AllTriggerCharacters_IncludesHtmlTriggerCharacters() { foreach (var character in RazorFormattingService.TestAccessor.GetHtmlTriggerCharacterSet()) { - Assert.Contains(character, RazorFormattingService.AllTriggerCharacterSet.ToList()); + Assert.Contains(character, CohostOnTypeFormattingEndpoint.AllTriggerCharacterSet.ToList()); } } } diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.UnitTests/Formatting/FormattingUtilitiesTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.UnitTests/Formatting/FormattingUtilitiesTest.cs similarity index 98% rename from src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.UnitTests/Formatting/FormattingUtilitiesTest.cs rename to src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.UnitTests/Formatting/FormattingUtilitiesTest.cs index 9446ef5c0af7d..32185b5ab7892 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.UnitTests/Formatting/FormattingUtilitiesTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.UnitTests/Formatting/FormattingUtilitiesTest.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Razor.Test.Common; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Text; using Xunit; diff --git a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRangeFormattingEndpointTest.cs b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRangeFormattingEndpointTest.cs index 7683e1bda1205..5bbb682d66733 100644 --- a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRangeFormattingEndpointTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRangeFormattingEndpointTest.cs @@ -7,11 +7,12 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.LanguageServer; +using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; diff --git a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRoslynGoToDefTest.cs b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRoslynGoToDefTest.cs index 421af086fb382..d4fec2a8ef0ee 100644 --- a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRoslynGoToDefTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/CohostRoslynGoToDefTest.cs @@ -17,7 +17,7 @@ namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; public class CohostRoslynGoToDefTest(ITestOutputHelper testOutputHelper) : CohostEndpointTestBase(testOutputHelper) { - [Fact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [Fact] public Task Component() => VerifyGoToDefinitionAsync( csharpFile: """ @@ -69,7 +69,17 @@ private async Task VerifyGoToDefinitionAsync( var definition = await RemoteGoToDefinitionService.TestAccessor.GetDefinitionsAsync(LocalWorkspace, csharpDocument, typeOnly: false, csharpPosition, DisposalToken); Assert.NotNull(definition); - var def = Assert.Single(definition); - Assert.Equal(razorDocument.GetURI(), def.DocumentUri); + // This calls Roslyn's Go To Definition handler directly to verify that Roslyn can call Razor's span mapping service. + // A real Go To Definition request from a C# file doesn't go through Razor's remote service. Since both the impl and + // decl generated documents contain the component symbol, Roslyn maps both results back to the same Razor location here. + // TODO: Check if we need to de-dupe on the Roslyn side, after span mapping, or if Roslyn/VS/VS Code takes care of it already. + Assert.Equal(2, definition.Length); + var expectedUri = razorDocument.GetURI(); + var expectedRange = definition[0].Range.ToLinePositionSpan(); + Assert.All(definition, def => + { + Assert.Equal(expectedUri, def.DocumentUri); + Assert.Equal(expectedRange, def.Range.ToLinePositionSpan()); + }); } } diff --git a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingLogTest.cs b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingLogTest.cs index 5e7948b46c982..454d73eab4f3a 100644 --- a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingLogTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingLogTest.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.CSharp.Formatting; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Text; using Xunit; using Xunit.Abstractions; diff --git a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingTestBase.cs b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingTestBase.cs index c4acd399d1804..ff241c702092b 100644 --- a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingTestBase.cs +++ b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/FormattingTestBase.cs @@ -13,6 +13,7 @@ using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Remote; +using Microsoft.CodeAnalysis.Remote.Razor.Formatting; using Microsoft.CodeAnalysis.Text; using Microsoft.VisualStudio.Razor.Settings; using Roslyn.Test.Utilities; diff --git a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/OnTypeFormattingTest.cs b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/OnTypeFormattingTest.cs index c6b763a7d1d76..101bd843dc90f 100644 --- a/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/OnTypeFormattingTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.UnitTests/Cohost/Formatting/OnTypeFormattingTest.cs @@ -105,7 +105,7 @@ @using Microsoft.AspNetCore.Components.Forms triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Class_SingleLineAsync() { await RunOnTypeFormattingTestAsync( @@ -123,7 +123,7 @@ public class Foo { } expectedChangedLines: 1); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Class_SingleLine_UseTabsAsync() { await RunOnTypeFormattingTestAsync( @@ -142,7 +142,7 @@ public class Foo { } expectedChangedLines: 1); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Class_SingleLine_AdjustTabSizeAsync() { await RunOnTypeFormattingTestAsync( @@ -161,7 +161,7 @@ public class Foo { } expectedChangedLines: 1); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Class_MultiLineAsync() { await RunOnTypeFormattingTestAsync( @@ -181,7 +181,7 @@ public class Foo triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Method_SingleLineAsync() { await RunOnTypeFormattingTestAsync( @@ -199,7 +199,7 @@ public void Foo { } expectedChangedLines: 1); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Method_MultiLineAsync() { await RunOnTypeFormattingTestAsync( @@ -219,7 +219,7 @@ public void Foo triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Property_SingleLineAsync() { await RunOnTypeFormattingTestAsync( @@ -236,7 +236,7 @@ await RunOnTypeFormattingTestAsync( triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Property_MultiLineAsync() { await RunOnTypeFormattingTestAsync( @@ -257,7 +257,7 @@ public string Foo triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task CloseCurly_Property_StartOfBlockAsync() { await RunOnTypeFormattingTestAsync( @@ -273,7 +273,7 @@ await RunOnTypeFormattingTestAsync( triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task Semicolon_ClassField_SingleLineAsync() { await RunOnTypeFormattingTestAsync( @@ -290,7 +290,7 @@ public class Foo { private int _hello = 0; } triggerCharacter: ';'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task Semicolon_ClassField_MultiLineAsync() { await RunOnTypeFormattingTestAsync( @@ -309,7 +309,7 @@ public class Foo{ triggerCharacter: ';'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task Semicolon_MethodVariableAsync() { await RunOnTypeFormattingTestAsync( @@ -366,7 +366,7 @@ protected override async Task OnInitializedAsync() triggerCharacter: ';'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task ClosingBrace_MatchesCSharpIndentationAsync() { await RunOnTypeFormattingTestAsync( @@ -414,7 +414,7 @@ private void IncrementCount() triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task ClosingBrace_DoesntMatchCSharpIndentationAsync() { await RunOnTypeFormattingTestAsync( @@ -624,7 +624,7 @@ await RunOnTypeFormattingTestAsync( triggerCharacter: ';'); } - [Fact(Skip = "https://github.com/dotnet/aspnetcore/issues/36390")] + [FormattingTestFact] [WorkItem("https://github.com/dotnet/aspnetcore/issues/34319")] public async Task NestedHtml_NestedCodeBlock_EndingBrace() { @@ -660,7 +660,7 @@ await RunOnTypeFormattingTestAsync( triggerCharacter: '}'); } - [Fact(Skip = "https://github.com/dotnet/aspnetcore/issues/36390")] + [FormattingTestFact] [WorkItem("https://github.com/dotnet/aspnetcore/issues/34319")] public async Task NestedHtml_NestedCodeBlock_EndingBrace_WithCode() { @@ -716,7 +716,7 @@ void Foo() await RunOnTypeFormattingTestAsync(input, input.Replace("$$", ""), triggerCharacter: ';'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] [WorkItem("https://github.com/dotnet/razor-tooling/issues/5698")] public async Task Semicolon_NoDocumentChanges2() { @@ -870,7 +870,7 @@ public void M() triggerCharacter: ';'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] [WorkItem("https://github.com/dotnet/razor-tooling/issues/6158")] public async Task Format_NestedLambdas() { @@ -1071,7 +1071,7 @@ await RunOnTypeFormattingTestAsync( triggerCharacter: ';'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task Semicolon_PropertyGet() { await RunOnTypeFormattingTestAsync( @@ -1135,7 +1135,7 @@ await RunOnTypeFormattingTestAsync( fileKind: RazorFileKind.Legacy); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] public async Task OnTypeFormatting_Enabled() { await RunOnTypeFormattingTestAsync( @@ -1161,7 +1161,7 @@ private void IncrementCount() triggerCharacter: '}'); } - [FormattingTestFact(Skip = "PROTOTYPE(sonic): cohosting feature not yet decl/impl split aware; see PR #83887")] + [FormattingTestFact] [WorkItem("https://github.com/dotnet/razor/issues/11117")] public async Task SemiColon_DoesntBreakHtmlAttributes() { diff --git a/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj b/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj index 416a6786cb740..a56728be8a9b7 100644 --- a/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj +++ b/src/Workspaces/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Workspaces.csproj @@ -46,6 +46,7 @@ +