From f284f21cb4d80ea687409cdd94e40cd5e6f56708 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Sat, 13 Feb 2021 18:39:44 +0100 Subject: [PATCH 1/8] https://github.com/dotnet/roslyn/issues/50742 fix normalize whitespace --- .../Portable/Syntax/SyntaxNormalizer.cs | 25 +++++++++++++++++++ .../Test/Syntax/Syntax/SyntaxFactoryTests.cs | 12 +++++++++ 2 files changed, 37 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs index a362cb4c12612..753be322fdbdb 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs @@ -27,6 +27,7 @@ internal class SyntaxNormalizer : CSharpSyntaxRewriter private bool _afterLineBreak; private bool _afterIndentation; + private bool _inSingleLineInterpolation; // CONSIDER: if we become concerned about space, we shouldn't actually need any // of the values between indentations[0] and indentations[initialDepth] (exclusive). @@ -177,6 +178,11 @@ private static bool NeedsIndentAfterLineBreak(SyntaxToken token) private int LineBreaksAfter(SyntaxToken currentToken, SyntaxToken nextToken) { + if (_inSingleLineInterpolation) + { + return 0; + } + if (currentToken.IsKind(SyntaxKind.EndOfDirectiveToken)) { return 1; @@ -915,5 +921,24 @@ node is QueryExpressionSyntax || return 0; } + + public override SyntaxNode? VisitInterpolatedStringExpression(InterpolatedStringExpressionSyntax node) + { + if (node.StringStartToken.Kind() == SyntaxKind.InterpolatedStringStartToken) + { + var old = _inSingleLineInterpolation; + _inSingleLineInterpolation = true; + try + { + return base.VisitInterpolatedStringExpression(node); + } + finally + { + _inSingleLineInterpolation = old; + } + } + + return base.VisitInterpolatedStringExpression(node); + } } } diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs index e2f6c14aea80a..79792f243faf3 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs @@ -534,6 +534,18 @@ public void TestSpacingOnTernary() Assert.Equal("x is DateTime ? y : z", syntaxNode2.ToFullString()); } + [Fact] + [WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] + public void TestLineBreakInterpolations() + { + var code = @"$""Printed: { new Printer() { TextToPrint = ""Hello world!"" }.PrintedText }"""; + + var syntaxNode = SyntaxFactory.ParseExpression(code).NormalizeWhitespace(); + var aText = syntaxNode.ToFullString(); + + Assert.True(!aText.Contains('\n')); + } + [Fact] [WorkItem(21231, "https://github.com/dotnet/roslyn/issues/21231")] public void TestSpacingOnCoalescing() From 1dabbaf60b354a6589d88195bfef3e2870eacda5 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Sat, 13 Feb 2021 20:26:54 +0100 Subject: [PATCH 2/8] test updated --- .../Test/Syntax/Syntax/SyntaxFactoryTests.cs | 12 ------------ .../Test/Syntax/Syntax/SyntaxNormalizerTests.cs | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs index 79792f243faf3..e2f6c14aea80a 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxFactoryTests.cs @@ -534,18 +534,6 @@ public void TestSpacingOnTernary() Assert.Equal("x is DateTime ? y : z", syntaxNode2.ToFullString()); } - [Fact] - [WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] - public void TestLineBreakInterpolations() - { - var code = @"$""Printed: { new Printer() { TextToPrint = ""Hello world!"" }.PrintedText }"""; - - var syntaxNode = SyntaxFactory.ParseExpression(code).NormalizeWhitespace(); - var aText = syntaxNode.ToFullString(); - - Assert.True(!aText.Contains('\n')); - } - [Fact] [WorkItem(21231, "https://github.com/dotnet/roslyn/issues/21231")] public void TestSpacingOnCoalescing() diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs index 341ab42ae6fb5..23b62f7af2a13 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs @@ -16,6 +16,20 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class SyntaxNormalizerTests { + [Fact] + [WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] + public void TestLineBreakInterpolations() + { + var code = @"$""Printed: { new Printer() { TextToPrint = ""Hello world!"" }.PrintedText }"""; + + var syntaxNode = SyntaxFactory.ParseExpression(code).NormalizeWhitespace(); + var text = syntaxNode.ToFullString(); + + //we test only for line breaks because they caused that the produced text couldn't be parsed after NormalizeWhitespace + //the concrete formatting (e.g. spaces, tabs) should be ignored here + Assert.True(!text.Contains('\n')); + } + [Fact] public void TestNormalizeExpression1() { From 800119c06db633787bb93cdc03f2f33b2e5049b0 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Sat, 13 Feb 2021 20:33:42 +0100 Subject: [PATCH 3/8] comment added to VisitInterpolatedStringExpression --- src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs index 753be322fdbdb..2c7a9df8153a6 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs @@ -926,6 +926,13 @@ node is QueryExpressionSyntax || { if (node.StringStartToken.Kind() == SyntaxKind.InterpolatedStringStartToken) { + /* + * Just for non verbatim strings we want to make sure that the formatting of interpolations does not emit line breaks. + * See: https://github.com/dotnet/roslyn/issues/50742 + * + * The flag _inSingleLineInterpolation is set to true while visiting InterpolatedStringExpressionSyntax and checked in LineBreaksAfter + * to suppress adding newlines. + */ var old = _inSingleLineInterpolation; _inSingleLineInterpolation = true; try From a340856b64f20905336ddb5987e9fe79711c5996 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Sat, 13 Feb 2021 20:56:46 +0100 Subject: [PATCH 4/8] TestVerbatimStringInterpolationWithLineBreaks added, TestLineBreakInterpolations extended --- .../Syntax/Syntax/SyntaxNormalizerTests.cs | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs index 23b62f7af2a13..0d29fb7e75b83 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs @@ -27,7 +27,29 @@ public void TestLineBreakInterpolations() //we test only for line breaks because they caused that the produced text couldn't be parsed after NormalizeWhitespace //the concrete formatting (e.g. spaces, tabs) should be ignored here - Assert.True(!text.Contains('\n')); + Assert.True(!text.Contains("\n")); + + var parsed = SyntaxFactory.ParseExpression(text); + Assert.False(parsed.HasErrors); + } + + [Fact] + [WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] + public void TestVerbatimStringInterpolationWithLineBreaks() + { + var code = @"Console.WriteLine($@""Test with line +breaks +{ + new[]{ + 1, 2, 3 + }[2] +} + "");"; + + var syntaxNode = SyntaxFactory.ParseStatement(code).NormalizeWhitespace(); + var text = syntaxNode.ToFullString(); + var parsed = SyntaxFactory.ParseStatement(text); + Assert.False(parsed.HasErrors); } [Fact] From ae26e1bfb46630cc28186f9b72f37ae306d38943 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Sat, 13 Feb 2021 21:22:28 +0100 Subject: [PATCH 5/8] Update src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs Co-authored-by: CyrusNajmabadi --- .../CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs index 0d29fb7e75b83..c49edd53ffcf4 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs @@ -16,8 +16,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class SyntaxNormalizerTests { - [Fact] - [WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] + [Fact, WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] public void TestLineBreakInterpolations() { var code = @"$""Printed: { new Printer() { TextToPrint = ""Hello world!"" }.PrintedText }"""; From 90689a1f35e4f16fe02170d2e94ad788966fe9c4 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Sat, 13 Feb 2021 21:24:43 +0100 Subject: [PATCH 6/8] comment style changed --- .../CSharp/Portable/Syntax/SyntaxNormalizer.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs index 2c7a9df8153a6..46b26c57c47ef 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxNormalizer.cs @@ -926,13 +926,11 @@ node is QueryExpressionSyntax || { if (node.StringStartToken.Kind() == SyntaxKind.InterpolatedStringStartToken) { - /* - * Just for non verbatim strings we want to make sure that the formatting of interpolations does not emit line breaks. - * See: https://github.com/dotnet/roslyn/issues/50742 - * - * The flag _inSingleLineInterpolation is set to true while visiting InterpolatedStringExpressionSyntax and checked in LineBreaksAfter - * to suppress adding newlines. - */ + //Just for non verbatim strings we want to make sure that the formatting of interpolations does not emit line breaks. + //See: https://github.com/dotnet/roslyn/issues/50742 + // + //The flag _inSingleLineInterpolation is set to true while visiting InterpolatedStringExpressionSyntax and checked in LineBreaksAfter + //to suppress adding newlines. var old = _inSingleLineInterpolation; _inSingleLineInterpolation = true; try From bf68fcffed83ffb7a4705a54cff809933b5f5e41 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Sat, 13 Feb 2021 21:54:08 +0100 Subject: [PATCH 7/8] usage of TestNormalizeExpression and TestNormalizeStatement --- .../Syntax/Syntax/SyntaxNormalizerTests.cs | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs index c49edd53ffcf4..5f841d0e7f0d1 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs @@ -19,36 +19,29 @@ public class SyntaxNormalizerTests [Fact, WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] public void TestLineBreakInterpolations() { - var code = @"$""Printed: { new Printer() { TextToPrint = ""Hello world!"" }.PrintedText }"""; - - var syntaxNode = SyntaxFactory.ParseExpression(code).NormalizeWhitespace(); - var text = syntaxNode.ToFullString(); - - //we test only for line breaks because they caused that the produced text couldn't be parsed after NormalizeWhitespace - //the concrete formatting (e.g. spaces, tabs) should be ignored here - Assert.True(!text.Contains("\n")); - - var parsed = SyntaxFactory.ParseExpression(text); - Assert.False(parsed.HasErrors); + TestNormalizeExpression( + @"$""Printed: { new Printer() { TextToPrint = ""Hello world!"" }.PrintedText }""", + @"$""Printed: {new Printer(){TextToPrint = ""Hello world!""}.PrintedText}""" + ); } [Fact] [WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] public void TestVerbatimStringInterpolationWithLineBreaks() { - var code = @"Console.WriteLine($@""Test with line + TestNormalizeStatement(@"Console.WriteLine($@""Test with line breaks { new[]{ 1, 2, 3 }[2] } - "");"; - - var syntaxNode = SyntaxFactory.ParseStatement(code).NormalizeWhitespace(); - var text = syntaxNode.ToFullString(); - var parsed = SyntaxFactory.ParseStatement(text); - Assert.False(parsed.HasErrors); + "");", + @"Console.WriteLine($@""Test with line +breaks +{new[]{1, 2, 3}[2]} + "");" + ); } [Fact] From 50592f1da83ab49027b4fb9c39bec01dbd6da839 Mon Sep 17 00:00:00 2001 From: Bernd Baumanns Date: Mon, 15 Feb 2021 21:30:29 +0100 Subject: [PATCH 8/8] Keep attributes together --- .../CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs index 5f841d0e7f0d1..4101ceb06b9cc 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxNormalizerTests.cs @@ -25,8 +25,7 @@ public void TestLineBreakInterpolations() ); } - [Fact] - [WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] + [Fact, WorkItem(50742, "https://github.com/dotnet/roslyn/issues/50742")] public void TestVerbatimStringInterpolationWithLineBreaks() { TestNormalizeStatement(@"Console.WriteLine($@""Test with line