diff --git a/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.Indenter.cs b/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.Indenter.cs index 6b925a476f6b32e1388778a24cf7384c64088c57..c9bf25f5236c0209ee44282763fa1a9f95d646c4 100644 --- a/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.Indenter.cs +++ b/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.Indenter.cs @@ -136,8 +136,14 @@ internal class Indenter : AbstractIndenter Contract.ThrowIfTrue(token.Kind() == SyntaxKind.None); // special cases - // if token belongs to verbatim token literal - if (token.IsVerbatimStringLiteral()) + // case 1: token belongs to verbatim token literal + // case 2: $@"$${0}" + // case 3: $@"Comment$$ inbetween{0}" + // case 4: $@"{0}$$" + if (token.IsVerbatimStringLiteral() || + token.IsKind(SyntaxKind.InterpolatedVerbatimStringStartToken) || + token.IsKind(SyntaxKind.InterpolatedStringTextToken) || + (token.IsKind(SyntaxKind.CloseBraceToken) && token.Parent.IsKind(SyntaxKind.Interpolation))) { return IndentFromStartOfLine(0); } diff --git a/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.cs b/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.cs index f40200c04cbe5a2115325135f6e632e1056110c2..b06fb290015e08083c0e293a703b5ecf60242a48 100644 --- a/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.cs +++ b/src/EditorFeatures/CSharp/Formatting/Indentation/CSharpIndentationService.cs @@ -86,7 +86,7 @@ protected override AbstractIndenter GetIndenter(Document document, ITextSnapshot } var lineOperation = FormattingOperations.GetAdjustNewLinesOperation(formattingRules, previousToken, token, optionSet); - if (lineOperation != null) + if (lineOperation != null && lineOperation.Option != AdjustNewLinesOption.ForceLinesIfOnSingleLine) { return true; } @@ -109,7 +109,8 @@ public override void AddIndentBlockOperations(List list, S if (node is BaseParameterListSyntax || node is TypeArgumentListSyntax || - node is TypeParameterListSyntax) + node is TypeParameterListSyntax || + node.IsKind(SyntaxKind.Interpolation)) { AddIndentBlockOperations(list, node); return; diff --git a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs index efc84e77850a7990cf92f973dd3922edf34fcd0e..d8fc26b271c66ebfecb1f2cadd5b569f17597248 100644 --- a/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs +++ b/src/EditorFeatures/CSharpTest/Formatting/Indentation/SmartIndenterEnterOnTokenTests.cs @@ -978,6 +978,280 @@ class What expectedIndentation: 8); } + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationString_1() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@"" +{Program.number}""; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 0); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationString_2() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@""Comment +{Program.number}""; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 0); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationString_3() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@""Comment{Program.number} +""; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 0); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationString_4() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@""Comment{Program.number}Comment here +""; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 0); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void OutsideInterpolationString() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@""Comment{Program.number}Comment here"" +; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 12); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationSyntax_1() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@""{ +Program.number}""; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 12); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationSyntax_2() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@""{ + Program +.number}""; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 6, + expectedIndentation: 12); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationSyntax_3() + { + var code = @"class Program +{ + static void Main(string[] args) + { + var s = $@""{ +}""; + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 12); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationSyntax_4() + { + var code = @"class Program +{ + static void Main(string[] args) + { + Console.WriteLine($@""PPP{ +((Func)((int s) => { return number; })).Invoke(3):(408) ###-####}""); + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 12); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationSyntax_5() + { + var code = @"class Program +{ + static void Main(string[] args) + { + Console.WriteLine($@""PPP{ ((Func)((int s) +=> { return number; })).Invoke(3):(408) ###-####}""); + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 12); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationSyntax_6() + { + var code = @"class Program +{ + static void Main(string[] args) + { + Console.WriteLine($@""PPP{ ((Func)((int s) => { return number; })) +.Invoke(3):(408) ###-####}""); + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 12); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void InsideInterpolationSyntax_7() + { + var code = @"class Program +{ + static void Main(string[] args) + { + Console.WriteLine($@""PPP{ ((Func)((int s) => +{ return number; })).Invoke(3):(408) ###-####}""); + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 8); + } + + [Fact] + [WorkItem(872)] + [Trait(Traits.Feature, Traits.Features.SmartIndent)] + public void IndentLambdaBodyOneIndentationToFirstTokenOfTheStatement() + { + var code = @"class Program +{ + static void Main(string[] args) + { + Console.WriteLine(((Func)((int s) => +{ return number; })).Invoke(3)); + } + + static int number; +}"; + AssertIndentNotUsingSmartTokenFormatterButUsingIndenter( + code, + indentationLine: 5, + expectedIndentation: 8); + } + private void AssertIndentUsingSmartTokenFormatter( string code, char ch,