From 6bdad0b49e9dbc3fd3daa0e7faeca6a3985aeb69 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Sat, 2 Mar 2024 12:13:52 +1100 Subject: [PATCH 1/5] Add formatting option to force open brace onto the next line after a `@code` or `@functions` block --- .../Formatting/RazorFormattingPass.cs | 44 +++--- .../RazorLSPOptions.cs | 3 + .../Settings/ClientSettings.cs | 4 +- .../Options/OptionsStorage.cs | 8 +- .../Options/SettingsNames.cs | 2 + .../Options/AdvancedOptionPage.cs | 10 ++ .../UnifiedSettings/razor.registration.json | 14 ++ .../VSPackage.resx | 6 + .../xlf/VSPackage.cs.xlf | 10 ++ .../xlf/VSPackage.de.xlf | 10 ++ .../xlf/VSPackage.es.xlf | 10 ++ .../xlf/VSPackage.fr.xlf | 10 ++ .../xlf/VSPackage.it.xlf | 10 ++ .../xlf/VSPackage.ja.xlf | 10 ++ .../xlf/VSPackage.ko.xlf | 10 ++ .../xlf/VSPackage.pl.xlf | 10 ++ .../xlf/VSPackage.pt-BR.xlf | 10 ++ .../xlf/VSPackage.ru.xlf | 10 ++ .../xlf/VSPackage.tr.xlf | 10 ++ .../xlf/VSPackage.zh-Hans.xlf | 10 ++ .../xlf/VSPackage.zh-Hant.xlf | 10 ++ .../CodeActionEndToEndTest.NetFx.cs | 1 + .../DefaultRazorConfigurationServiceTest.cs | 8 +- .../Formatting_NetFx/RazorFormattingTest.cs | 140 ++++++++++++++++++ .../TestRazorFormattingService.cs | 2 +- .../RazorLSPOptionsMonitorTest.cs | 6 +- .../LanguageServer/LanguageServerTestBase.cs | 4 +- 27 files changed, 346 insertions(+), 36 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs index 66a597bce3f..d3ca14f490b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; @@ -14,27 +13,20 @@ using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.VisualStudio.LanguageServer.Protocol; namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; -internal class RazorFormattingPass : FormattingPassBase +internal class RazorFormattingPass( + IRazorDocumentMappingService documentMappingService, + IClientConnection clientConnection, + IOptionsMonitor optionsMonitor, + IRazorLoggerFactory loggerFactory) + : FormattingPassBase(documentMappingService, clientConnection) { - private readonly ILogger _logger; - - public RazorFormattingPass( - IRazorDocumentMappingService documentMappingService, - IClientConnection clientConnection, - IRazorLoggerFactory loggerFactory) - : base(documentMappingService, clientConnection) - { - if (loggerFactory is null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _logger = loggerFactory.CreateLogger(); - } + private readonly ILogger _logger = loggerFactory.CreateLogger(); + private readonly IOptionsMonitor _optionsMonitor = optionsMonitor; // Run after the C# formatter pass. public override int Order => DefaultOrder - 4; @@ -76,7 +68,7 @@ public async override Task ExecuteAsync(FormattingContext cont return new FormattingResult(finalEdits); } - private static IEnumerable FormatRazor(FormattingContext context, RazorSyntaxTree syntaxTree) + private IEnumerable FormatRazor(FormattingContext context, RazorSyntaxTree syntaxTree) { var edits = new List(); var source = syntaxTree.Source; @@ -93,7 +85,7 @@ private static IEnumerable FormatRazor(FormattingContext context, Razo return edits; } - private static void TryFormatBlocks(FormattingContext context, List edits, RazorSourceDocument source, SyntaxNode node) + private void TryFormatBlocks(FormattingContext context, List edits, RazorSourceDocument source, SyntaxNode node) { // We only want to run one of these _ = TryFormatFunctionsBlock(context, edits, source, node) || @@ -103,7 +95,7 @@ private static void TryFormatBlocks(FormattingContext context, List ed TryFormatSectionBlock(context, edits, source, node); } - private static bool TryFormatSectionBlock(FormattingContext context, List edits, RazorSourceDocument source, SyntaxNode node) + private bool TryFormatSectionBlock(FormattingContext context, List edits, RazorSourceDocument source, SyntaxNode node) { // @section Goo { // } @@ -265,7 +257,7 @@ private static bool TryFormatHtmlInCSharp(FormattingContext context, IList edits, RazorSourceDocument source, SyntaxNode node) + private void TryFormatCSharpBlockStructure(FormattingContext context, List edits, RazorSourceDocument source, SyntaxNode node) { // We're looking for a code block like this: // @@ -355,9 +347,14 @@ static bool IsSingleLineDirective(SyntaxNode node, [NotNullWhen(true)] out Synta } } - private static void FormatWhitespaceBetweenDirectiveAndBrace(SyntaxNode node, RazorDirectiveSyntax directive, List edits, RazorSourceDocument source, FormattingContext context) + private void FormatWhitespaceBetweenDirectiveAndBrace(SyntaxNode node, RazorDirectiveSyntax directive, List edits, RazorSourceDocument source, FormattingContext context) { - if (node.ContainsOnlyWhitespace(includingNewLines: false)) + // If we're formatting a @code or @functions directive, the user might have indicated they always want a newline + var forceNewLine = _optionsMonitor.CurrentValue.CodeBlockBraceOnNextLine && + directive.Body is RazorDirectiveBodySyntax { Keyword: { } keyword } && + keyword.GetContent() is "code" or "functions"; + + if (node.ContainsOnlyWhitespace(includingNewLines: false) && !forceNewLine) { ShrinkToSingleSpace(node, edits, source); } @@ -393,6 +390,7 @@ private static bool FormatBlock(FormattingContext context, RazorSourceDocument s var openBraceRange = openBraceNode.GetRangeWithoutWhitespace(source); var codeRange = codeNode.GetRangeWithoutWhitespace(source); + if (openBraceRange is not null && codeRange is not null && openBraceRange.End.Line == codeRange.Start.Line && diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs index f91c26bb86f..ba14c559e1f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs @@ -15,6 +15,7 @@ internal record RazorLSPOptions( bool FormatOnType, bool AutoInsertAttributeQuotes, bool ColorBackground, + bool CodeBlockBraceOnNextLine, bool CommitElementsWithSpace) { public RazorLSPOptions(bool enableFormatting, bool autoClosingTags, bool commitElementsWithSpace, ClientSettings settings) @@ -27,6 +28,7 @@ public RazorLSPOptions(bool enableFormatting, bool autoClosingTags, bool commitE settings.AdvancedSettings.FormatOnType, settings.AdvancedSettings.AutoInsertAttributeQuotes, settings.AdvancedSettings.ColorBackground, + settings.AdvancedSettings.CodeBlockBraceOnNextLine, commitElementsWithSpace) { } @@ -40,6 +42,7 @@ public RazorLSPOptions(bool enableFormatting, bool autoClosingTags, bool commitE FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, + CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: true); /// diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Settings/ClientSettings.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Settings/ClientSettings.cs index 223e504adc7..10379aeb4c4 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Settings/ClientSettings.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Settings/ClientSettings.cs @@ -32,7 +32,7 @@ internal sealed record ClientSpaceSettings(bool IndentWithTabs, int IndentSize) public int IndentSize { get; } = IndentSize >= 0 ? IndentSize : throw new ArgumentOutOfRangeException(nameof(IndentSize)); } -internal sealed record ClientAdvancedSettings(bool FormatOnType, bool AutoClosingTags, bool AutoInsertAttributeQuotes, bool ColorBackground, bool CommitElementsWithSpace, SnippetSetting SnippetSetting, LogLevel LogLevel) +internal sealed record ClientAdvancedSettings(bool FormatOnType, bool AutoClosingTags, bool AutoInsertAttributeQuotes, bool ColorBackground, bool CodeBlockBraceOnNextLine, bool CommitElementsWithSpace, SnippetSetting SnippetSetting, LogLevel LogLevel) { - public static readonly ClientAdvancedSettings Default = new(FormatOnType: true, AutoClosingTags: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CommitElementsWithSpace: true, SnippetSetting.All, LogLevel.Warning); + public static readonly ClientAdvancedSettings Default = new(FormatOnType: true, AutoClosingTags: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: true, SnippetSetting.All, LogLevel.Warning); } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/OptionsStorage.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/OptionsStorage.cs index 087fb1506be..213c7bf2e68 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/OptionsStorage.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/OptionsStorage.cs @@ -53,6 +53,12 @@ public bool ColorBackground set => SetBool(SettingsNames.ColorBackground.LegacyName, value); } + public bool CodeBlockBraceOnNextLine + { + get => GetBool(SettingsNames.CodeBlockBraceOnNextLine.LegacyName, defaultValue: false); + set => SetBool(SettingsNames.CodeBlockBraceOnNextLine.LegacyName, value); + } + public bool CommitElementsWithSpace { get => GetBool(SettingsNames.CommitElementsWithSpace.LegacyName, defaultValue: true); @@ -101,7 +107,7 @@ public async Task OnChangedAsync(Action changed) private EventHandler? _changed; - public ClientAdvancedSettings GetAdvancedSettings() => new(FormatOnType, AutoClosingTags, AutoInsertAttributeQuotes, ColorBackground, CommitElementsWithSpace, Snippets, LogLevel); + public ClientAdvancedSettings GetAdvancedSettings() => new(FormatOnType, AutoClosingTags, AutoInsertAttributeQuotes, ColorBackground, CodeBlockBraceOnNextLine, CommitElementsWithSpace, Snippets, LogLevel); public bool GetBool(string name, bool defaultValue) { diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/SettingsNames.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/SettingsNames.cs index 371ea38c0a7..bce87538ef4 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/SettingsNames.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/Options/SettingsNames.cs @@ -14,6 +14,7 @@ public record Setting(string LegacyName, string UnifiedName); public static readonly Setting AutoClosingTags = new("AutoClosingTags", UnifiedCollection + ".autoClosingTags"); public static readonly Setting AutoInsertAttributeQuotes = new("AutoInsertAttributeQuotes", UnifiedCollection + ".autoInsertAttributeQuotes"); public static readonly Setting ColorBackground = new("ColorBackground", UnifiedCollection + ".colorBackground"); + public static readonly Setting CodeBlockBraceOnNextLine = new("CodeBlockBraceOnNextLine", UnifiedCollection + ".codeBlockBraceOnNextLine"); public static readonly Setting CommitElementsWithSpace = new("CommitElementsWithSpace", UnifiedCollection + ".commitCharactersWithSpace"); public static readonly Setting Snippets = new("Snippets", UnifiedCollection + ".snippets"); public static readonly Setting LogLevel = new("LogLevel", UnifiedCollection + ".logLevel"); @@ -24,6 +25,7 @@ public record Setting(string LegacyName, string UnifiedName); AutoClosingTags, AutoInsertAttributeQuotes, ColorBackground, + CodeBlockBraceOnNextLine, CommitElementsWithSpace, Snippets, LogLevel, diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Options/AdvancedOptionPage.cs b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Options/AdvancedOptionPage.cs index fb8d00ba813..552e7539e6d 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Options/AdvancedOptionPage.cs +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/Options/AdvancedOptionPage.cs @@ -21,6 +21,7 @@ internal class AdvancedOptionPage : DialogPage private bool? _autoClosingTags; private bool? _autoInsertAttributeQuotes; private bool? _colorBackground; + private bool? _codeBlockBraceOnNextLine; private bool? _commitElementsWithSpace; private SnippetSetting? _snippets; private LogLevel? _logLevel; @@ -81,6 +82,15 @@ public bool ColorBackground set => _colorBackground = value; } + [LocCategory(nameof(VSPackage.Formatting))] + [LocDescription(nameof(VSPackage.Setting_CodeBlockBraceOnNextLineDescription))] + [LocDisplayName(nameof(VSPackage.Setting_CodeBlockBraceOnNextLineDisplayName))] + public bool CodeBlockBraceOnNextLine + { + get => _codeBlockBraceOnNextLine ?? _optionsStorage.Value.CodeBlockBraceOnNextLine; + set => _codeBlockBraceOnNextLine = value; + } + [LocCategory(nameof(VSPackage.Completion))] [LocDescription(nameof(VSPackage.Setting_SnippetsDescription))] [LocDisplayName(nameof(VSPackage.Setting_SnippetsDisplayName))] diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/UnifiedSettings/razor.registration.json b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/UnifiedSettings/razor.registration.json index f71cb519e97..85171315bff 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/UnifiedSettings/razor.registration.json +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/UnifiedSettings/razor.registration.json @@ -61,6 +61,20 @@ } } }, + "textEditor.razor.advanced.codeBlockBraceOnNextLine": { + "type": "boolean", + "default": false, + "title": "@Setting_CodeBlockBraceOnNextLinedDisplayName;{13b72f58-279e-49e0-a56d-296be02f0805}", + "description": "@Setting_CodeBlockBraceOnNextLinedDescription;{13b72f58-279e-49e0-a56d-296be02f0805}", + "migration": { + "pass": { + "input": { + "store": "VsUserSettingsRegistry", + "path": "Razor\\CodeBlockBraceOnNextLined" + } + } + } + }, "textEditor.razor.advanced.commitElementsWithSpace": { "type": "boolean", "default": true, diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/VSPackage.resx b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/VSPackage.resx index 29353626062..fd7017ba0a1 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/VSPackage.resx +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/VSPackage.resx @@ -162,6 +162,12 @@ Auto Insert Attribute Quotes + + Forces the open brace after an @code or @functions directive to be on the following line + + + Code/Functions block open brace on next line + If true, gives C# code in Razor files a background color diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.cs.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.cs.xlf index 6afb1073ab3..1a69239b72c 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.cs.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.cs.xlf @@ -62,6 +62,16 @@ Automaticky vložit uvozovky atributů + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Pokud je hodnota „true“, vrátí kód C# v souborech Razor barvu pozadí. diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.de.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.de.xlf index eaeba6bbe0e..5cc4805b2a8 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.de.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.de.xlf @@ -62,6 +62,16 @@ Anführungszeichen für Attribute automatisch einfügen + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Bei „true“ erhält C#-Code in Razor-Dateien eine Hintergrundfarbe. diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.es.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.es.xlf index b99ee9d749a..944e15337c5 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.es.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.es.xlf @@ -62,6 +62,16 @@ Insertar automáticamente comillas de atributo + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Si es true, da un color de fondo al código de C# de los archivos de Razor. diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.fr.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.fr.xlf index c180c999a04..572f683f6d1 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.fr.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.fr.xlf @@ -62,6 +62,16 @@ Insérer automatiquement des guillemets d’attribut + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Si la valeur est true, donne une couleur d’arrière-plan au code C# dans les fichiers Razor diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.it.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.it.xlf index e36af475ab5..3aa399b5497 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.it.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.it.xlf @@ -62,6 +62,16 @@ Inserire automaticamente le virgolette degli attributi + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Se true, assegna un colore di sfondo al codice C# nei file Razor diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ja.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ja.xlf index 687875ba339..d2023dbd414 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ja.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ja.xlf @@ -62,6 +62,16 @@ 属性引用符の自動挿入 + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color true の場合、Razor ファイルの C# コードに背景色を表示します diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ko.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ko.xlf index 74581f91aed..0960b8df605 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ko.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ko.xlf @@ -62,6 +62,16 @@ 특성 따옴표 자동 삽입 + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color true이면 Razor 파일의 C# 코드에 배경색을 지정합니다. diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pl.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pl.xlf index 4cdb12c1ca6..91dfbf493e5 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pl.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pl.xlf @@ -62,6 +62,16 @@ Automatyczne wstawianie cudzysłowów atrybutów + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Jeśli ma wartość true, nadaje kolor tła dla kodu języka C# w plikach Razor diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pt-BR.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pt-BR.xlf index 5a6876fa631..be17f4472d4 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pt-BR.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.pt-BR.xlf @@ -62,6 +62,16 @@ Inserir Aspas de Atributo Automaticamente + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Se verdadeiro, dá ao código C# nos arquivos Razor uma cor de fundo diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ru.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ru.xlf index dfb821317fa..28bd1d98b60 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ru.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.ru.xlf @@ -62,6 +62,16 @@ Автоматически вставлять кавычки атрибутов + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color Если ИСТИНА, коду C# в файлах Razor присваивается цвет фона. diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.tr.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.tr.xlf index ca10dffbdc9..43fe9952e51 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.tr.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.tr.xlf @@ -62,6 +62,16 @@ Öznitelik Tırnaklarını Otomatik Ekle + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color True ise Razor dosyalarında C# kodu bir arka plan rengi verir diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hans.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hans.xlf index b2454d2bdb9..dbd1adc6674 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hans.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hans.xlf @@ -62,6 +62,16 @@ 自动插入属性引号 + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color 如果为 true,则为 Razor 文件中的 C# 代码提供背景色 diff --git a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hant.xlf b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hant.xlf index b2dc09753ae..2bb7ed4ce61 100644 --- a/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hant.xlf +++ b/src/Razor/src/Microsoft.VisualStudio.RazorExtension/xlf/VSPackage.zh-Hant.xlf @@ -62,6 +62,16 @@ 自動插入屬性引號 + + Forces the open brace after an @code or @functions directive to be on the following line + Forces the open brace after an @code or @functions directive to be on the following line + + + + Code/Functions block open brace on next line + Code/Functions block open brace on next line + + If true, gives C# code in Razor files a background color 若為 true,則給予 Razor 檔案中的 C# 程式碼背景色彩 diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs index 8b267cb979e..87e2def4d15 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs @@ -719,6 +719,7 @@ public async Task Handle_GenerateMethod_VaryIndentSize(bool insertSpaces, int ta FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, + CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: true); var optionsMonitor = TestRazorLSPOptionsMonitor.Create(); await optionsMonitor.UpdateAsync(razorLSPOptions, CancellationToken.None); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs index a290c2023a5..7b06afb69b4 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs @@ -21,7 +21,7 @@ public async Task GetLatestOptionsAsync_ReturnsExpectedOptions() { // Arrange var expectedOptions = new RazorLSPOptions( - EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CommitElementsWithSpace: false); + EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: false); var razorJsonString = """ @@ -92,7 +92,7 @@ public void BuildOptions_VSCodeOptionsOnly_ReturnsExpected() { // Arrange - purposely choosing options opposite of default var expectedOptions = new RazorLSPOptions( - EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CommitElementsWithSpace: false); + EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: false); var razorJsonString = """ { "format": { @@ -128,7 +128,7 @@ public void BuildOptions_VSOptionsOnly_ReturnsExpected() { // Arrange - purposely choosing options opposite of default var expectedOptions = new RazorLSPOptions( - EnableFormatting: true, AutoClosingTags: false, InsertSpaces: false, TabSize: 8, AutoShowCompletion: true, AutoListParams: true, FormatOnType: false, AutoInsertAttributeQuotes: false, ColorBackground: false, CommitElementsWithSpace: false); + EnableFormatting: true, AutoClosingTags: false, InsertSpaces: false, TabSize: 8, AutoShowCompletion: true, AutoListParams: true, FormatOnType: false, AutoInsertAttributeQuotes: false, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: false); var razorJsonString = """ { } @@ -171,7 +171,7 @@ public void BuildOptions_MalformedOptions() // Arrange // The Json blob is seen as a VS Code options set, so we have to use its default - var expectedOptions = RazorLSPOptions.Default with { CommitElementsWithSpace = false}; + var expectedOptions = RazorLSPOptions.Default with { CommitElementsWithSpace = false }; var razorJsonString = @" { ""format"": { diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/RazorFormattingTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/RazorFormattingTest.cs index bad9ad81df0..b2cbdd1c2b1 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/RazorFormattingTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/RazorFormattingTest.cs @@ -224,6 +224,61 @@ private void IncrementCount() """); } + [Fact] + public async Task CodeBlock_FixCloseBrace3() + { + await RunFormattingTestAsync( + input: """ + @code { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + expected: """ + @code + { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + razorLSPOptions: RazorLSPOptions.Default with { CodeBlockBraceOnNextLine = true }); + } + + [Fact] + public async Task CodeBlock_FixCloseBrace4() + { + await RunFormattingTestAsync( + input: """ + @code { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } } + """, + expected: """ + @code + { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + razorLSPOptions: RazorLSPOptions.Default with { CodeBlockBraceOnNextLine = true }); + } + [Fact] public async Task CodeBlock_TooMuchWhitespace() { @@ -276,6 +331,34 @@ private void IncrementCount() """); } + [Fact] + public async Task CodeBlock_NonSpaceWhitespace2() + { + await RunFormattingTestAsync( + input: """ + @code { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + expected: """ + @code + { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + razorLSPOptions: RazorLSPOptions.Default with { CodeBlockBraceOnNextLine = true }); + } + [Fact] public async Task CodeBlock_NoWhitespace() { @@ -302,6 +385,34 @@ private void IncrementCount() """); } + [Fact] + public async Task CodeBlock_NoWhitespace2() + { + await RunFormattingTestAsync( + input: """ + @code{ + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + expected: """ + @code + { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + razorLSPOptions: RazorLSPOptions.Default with { CodeBlockBraceOnNextLine = true }); + } + [Fact] public async Task FunctionsBlock_BraceOnNewLine() { @@ -358,6 +469,35 @@ private void IncrementCount() fileKind: FileKinds.Legacy); } + [Fact] + public async Task FunctionsBlock_TooManySpaces2() + { + await RunFormattingTestAsync( + input: """ + @functions { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + expected: """ + @functions + { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, + fileKind: FileKinds.Legacy, + razorLSPOptions: RazorLSPOptions.Default with { CodeBlockBraceOnNextLine = true }); + } + [Fact] public async Task FunctionsBlock_FixCloseBrace() { diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs index baa3f624d41..0ce03fa675f 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs @@ -64,7 +64,7 @@ await dispatcher.RunAsync(() => new HtmlFormattingPass(mappingService, client, versionCache, optionsMonitor, loggerFactory), new CSharpFormattingPass(mappingService, client, loggerFactory), new CSharpOnTypeFormattingPass(mappingService, client, optionsMonitor, loggerFactory), - new RazorFormattingPass(mappingService, client, loggerFactory), + new RazorFormattingPass(mappingService, client, optionsMonitor, loggerFactory), new FormattingDiagnosticValidationPass(mappingService, client, loggerFactory), new FormattingContentValidationPass(mappingService, client, loggerFactory), }; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLSPOptionsMonitorTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLSPOptionsMonitorTest.cs index 0c363ee1f2d..75bb359e05e 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLSPOptionsMonitorTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorLSPOptionsMonitorTest.cs @@ -28,7 +28,7 @@ public RazorLSPOptionsMonitorTest(ITestOutputHelper testOutput) public async Task UpdateAsync_Invokes_OnChangeRegistration() { // Arrange - var expectedOptions = new RazorLSPOptions(EnableFormatting: false, AutoClosingTags: true, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CommitElementsWithSpace: true); + var expectedOptions = new RazorLSPOptions(EnableFormatting: false, AutoClosingTags: true, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: true); var configService = Mock.Of( f => f.GetLatestOptionsAsync(DisposalToken) == Task.FromResult(expectedOptions), MockBehavior.Strict); @@ -50,7 +50,7 @@ public async Task UpdateAsync_Invokes_OnChangeRegistration() public async Task UpdateAsync_DoesNotInvoke_OnChangeRegistration_AfterDispose() { // Arrange - var expectedOptions = new RazorLSPOptions(EnableFormatting: false, AutoClosingTags: true, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CommitElementsWithSpace: true); + var expectedOptions = new RazorLSPOptions(EnableFormatting: false, AutoClosingTags: true, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: true); var configService = Mock.Of( f => f.GetLatestOptionsAsync(DisposalToken) == Task.FromResult(expectedOptions), MockBehavior.Strict); @@ -96,7 +96,7 @@ public async Task UpdateAsync_ConfigReturnsNull_DoesNotInvoke_OnChangeRegistrati public void InitializedOptionsAreCurrent() { // Arrange - var expectedOptions = new RazorLSPOptions(EnableFormatting: false, AutoClosingTags: true, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CommitElementsWithSpace: true); + var expectedOptions = new RazorLSPOptions(EnableFormatting: false, AutoClosingTags: true, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: true); var configService = Mock.Of( f => f.GetLatestOptionsAsync(DisposalToken) == Task.FromResult(expectedOptions), MockBehavior.Strict); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs index f683907c31a..81b764e5d64 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs @@ -121,10 +121,10 @@ internal static VersionedDocumentContext CreateDocumentContext(Uri uri, IDocumen return new VersionedDocumentContext(uri, snapshot, projectContext: null, version: 0); } - internal static IOptionsMonitor GetOptionsMonitor(bool enableFormatting = true, bool autoShowCompletion = true, bool autoListParams = true, bool formatOnType = true, bool autoInsertAttributeQuotes = true, bool colorBackground = false, bool commitElementsWithSpace = true) + internal static IOptionsMonitor GetOptionsMonitor(bool enableFormatting = true, bool autoShowCompletion = true, bool autoListParams = true, bool formatOnType = true, bool autoInsertAttributeQuotes = true, bool colorBackground = false, bool codeBlockBraceOnNextLine = false, bool commitElementsWithSpace = true) { var monitor = new Mock>(MockBehavior.Strict); - monitor.SetupGet(m => m.CurrentValue).Returns(new RazorLSPOptions(enableFormatting, true, InsertSpaces: true, TabSize: 4, autoShowCompletion, autoListParams, formatOnType, autoInsertAttributeQuotes, colorBackground, commitElementsWithSpace)); + monitor.SetupGet(m => m.CurrentValue).Returns(new RazorLSPOptions(enableFormatting, true, InsertSpaces: true, TabSize: 4, autoShowCompletion, autoListParams, formatOnType, autoInsertAttributeQuotes, colorBackground, codeBlockBraceOnNextLine, commitElementsWithSpace)); return monitor.Object; } From 4b70cb5d91b0dc3e7f01a769be930b58db580c82 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Sat, 2 Mar 2024 21:05:37 +1100 Subject: [PATCH 2/5] Oops, missed a spot --- .../Settings/ClientSettingsManagerTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/Settings/ClientSettingsManagerTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/Settings/ClientSettingsManagerTest.cs index 736ebf76c1e..d818d2b3496 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/Settings/ClientSettingsManagerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/Settings/ClientSettingsManagerTest.cs @@ -82,7 +82,7 @@ public void Update_TriggersChangedIfAdvancedSettingsAreDifferent() var manager = new ClientSettingsManager(_clientSettingsChangeTriggers); var called = false; manager.ClientSettingsChanged += (caller, args) => called = true; - var settings = new ClientAdvancedSettings(FormatOnType: false, AutoClosingTags: true, AutoInsertAttributeQuotes: true, ColorBackground: true, CommitElementsWithSpace: false, SnippetSetting: default, LogLevel: default); + var settings = new ClientAdvancedSettings(FormatOnType: false, AutoClosingTags: true, AutoInsertAttributeQuotes: true, ColorBackground: true, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: false, SnippetSetting: default, LogLevel: default); // Act manager.Update(settings); From 29c73a5e9a9a363661fb910b880e61d0178b7917 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Sat, 2 Mar 2024 21:33:58 +1100 Subject: [PATCH 3/5] Fix case where there is no whitespace at all between directive and brace --- .../Formatting/RazorFormattingPass.cs | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs index d3ca14f490b..e958a5406d9 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs @@ -114,8 +114,8 @@ directiveCode.Children is [RazorDirectiveSyntax directive] && if (TryGetWhitespace(children, out var whitespaceBeforeSectionName, out var whitespaceAfterSectionName)) { // For whitespace we normalize it differently depending on if its multi-line or not - FormatWhitespaceBetweenDirectiveAndBrace(whitespaceBeforeSectionName, directive, edits, source, context); - FormatWhitespaceBetweenDirectiveAndBrace(whitespaceAfterSectionName, directive, edits, source, context); + FormatWhitespaceBetweenDirectiveAndBrace(whitespaceBeforeSectionName, directive, edits, source, context, forceNewLine: false); + FormatWhitespaceBetweenDirectiveAndBrace(whitespaceAfterSectionName, directive, edits, source, context, forceNewLine: false); return true; } @@ -276,11 +276,16 @@ private void TryFormatCSharpBlockStructure(FormattingContext context, List edits, RazorSourceDocument source, FormattingContext context) + private void FormatWhitespaceBetweenDirectiveAndBrace(SyntaxNode node, RazorDirectiveSyntax directive, List edits, RazorSourceDocument source, FormattingContext context, bool forceNewLine) { - // If we're formatting a @code or @functions directive, the user might have indicated they always want a newline - var forceNewLine = _optionsMonitor.CurrentValue.CodeBlockBraceOnNextLine && - directive.Body is RazorDirectiveBodySyntax { Keyword: { } keyword } && - keyword.GetContent() is "code" or "functions"; - if (node.ContainsOnlyWhitespace(includingNewLines: false) && !forceNewLine) { ShrinkToSingleSpace(node, edits, source); From 41fabfa714c6c9b46de57ad9e89f29162cdda933 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Sat, 2 Mar 2024 21:47:57 +1100 Subject: [PATCH 4/5] Add VS Code support --- .../DefaultRazorConfigurationService.cs | 27 +++++++++++++---- .../RazorLSPOptions.cs | 30 +++++++------------ .../DefaultRazorConfigurationServiceTest.cs | 10 ++++--- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorConfigurationService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorConfigurationService.cs index 5577a64b524..3fdb7458bd5 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorConfigurationService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorConfigurationService.cs @@ -95,8 +95,14 @@ internal RazorLSPOptions BuildOptions(JObject[] result) } else { - ExtractVSCodeOptions(result, out var enableFormatting, out var autoClosingTags, out var commitElementsWithSpace); - return new RazorLSPOptions(enableFormatting, autoClosingTags, commitElementsWithSpace, ClientSettings.Default); + ExtractVSCodeOptions(result, out var enableFormatting, out var autoClosingTags, out var commitElementsWithSpace, out var codeBlockBraceOnNextLine); + return RazorLSPOptions.Default with + { + EnableFormatting = enableFormatting, + AutoClosingTags = autoClosingTags, + CommitElementsWithSpace = commitElementsWithSpace, + CodeBlockBraceOnNextLine = codeBlockBraceOnNextLine + }; } } @@ -104,13 +110,15 @@ private void ExtractVSCodeOptions( JObject[] result, out bool enableFormatting, out bool autoClosingTags, - out bool commitElementsWithSpace) + out bool commitElementsWithSpace, + out bool codeBlockBraceOnNextLine) { var razor = result[0]; var html = result[1]; enableFormatting = RazorLSPOptions.Default.EnableFormatting; autoClosingTags = RazorLSPOptions.Default.AutoClosingTags; + codeBlockBraceOnNextLine = RazorLSPOptions.Default.CodeBlockBraceOnNextLine; // Deliberately not using the "default" here because we want a different default for VS Code, as // this matches VS Code's html servers commit behaviour commitElementsWithSpace = false; @@ -119,10 +127,17 @@ private void ExtractVSCodeOptions( { if (razor.TryGetValue("format", out var parsedFormat)) { - if (parsedFormat is JObject jObject && - jObject.TryGetValue("enable", out var parsedEnableFormatting)) + if (parsedFormat is JObject jObject) { - enableFormatting = GetObjectOrDefault(parsedEnableFormatting, enableFormatting); + if (jObject.TryGetValue("enable", out var parsedEnableFormatting)) + { + enableFormatting = GetObjectOrDefault(parsedEnableFormatting, enableFormatting); + } + + if (jObject.TryGetValue("codeBlockBraceOnNextLine", out var parsedCodeBlockBraceOnNextLine)) + { + codeBlockBraceOnNextLine = GetObjectOrDefault(parsedCodeBlockBraceOnNextLine, codeBlockBraceOnNextLine); + } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs index ba14c559e1f..a87c2923a13 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLSPOptions.cs @@ -18,21 +18,6 @@ internal record RazorLSPOptions( bool CodeBlockBraceOnNextLine, bool CommitElementsWithSpace) { - public RazorLSPOptions(bool enableFormatting, bool autoClosingTags, bool commitElementsWithSpace, ClientSettings settings) - : this(enableFormatting, - autoClosingTags, - !settings.ClientSpaceSettings.IndentWithTabs, - settings.ClientSpaceSettings.IndentSize, - settings.ClientCompletionSettings.AutoShowCompletion, - settings.ClientCompletionSettings.AutoListParams, - settings.AdvancedSettings.FormatOnType, - settings.AdvancedSettings.AutoInsertAttributeQuotes, - settings.AdvancedSettings.ColorBackground, - settings.AdvancedSettings.CodeBlockBraceOnNextLine, - commitElementsWithSpace) - { - } - public readonly static RazorLSPOptions Default = new(EnableFormatting: true, AutoClosingTags: true, AutoListParams: true, @@ -49,9 +34,16 @@ public RazorLSPOptions(bool enableFormatting, bool autoClosingTags, bool commitE /// Initializes the LSP options with the settings from the passed in client settings, and default values for anything /// not defined in client settings. /// - internal static RazorLSPOptions From(ClientSettings clientSettings) + internal static RazorLSPOptions From(ClientSettings settings) => new(Default.EnableFormatting, - clientSettings.AdvancedSettings.AutoClosingTags, - clientSettings.AdvancedSettings.CommitElementsWithSpace, - clientSettings); + settings.AdvancedSettings.AutoClosingTags, + !settings.ClientSpaceSettings.IndentWithTabs, + settings.ClientSpaceSettings.IndentSize, + settings.ClientCompletionSettings.AutoShowCompletion, + settings.ClientCompletionSettings.AutoListParams, + settings.AdvancedSettings.FormatOnType, + settings.AdvancedSettings.AutoInsertAttributeQuotes, + settings.AdvancedSettings.ColorBackground, + settings.AdvancedSettings.CodeBlockBraceOnNextLine, + settings.AdvancedSettings.CommitElementsWithSpace); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs index 7b06afb69b4..d01e2537e7f 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorConfigurationServiceTest.cs @@ -21,13 +21,14 @@ public async Task GetLatestOptionsAsync_ReturnsExpectedOptions() { // Arrange var expectedOptions = new RazorLSPOptions( - EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: false); + EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: true, CommitElementsWithSpace: false); var razorJsonString = """ { "format": { - "enable": "false" + "enable": "false", + "codeBlockBraceOnNextLine": "true" } } @@ -92,11 +93,12 @@ public void BuildOptions_VSCodeOptionsOnly_ReturnsExpected() { // Arrange - purposely choosing options opposite of default var expectedOptions = new RazorLSPOptions( - EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: false, CommitElementsWithSpace: false); + EnableFormatting: false, AutoClosingTags: false, InsertSpaces: true, TabSize: 4, AutoShowCompletion: true, AutoListParams: true, FormatOnType: true, AutoInsertAttributeQuotes: true, ColorBackground: false, CodeBlockBraceOnNextLine: true, CommitElementsWithSpace: false); var razorJsonString = """ { "format": { - "enable": "false" + "enable": "false", + "codeBlockBraceOnNextLine": "true" } } From 823069a2295f827ea5f42ae2944f0a32587f4c2d Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 5 Mar 2024 11:46:30 +1100 Subject: [PATCH 5/5] PR Feedback --- .../Formatting/RazorFormattingPass.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs index e958a5406d9..bdfa0e7eba8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingPass.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.Language.Components; using Microsoft.AspNetCore.Razor.Language.Extensions; using Microsoft.AspNetCore.Razor.Language.Syntax; using Microsoft.AspNetCore.Razor.LanguageServer.Extensions; @@ -95,7 +96,7 @@ private void TryFormatBlocks(FormattingContext context, List edits, Ra TryFormatSectionBlock(context, edits, source, node); } - private bool TryFormatSectionBlock(FormattingContext context, List edits, RazorSourceDocument source, SyntaxNode node) + private static bool TryFormatSectionBlock(FormattingContext context, List edits, RazorSourceDocument source, SyntaxNode node) { // @section Goo { // } @@ -170,8 +171,7 @@ private static bool TryFormatFunctionsBlock(FormattingContext context, IList edits, RazorSourceDocument source, FormattingContext context, bool forceNewLine) + private static void FormatWhitespaceBetweenDirectiveAndBrace(SyntaxNode node, RazorDirectiveSyntax directive, List edits, RazorSourceDocument source, FormattingContext context, bool forceNewLine) { if (node.ContainsOnlyWhitespace(includingNewLines: false) && !forceNewLine) { @@ -536,4 +536,11 @@ static int GetTrailingWhitespaceLength(SyntaxNode node, FormattingContext contex } } } + + private static bool IsCodeOrFunctionsBlock(RazorSyntaxNode keyword) + { + var keywordContent = keyword.GetContent(); + return keywordContent == FunctionsDirective.Directive.Directive || + keywordContent == ComponentCodeDirective.Directive.Directive; + } }