From 760e583ec333970175a526df108b96a5832b043e Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Thu, 13 Oct 2016 02:33:52 -0700 Subject: [PATCH] Only format an open curly if it the first token on a line. --- .../CSharpEditorFormattingService.cs | 26 ++++++-- .../Indentation/SmartTokenFormatter.cs | 7 ++- .../Formatting/FormattingEngineTests.cs | 59 +++++++++++++++++++ 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/EditorFeatures/CSharp/Formatting/CSharpEditorFormattingService.cs b/src/EditorFeatures/CSharp/Formatting/CSharpEditorFormattingService.cs index 5adf6dfeb08..5c2520c58cf 100644 --- a/src/EditorFeatures/CSharp/Formatting/CSharpEditorFormattingService.cs +++ b/src/EditorFeatures/CSharp/Formatting/CSharpEditorFormattingService.cs @@ -138,10 +138,25 @@ private static bool TokenShouldNotFormatOnReturn(SyntaxToken token) return !token.IsKind(SyntaxKind.CloseParenToken) || !token.Parent.IsKind(SyntaxKind.UsingStatement); } - private static bool TokenShouldNotFormatOnTypeChar(SyntaxToken token) + private static bool TokenShouldNotFormatOnTypeChar( + SyntaxToken token, CancellationToken cancellationToken) { - return (token.IsKind(SyntaxKind.CloseParenToken) && !token.Parent.IsKind(SyntaxKind.UsingStatement)) || - (token.IsKind(SyntaxKind.ColonToken) && !(token.Parent.IsKind(SyntaxKind.LabeledStatement) || token.Parent is SwitchLabelSyntax)); + if (token.IsKind(SyntaxKind.CloseParenToken) && !token.Parent.IsKind(SyntaxKind.UsingStatement)) + { + return true; + } + + if (token.IsKind(SyntaxKind.ColonToken) && !(token.Parent.IsKind(SyntaxKind.LabeledStatement) || token.Parent is SwitchLabelSyntax)) + { + return true; + } + + if (token.IsKind(SyntaxKind.OpenBraceToken) && !token.IsFirstTokenOnLine(token.SyntaxTree.GetText())) + { + return true; + } + + return false; } public async Task> GetFormattingChangesAsync(Document document, char typedChar, int caretPosition, CancellationToken cancellationToken) @@ -149,7 +164,7 @@ public async Task> GetFormattingChangesAsync(Document document var formattingRules = this.GetFormattingRules(document, caretPosition); // first, find the token user just typed. - SyntaxToken token = await GetTokenBeforeTheCaretAsync(document, caretPosition, cancellationToken).ConfigureAwait(false); + var token = await GetTokenBeforeTheCaretAsync(document, caretPosition, cancellationToken).ConfigureAwait(false); if (token.IsMissing || !ValidSingleOrMultiCharactersTokenKind(typedChar, token.Kind()) || @@ -167,7 +182,8 @@ public async Task> GetFormattingChangesAsync(Document document // Check to see if any of the below. If not, bail. // case 1: The token is ')' and the parent is an using statement. // case 2: The token is ':' and the parent is either labelled statement or case switch or default switch - if (TokenShouldNotFormatOnTypeChar(token)) + // + if (TokenShouldNotFormatOnTypeChar(token, cancellationToken)) { return null; } diff --git a/src/EditorFeatures/CSharp/Formatting/Indentation/SmartTokenFormatter.cs b/src/EditorFeatures/CSharp/Formatting/Indentation/SmartTokenFormatter.cs index 703f68bc441..48f188d4c71 100644 --- a/src/EditorFeatures/CSharp/Formatting/Indentation/SmartTokenFormatter.cs +++ b/src/EditorFeatures/CSharp/Formatting/Indentation/SmartTokenFormatter.cs @@ -68,7 +68,8 @@ private bool CloseBraceOfTryOrDoBlock(SyntaxToken endToken) (endToken.Parent.IsParentKind(SyntaxKind.TryStatement) || endToken.Parent.IsParentKind(SyntaxKind.DoStatement)); } - public Task> FormatTokenAsync(Workspace workspace, SyntaxToken token, CancellationToken cancellationToken) + public Task> FormatTokenAsync( + Workspace workspace, SyntaxToken token, CancellationToken cancellationToken) { Contract.ThrowIfTrue(token.Kind() == SyntaxKind.None || token.Kind() == SyntaxKind.EndOfFileToken); @@ -100,7 +101,9 @@ public Task> FormatTokenAsync(Workspace workspace, SyntaxToken var smartTokenformattingRules = (new SmartTokenFormattingRule()).Concat(_formattingRules); var adjustedStartPosition = previousToken.SpanStart; var indentStyle = _optionSet.GetOption(FormattingOptions.SmartIndent, LanguageNames.CSharp); - if (token.IsKind(SyntaxKind.OpenBraceToken) && token.IsFirstTokenOnLine(token.SyntaxTree.GetText()) && indentStyle != FormattingOptions.IndentStyle.Smart) + if (token.IsKind(SyntaxKind.OpenBraceToken) && + token.IsFirstTokenOnLine(token.SyntaxTree.GetText(cancellationToken)) && + indentStyle != FormattingOptions.IndentStyle.Smart) { adjustedStartPosition = token.SpanStart; } diff --git a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs index 3eeed282793..7248f013bd4 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/FormattingEngineTests.cs @@ -6,6 +6,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Editor.Commands; using Microsoft.CodeAnalysis.Editor.Implementation.Formatting; +using Microsoft.CodeAnalysis.Editor.Options; using Microsoft.CodeAnalysis.Editor.Shared.Options; using Microsoft.CodeAnalysis.Editor.UnitTests.Utilities; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; @@ -1142,6 +1143,64 @@ class C await AssertFormatAfterTypeCharAsync(code, expected, optionSet); } + [WpfFact, WorkItem(4435, "https://github.com/dotnet/roslyn/issues/4435")] + [Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)] + public async Task OpenCurlyNotFormattedIfNotAtStartOfLine() + { + var code = +@" +class C +{ + public int P {$$ +} +"; + + var expected = +@" +class C +{ + public int P { +} +"; + + var optionSet = new Dictionary + { + { new OptionKey(BraceCompletionOptions.EnableBraceCompletion, LanguageNames.CSharp), false } + }; + + await AssertFormatAfterTypeCharAsync(code, expected); + } + + [WpfFact, WorkItem(4435, "https://github.com/dotnet/roslyn/issues/4435")] + [Trait(Traits.Feature, Traits.Features.SmartTokenFormatting)] + public async Task OpenCurlyFormattedIfAtStartOfLine() + { + var code = +@" +class C +{ + public int P + {$$ +} +"; + + var expected = +@" +class C +{ + public int P + { +} +"; + + var optionSet = new Dictionary + { + { new OptionKey(BraceCompletionOptions.EnableBraceCompletion, LanguageNames.CSharp), false } + }; + + await AssertFormatAfterTypeCharAsync(code, expected); + } + [WpfFact, Trait(Traits.Feature, Traits.Features.Formatting)] public async Task DoNotFormatIncompleteBlockOnSingleLineIfNotTypingCloseCurly1() { -- GitLab