1 //===- unittest/Format/FormatTestCSharp.cpp - Formatting tests for CSharp -===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "FormatTestBase.h"
11 #define DEBUG_TYPE "format-test"
18 class FormatTestCSharp
: public test::FormatTestBase
{
20 FormatStyle
getDefaultStyle() const override
{
21 return getMicrosoftStyle(FormatStyle::LK_CSharp
);
24 static std::string
format(StringRef Code
, unsigned Offset
, unsigned Length
,
25 const FormatStyle
&Style
) {
26 LLVM_DEBUG(llvm::errs() << "---\n");
27 LLVM_DEBUG(llvm::errs() << Code
<< "\n\n");
28 std::vector
<tooling::Range
> Ranges(1, tooling::Range(Offset
, Length
));
29 tooling::Replacements Replaces
= reformat(Style
, Code
, Ranges
);
30 auto Result
= applyAllReplacements(Code
, Replaces
);
31 EXPECT_TRUE(static_cast<bool>(Result
));
32 LLVM_DEBUG(llvm::errs() << "\n" << *Result
<< "\n\n");
37 format(StringRef Code
,
38 const FormatStyle
&Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
)) {
39 return format(Code
, 0, Code
.size(), Style
);
42 static FormatStyle
getStyleWithColumns(unsigned ColumnLimit
) {
43 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
44 Style
.ColumnLimit
= ColumnLimit
;
49 TEST_F(FormatTestCSharp
, CSharpClass
) {
50 verifyFormat("public class SomeClass\n"
70 // Ensure that small and empty classes are handled correctly with condensed
71 // (Google C++-like) brace-breaking style.
72 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
73 Style
.BreakBeforeBraces
= FormatStyle::BS_Attach
;
75 verifyFormat("public class SomeEmptyClass {}", Style
);
77 verifyFormat("public class SomeTinyClass {\n"
81 verifyFormat("private class SomeTinyClass {\n"
85 verifyFormat("protected class SomeTinyClass {\n"
89 verifyFormat("internal class SomeTinyClass {\n"
95 TEST_F(FormatTestCSharp
, AccessModifiers
) {
96 verifyFormat("public String toString()\n"
99 verifyFormat("private String toString()\n"
102 verifyFormat("protected String toString()\n"
105 verifyFormat("internal String toString()\n"
109 verifyFormat("public override String toString()\n"
112 verifyFormat("private override String toString()\n"
115 verifyFormat("protected override String toString()\n"
118 verifyFormat("internal override String toString()\n"
122 verifyFormat("internal static String toString()\n"
127 TEST_F(FormatTestCSharp
, NoStringLiteralBreaks
) {
128 // Breaking of interpolated strings is not implemented.
129 auto Style
= getDefaultStyle();
130 Style
.ColumnLimit
= 40;
131 Style
.BreakStringLiterals
= true;
133 "$\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
138 TEST_F(FormatTestCSharp
, StringLiteralBreaks
) {
139 // The line is 75 characters long. The default limit for the Microsoft style
141 auto Style
= getDefaultStyle();
142 Style
.BreakStringLiterals
= true;
144 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
147 // When the column limit is smaller, the string should get broken.
148 Style
.ColumnLimit
= 40;
149 verifyFormat(R
"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
" +
150 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
" +
153 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
156 // The new quotes should be the same as the original.
157 verifyFormat(R
"(foo(@"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
" +
158 @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
" +
161 "@\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
164 // The operators can be on either line.
165 Style
.BreakBeforeBinaryOperators
= FormatStyle::BOS_NonAssignment
;
166 verifyFormat(R
"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"
167 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"
170 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
173 Style
.AlignOperands
= FormatStyle::OAS_AlignAfterOperator
;
174 verifyFormat(R
"(foo("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"
175 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"
178 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
181 verifyFormat(R
"(x = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
"
182 + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
";)",
184 "\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
189 TEST_F(FormatTestCSharp
, CSharpVerbatiumStringLiterals
) {
190 verifyFormat("foo(@\"aaaaaaaa\\abc\\aaaa\");");
191 // @"ABC\" + ToString("B") - handle embedded \ in literal string at
195 * After removal of Lexer change we are currently not able
196 * To handle these cases
197 verifyFormat("string s = @\"ABC\\\" + ToString(\"B\");");
198 verifyFormat("string s = @\"ABC\"\"DEF\"\"GHI\"");
199 verifyFormat("string s = @\"ABC\"\"DEF\"\"\"");
200 verifyFormat("string s = @\"ABC\"\"DEF\"\"\" + abc");
204 TEST_F(FormatTestCSharp
, CSharpInterpolatedStringLiterals
) {
205 verifyFormat("foo($\"aaaaaaaa{aaa}aaaa\");");
206 verifyFormat("foo($\"aaaa{A}\");");
209 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\");");
210 verifyFormat("Name = $\"{firstName} {lastName}\";");
212 // $"ABC\" + ToString("B") - handle embedded \ in literal string at
214 verifyFormat("string s = $\"A{abc}BC\" + ToString(\"B\");");
215 verifyFormat("$\"{domain}\\\\{user}\"");
217 "var verbatimInterpolated = $@\"C:\\Users\\{userName}\\Documents\\\";");
220 TEST_F(FormatTestCSharp
, CSharpFatArrows
) {
221 verifyIncompleteFormat("Task serverTask = Task.Run(async() => {");
222 verifyFormat("public override string ToString() => \"{Name}\\{Age}\";");
225 TEST_F(FormatTestCSharp
, CSharpConditionalExpressions
) {
226 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
227 // conditional expression is not seen as a NullConditional.
228 verifyFormat("var y = A < B ? -1 : 1;", Style
);
231 TEST_F(FormatTestCSharp
, CSharpNullConditional
) {
232 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
233 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Always
;
236 "public Person(string firstName, string lastName, int? age = null)");
238 verifyFormat("foo () {\n"
239 " switch (args?.Length) {}\n"
243 verifyFormat("switch (args?.Length) {}", Style
);
245 verifyFormat("public static void Main(string[] args)\n"
247 " string dirPath = args?[0];\n"
250 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Never
;
252 verifyFormat("switch(args?.Length) {}", Style
);
255 TEST_F(FormatTestCSharp
, Attributes
) {
256 verifyFormat("[STAThread]\n"
257 "static void Main(string[] args)\n"
261 verifyFormat("[TestMethod]\n"
262 "private class Test\n"
266 verifyFormat("[TestMethod]\n"
267 "protected class Test\n"
271 verifyFormat("[TestMethod]\n"
272 "internal class Test\n"
276 verifyFormat("[TestMethod]\n"
281 verifyFormat("[TestMethod]\n"
282 "[DeploymentItem(\"Test.txt\")]\n"
283 "public class Test\n"
287 verifyFormat("[System.AttributeUsage(System.AttributeTargets.Method)]\n"
288 "[System.Runtime.InteropServices.ComVisible(true)]\n"
289 "public sealed class STAThreadAttribute : Attribute\n"
293 verifyFormat("[Verb(\"start\", HelpText = \"Starts the server listening on "
294 "provided port\")]\n"
299 verifyFormat("[TestMethod]\n"
300 "public string Host { set; get; }");
302 // Adjacent properties should not cause line wrapping issues
303 verifyFormat("[JsonProperty(\"foo\")]\n"
304 "public string Foo { set; get; }\n"
305 "[JsonProperty(\"bar\")]\n"
306 "public string Bar { set; get; }\n"
307 "[JsonProperty(\"bar\")]\n"
308 "protected string Bar { set; get; }\n"
309 "[JsonProperty(\"bar\")]\n"
310 "internal string Bar { set; get; }");
312 // Multiple attributes should always be split (not just the first ones)
313 verifyFormat("[XmlIgnore]\n"
314 "[JsonProperty(\"foo\")]\n"
315 "public string Foo { set; get; }");
317 verifyFormat("[XmlIgnore]\n"
318 "[JsonProperty(\"foo\")]\n"
319 "public string Foo { set; get; }\n"
321 "[JsonProperty(\"bar\")]\n"
322 "public string Bar { set; get; }");
324 verifyFormat("[XmlIgnore]\n"
326 "[JsonProperty(\"foo\")]\n"
327 "public string Foo { set; get; }\n"
330 "[JsonProperty(\"bar\")]\n"
331 "public string Bar { set; get; }");
333 verifyFormat("[TestMethod(\"start\", HelpText = \"Starts the server "
334 "listening on provided host\")]\n"
335 "public string Host { set; get; }");
337 verifyIncompleteFormat(
338 "[DllImport(\"Hello\", EntryPoint = \"hello_world\")]\n"
339 "// The const char* returned by hello_world must not be deleted.\n"
340 "private static extern IntPtr HelloFromCpp();)");
342 // Class attributes go on their own line and do not affect layout of
343 // interfaces. Line wrapping decisions previously caused each interface to be
345 verifyFormat("[SomeAttribute]\n"
346 "[SomeOtherAttribute]\n"
347 "public class A : IShape, IAnimal, IVehicle\n"
352 // Attributes in a method declaration do not cause line wrapping.
353 verifyFormat("void MethodA([In][Out] ref double x)\n"
357 verifyFormat("void MethodA([In, Out] ref double x)\n"
361 verifyFormat("void MethodA([In, Out] double[] x)\n"
365 verifyFormat("void MethodA([In] double[] x)\n"
369 verifyFormat("void MethodA(int[] x)\n"
372 verifyFormat("void MethodA(int[][] x)\n"
375 verifyFormat("void MethodA([] x)\n"
379 verifyFormat("public void Log([CallerLineNumber] int line = -1, "
380 "[CallerFilePath] string path = null,\n"
381 " [CallerMemberName] string name = null)\n"
385 // [] in an attribute do not cause premature line wrapping or indenting.
389 [SomeAttribute(new[] { RED, GREEN, BLUE }, -1.0f, 1.0f)]
391 public Data MemberVariable;
394 // Unwrappable lines go on a line of their own.
395 // 'target:' is not treated as a label.
396 // Modify Style to enforce a column limit.
397 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
398 Style
.ColumnLimit
= 10;
399 verifyFormat(R
"([assembly:InternalsVisibleTo(
400 "SomeAssembly
, PublicKey
=SomePublicKeyThatExceedsTheColumnLimit
")])",
404 TEST_F(FormatTestCSharp
, CSharpUsing
) {
405 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
406 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Always
;
407 verifyFormat("public void foo () {\n"
408 " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
413 // Ensure clang-format affects top-level snippets correctly.
414 verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
417 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Never
;
418 verifyFormat("public void foo() {\n"
419 " using(StreamWriter sw = new StreamWriter(filenameB)) {}\n"
424 // Ensure clang-format affects top-level snippets correctly.
425 verifyFormat("using(StreamWriter sw = new StreamWriter(filenameB)) {}",
428 Style
.SpaceBeforeParens
= FormatStyle::SBPO_ControlStatements
;
429 verifyFormat("public void foo() {\n"
430 " using (StreamWriter sw = new StreamWriter(filenameA)) {}\n"
435 // Ensure clang-format affects top-level snippets correctly.
436 verifyFormat("using (StreamWriter sw = new StreamWriter(filenameB)) {}",
439 Style
.SpaceBeforeParens
= FormatStyle::SBPO_NonEmptyParentheses
;
440 verifyFormat("public void foo() {\n"
441 " using (StreamWriter sw = new StreamWriter (filenameA)) {}\n"
446 // Ensure clang-format affects top-level snippets correctly.
447 verifyFormat("using (StreamWriter sw = new StreamWriter (filenameB)) {}",
451 TEST_F(FormatTestCSharp
, CSharpRegions
) {
452 verifyFormat("#region aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaa "
453 "aaaaaaaaaaaaaaa long region");
456 TEST_F(FormatTestCSharp
, CSharpKeyWordEscaping
) {
457 // AfterEnum is true by default.
458 verifyFormat("public enum var\n"
467 TEST_F(FormatTestCSharp
, CSharpNullCoalescing
) {
468 verifyFormat("var test = ABC ?? DEF");
469 verifyFormat("string myname = name ?? \"ABC\";");
470 verifyFormat("return _name ?? \"DEF\";");
473 TEST_F(FormatTestCSharp
, CSharpNullCoalescingAssignment
) {
474 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
475 Style
.SpaceBeforeAssignmentOperators
= true;
477 verifyFormat(R
"(test ??= ABC;)", Style
);
478 verifyFormat(R
"(test ??= true;)", Style
);
480 Style
.SpaceBeforeAssignmentOperators
= false;
482 verifyFormat(R
"(test??= ABC;)", Style
);
483 verifyFormat(R
"(test??= true;)", Style
);
486 TEST_F(FormatTestCSharp
, CSharpNullForgiving
) {
487 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
489 verifyFormat("var test = null!;", Style
);
490 verifyFormat("string test = someFunctionCall()! + \"ABC\"!", Style
);
491 verifyFormat("int test = (1! + 2 + bar! + foo())!", Style
);
492 verifyFormat(R
"(test ??= !foo!;)", Style
);
493 verifyFormat("test = !bar! ?? !foo!;", Style
);
494 verifyFormat("bool test = !(!true && !true! || !null && !null! || !false && "
495 "!false! && !bar()! + (!foo()))!",
498 // Check that line break keeps identifier with the bang.
499 Style
.ColumnLimit
= 14;
501 verifyFormat("var test =\n"
506 TEST_F(FormatTestCSharp
, AttributesIndentation
) {
507 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
508 Style
.BreakAfterReturnType
= FormatStyle::RTBS_None
;
510 verifyFormat("[STAThread]\n"
511 "static void Main(string[] args)\n"
516 verifyFormat("[STAThread]\n"
518 "veryLooooooooooooooongFunctionName(string[] args)\n"
523 verifyFormat("[STAThread]\n"
524 "veryLoooooooooooooooooooongReturnType "
525 "veryLooooooooooooooongFunctionName(string[] args)\n"
530 verifyFormat("[SuppressMessage(\"A\", \"B\", Justification = \"C\")]\n"
531 "public override X Y()\n"
536 verifyFormat("[SuppressMessage]\n"
542 verifyFormat("[SuppressMessage]\n"
543 "public override X Y()\n"
548 verifyFormat("public A(B b) : base(b)\n"
550 " [SuppressMessage]\n"
551 " public override X Y()\n"
557 verifyFormat("public A : Base\n"
566 verifyFormat("namespace\n"
579 TEST_F(FormatTestCSharp
, CSharpSpaceBefore
) {
580 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
581 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Always
;
583 verifyFormat("List<string> list;", Style
);
584 verifyFormat("Dictionary<string, string> dict;", Style
);
586 verifyFormat("for (int i = 0; i < size (); i++) {\n"
589 verifyFormat("foreach (var x in y) {\n"
592 verifyFormat("switch (x) {}", Style
);
593 verifyFormat("do {\n"
597 Style
.SpaceBeforeParens
= FormatStyle::SBPO_Never
;
599 verifyFormat("List<string> list;", Style
);
600 verifyFormat("Dictionary<string, string> dict;", Style
);
602 verifyFormat("for(int i = 0; i < size(); i++) {\n"
605 verifyFormat("foreach(var x in y) {\n"
608 verifyFormat("switch(x) {}", Style
);
609 verifyFormat("do {\n"
614 TEST_F(FormatTestCSharp
, CSharpSpaceAfterCStyleCast
) {
615 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
617 verifyFormat("(int)x / y;", Style
);
619 Style
.SpaceAfterCStyleCast
= true;
620 verifyFormat("(int) x / y;", Style
);
623 TEST_F(FormatTestCSharp
, CSharpEscapedQuotesInVerbatimStrings
) {
624 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
626 verifyFormat(R
"(string str = @"""";)", Style
);
627 verifyFormat(R
"(string str = @"""Hello world
""";)", Style
);
628 verifyFormat(R
"(string str = $@"""Hello
{friend}""";)", Style
);
629 verifyFormat(R
"(return $@"Foo
""/foo
?f
={Request
.Query
["f"]}""";)", Style
);
630 verifyFormat(R
"(return @$"Foo
""/foo
?f
={Request
.Query
["f"]}""";)", Style
);
631 verifyFormat(R
"(return @$"path
\to\
{specifiedFile
}")", Style
);
634 TEST_F(FormatTestCSharp
, CSharpQuotesInInterpolatedStrings
) {
635 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
637 verifyFormat(R
"(string str1 = $"{null
?? "null"}";)", Style
);
638 verifyFormat(R
"(string str2 = $"{{{braceCount
} braces
";)", Style
);
639 verifyFormat(R
"(string str3 = $"{braceCount
}}} braces
";)", Style
);
642 TEST_F(FormatTestCSharp
, CSharpNewlinesInVerbatimStrings
) {
643 // Use MS style as Google Style inserts a line break before multiline strings.
645 // verifyFormat does not understand multiline C# string-literals
646 // so check the format explicitly.
648 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
650 std::string Code
= R
"(string s1 = $@"some code
:
655 EXPECT_EQ(Code
, format(Code
, Style
));
657 // Multiline string in the middle of a function call.
659 var x = foo(className, $@"some code
:
663 y);)"; // y aligned with `className` arg.
665 EXPECT_EQ(Code
, format(Code
, Style
));
667 // Interpolated string with embedded multiline string.
668 Code
= R
"(Console.WriteLine($"{string
.Join(@
",
671 EXPECT_EQ(Code
, format(Code
, Style
));
674 TEST_F(FormatTestCSharp
, CSharpNewOperator
) {
675 FormatStyle Style
= getLLVMStyle(FormatStyle::LK_CSharp
);
677 verifyFormat("public void F() {\n"
678 " var v = new C(() => { var t = 5; });\n"
681 verifyFormat("public void F() {\n"
682 " var v = new C(() => {\n"
692 TEST_F(FormatTestCSharp
, CSharpLambdas
) {
693 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
694 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
698 Action<string> greet = name => {
699 string greeting = $"Hello
{name
}!";
700 Console.WriteLine(greeting);
706 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions#statement-lambdas
710 Action<string> greet = name =>
712 string greeting = $"Hello
{name
}!";
713 Console.WriteLine(greeting);
718 verifyFormat("void bar()\n"
720 " Function(Val, (Action)(() =>\n"
733 verifyFormat("void baz()\n"
735 " Function(Val, (Action)(() =>\n"
737 " using (var a = new Lock())\n"
748 verifyFormat("void baz()\n"
750 " Function(Val, (Action)(() =>\n"
760 verifyFormat("void baz()\n"
762 " Function(Val, (Action)(() =>\n"
772 verifyFormat("void baz()\n"
774 " Function(Val, (Action)(() =>\n"
775 " { A.Remove(item); }));\n"
779 verifyFormat("void bar()\n"
781 " Function(Val, (() =>\n"
793 verifyFormat("void bar()\n"
808 MicrosoftStyle
.IndentWidth
= 2;
809 verifyFormat("void bar()\n"
823 verifyFormat("void bar() {\n"
824 " Function((() => {\n"
835 TEST_F(FormatTestCSharp
, CSharpLambdasDontBreakFollowingCodeAlignment
) {
836 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
837 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
846 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
847 CodeThatFollowsLambda();
855 public class Sample {
858 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
859 CodeThatFollowsLambda();
867 TEST_F(FormatTestCSharp
, CSharpLambdasComplexLambdasDontBreakAlignment
) {
868 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
869 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
874 private static void ComplexLambda(BuildReport protoReport)
877 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
878 .Select(scene => scene.path)
880 if (allSelectedScenes.Count == 0)
894 private static void ComplexLambda(BuildReport protoReport) {
895 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
896 .Where(scene => scene.enabled)
897 .Select(scene => scene.path)
899 if (allSelectedScenes.Count == 0) {
911 TEST_F(FormatTestCSharp
, CSharpLambdasMulipleLambdasDontBreakAlignment
) {
912 FormatStyle GoogleStyle
= getGoogleStyle(FormatStyle::LK_CSharp
);
913 FormatStyle MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
918 private static void MultipleLambdas(BuildReport protoReport)
921 veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds.Where(scene => scene.enabled)
922 .Select(scene => scene.path)
924 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
925 if (allSelectedScenes.Count == 0)
939 private static void MultipleLambdas(BuildReport protoReport) {
940 allSelectedScenes = veryVeryLongCollectionNameThatPutsTheLineLenghtAboveTheThresholds
941 .Where(scene => scene.enabled)
942 .Select(scene => scene.path)
944 preBindEnumerators.RemoveAll(enumerator => !enumerator.MoveNext());
945 if (allSelectedScenes.Count == 0) {
957 TEST_F(FormatTestCSharp
, CSharpObjectInitializers
) {
958 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
960 // Start code fragments with a comment line so that C++ raw string literals
961 // as seen are identical to expected formatted code.
964 Shape[] shapes = new[] {
967 Colour = Colours.Red,
971 Colour = Colours.Yellow,
976 // Omitted final `,`s will change the formatting.
978 Shape[] shapes = new[] { new Circle { Radius = 2.7281, Colour = Colours.Red },
979 new Square { Side = 101.1, Colour = Colours.Yellow } };)",
982 // Lambdas can be supplied as initialiser arguments.
984 private Transformer _transformer = new X.Y {
985 Filler = (Shape shape) => { return new Transform.Fill(shape, RED); },
986 Scaler = (Shape shape) => { return new Transform.Resize(shape, 0.1); },
990 // Dictionary initialisation.
992 var myDict = new Dictionary<string, string> {
994 ["age
"] = Convert.ToString(DateTime.Today.Year - 1934),
1000 TEST_F(FormatTestCSharp
, CSharpArrayInitializers
) {
1001 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1004 private MySet<Node>[] setPoints = {
1011 TEST_F(FormatTestCSharp
, CSharpNamedArguments
) {
1012 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1015 PrintOrderDetails(orderNum: 31, productName: "Red Mug
", sellerName: "Gift Shop
");)",
1018 // Ensure that trailing comments do not cause problems.
1020 PrintOrderDetails(orderNum: 31, productName: "Red Mug
", // comment
1021 sellerName: "Gift Shop
");)",
1024 verifyFormat(R
"(foreach (var tickCount in task.Begin(seed: 0)) {)", Style
);
1027 TEST_F(FormatTestCSharp
, CSharpPropertyAccessors
) {
1028 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1030 verifyFormat("int Value { get }", Style
);
1031 verifyFormat("int Value { get; }", Style
);
1032 verifyFormat("int Value { internal get; }", Style
);
1033 verifyFormat("int Value { get; } = 0", Style
);
1034 verifyFormat("int Value { set }", Style
);
1035 verifyFormat("int Value { set; }", Style
);
1036 verifyFormat("int Value { init; }", Style
);
1037 verifyFormat("int Value { internal set; }", Style
);
1038 verifyFormat("int Value { set; } = 0", Style
);
1039 verifyFormat("int Value { get; set }", Style
);
1040 verifyFormat("int Value { get; init; }", Style
);
1041 verifyFormat("int Value { set; get }", Style
);
1042 verifyFormat("int Value { get; private set; }", Style
);
1043 verifyFormat("int Value { get; set; }", Style
);
1044 verifyFormat("int Value { get; set; } = 0", Style
);
1045 verifyFormat("int Value { internal get; internal set; }", Style
);
1047 // Do not wrap expression body definitions.
1049 public string Name {
1051 set => _name = value;
1055 public string Name {
1056 init => _name = value;
1061 public string Name {
1062 set => _name = value;
1067 // Examples taken from
1068 // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
1070 // Expression body definitions
1071 public class SaleItem {
1072 public decimal Price {
1074 set => _cost = value;
1080 // Properties with backing fields
1082 public double Hours {
1083 get { return _seconds / 3600; }
1085 if (value < 0 || value > 24)
1086 throw new ArgumentOutOfRangeException($"{nameof(value
)} must be between
0 and 24.");
1087 _seconds = value * 3600;
1094 // Auto-implemented properties
1095 public class SaleItem {
1096 public decimal Price { get; set; }
1100 // Add column limit to wrap long lines.
1101 Style
.ColumnLimit
= 100;
1103 // Examples with assignment to default value.
1105 // Long assignment to default value
1107 public override VeryLongNamedTypeIndeed VeryLongNamedValue { get; set } =
1108 VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1109 DefaultThirdArgument);
1114 // Long assignment to default value with expression body
1116 public override VeryLongNamedTypeIndeed VeryLongNamedValue {
1117 get => veryLongNamedField;
1118 set => veryLongNamedField = value;
1119 } = VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
1120 DefaultThirdArgument);
1124 // Brace wrapping and single-lining of accessor can be controlled by config.
1125 Style
.AllowShortBlocksOnASingleLine
= FormatStyle::SBS_Never
;
1126 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1127 Style
.BraceWrapping
.AfterFunction
= true;
1134 return _seconds / 3600;
1137 _seconds = value * 3600;
1143 // Microsoft style trivial property accessors have no line break before the
1145 auto MicrosoftStyle
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1147 public class SaleItem
1149 public decimal Price { get; set; }
1153 verifyFormat("internal class Program\n"
1155 " bool AutoAllowKnownApps\n"
1165 TEST_F(FormatTestCSharp
, DefaultLiteral
) {
1166 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1169 "T[] InitializeArray<T>(int length, T initialValue = default) {}", Style
);
1170 verifyFormat("System.Numerics.Complex fillValue = default;", Style
);
1171 verifyFormat("int Value { get } = default;", Style
);
1172 verifyFormat("int Value { get } = default!;", Style
);
1174 public record Person {
1175 public string GetInit { get; init; } = default!;
1179 public record Person {
1180 public string GetSet { get; set; } = default!;
1185 TEST_F(FormatTestCSharp
, CSharpSpaces
) {
1186 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1187 Style
.SpaceBeforeSquareBrackets
= false;
1188 Style
.SpacesInSquareBrackets
= false;
1189 Style
.SpaceBeforeCpp11BracedList
= true;
1190 Style
.Cpp11BracedListStyle
= false;
1191 Style
.SpacesInContainerLiterals
= false;
1192 Style
.SpaceAfterCStyleCast
= false;
1194 verifyFormat(R
"(new Car { "Door
", 0.1 })", Style
);
1195 verifyFormat(R
"(new Car { 0.1, "Door
" })", Style
);
1196 verifyFormat(R
"(new string[] { "A
" })", Style
);
1197 verifyFormat(R
"(new string[] {})", Style
);
1198 verifyFormat(R
"(new Car { someVariableName })", Style
);
1199 verifyFormat(R
"(new Car { someVariableName })", Style
);
1200 verifyFormat(R
"(new Dictionary<string, string> { ["Key
"] = "Value
" };)",
1202 verifyFormat(R
"(Apply(x => x.Name, x => () => x.ID);)", Style
);
1203 verifyFormat(R
"(bool[] xs = { true, true };)", Style
);
1204 verifyIncompleteFormat(
1205 R
"(taskContext.Factory.Run(async () => doThing(args);)", Style
);
1206 verifyFormat(R
"(catch (TestException) when (innerFinallyExecuted))", Style
);
1207 verifyFormat(R
"(private float[,] Values;)", Style
);
1208 verifyFormat(R
"(Result this[Index x] => Foo(x);)", Style
);
1210 verifyFormat(R
"(char[,,] rawCharArray = MakeCharacterGrid();)", Style
);
1211 verifyFormat(R
"(var (key, value))", Style
);
1213 // `&&` is not seen as a reference.
1214 verifyFormat(R
"(A == typeof(X) && someBool)", Style
);
1216 // Not seen as a C-style cast.
1218 foreach ((A a, B b) in someList) {
1222 // space after lock in `lock (processes)`.
1223 verifyFormat("lock (process)", Style
);
1225 Style
.SpacesInSquareBrackets
= true;
1226 verifyFormat(R
"(private float[ , ] Values;)", Style
);
1227 verifyFormat(R
"(string dirPath = args?[ 0 ];)", Style
);
1228 verifyFormat(R
"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style
);
1230 // Method returning tuple
1231 verifyFormat(R
"(public (string name, int age) methodTuple() {})", Style
);
1232 verifyFormat(R
"(private (string name, int age) methodTuple() {})", Style
);
1233 verifyFormat(R
"(protected (string name, int age) methodTuple() {})", Style
);
1234 verifyFormat(R
"(virtual (string name, int age) methodTuple() {})", Style
);
1235 verifyFormat(R
"(extern (string name, int age) methodTuple() {})", Style
);
1236 verifyFormat(R
"(static (string name, int age) methodTuple() {})", Style
);
1237 verifyFormat(R
"(internal (string name, int age) methodTuple() {})", Style
);
1238 verifyFormat(R
"(abstract (string name, int age) methodTuple() {})", Style
);
1239 verifyFormat(R
"(sealed (string name, int age) methodTuple() {})", Style
);
1240 verifyFormat(R
"(override (string name, int age) methodTuple() {})", Style
);
1241 verifyFormat(R
"(async (string name, int age) methodTuple() {})", Style
);
1242 verifyFormat(R
"(unsafe (string name, int age) methodTuple() {})", Style
);
1244 Style
.SpacesInSquareBrackets
= false;
1245 Style
.SpaceBeforeSquareBrackets
= true;
1246 verifyFormat("return a is [1, 2, 3];", Style
);
1247 verifyFormat("return a is [..];", Style
);
1248 Style
.SpaceBeforeSquareBrackets
= false;
1249 verifyFormat("return a is [1, 2, 3];", Style
);
1250 verifyFormat("return a is [..];", Style
);
1253 TEST_F(FormatTestCSharp
, CSharpNullableTypes
) {
1254 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1255 Style
.SpacesInSquareBrackets
= false;
1260 int? value = some.bar();
1263 Style
); // int? is nullable not a conditional expression.
1265 verifyFormat(R
"(void foo(int? x, int? y, int? z) {})",
1266 Style
); // Nullables in function definitions.
1268 verifyFormat(R
"(public float? Value;)", Style
); // no space before `?`.
1270 verifyFormat(R
"(int?[] arr = new int?[10];)",
1271 Style
); // An array of a nullable type.
1273 verifyFormat(R
"(var x = (int?)y;)", Style
); // Cast to a nullable type.
1275 verifyFormat(R
"(var x = new MyContainer<int?>();)", Style
); // Generics.
1278 public interface I {
1281 Style
); // Interface methods.
1283 Style
.ColumnLimit
= 10;
1285 public VeryLongType? Function(
1290 Style
); // ? sticks with identifier.
1293 TEST_F(FormatTestCSharp
, CSharpArraySubscripts
) {
1294 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1296 // Do not format array subscript operators as attributes.
1298 if (someThings[index].Contains(myThing)) {
1303 if (someThings[i][j][k].Contains(myThing)) {
1308 TEST_F(FormatTestCSharp
, CSharpGenericTypeConstraints
) {
1309 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1311 EXPECT_TRUE(Style
.BraceWrapping
.SplitEmptyRecord
);
1313 verifyFormat("class ItemFactory<T>\n"
1314 " where T : new() {\n"
1318 // When the "where" line is not to be formatted, following lines should not
1319 // take on its indentation.
1320 verifyFormat("class ItemFactory<T>\n"
1321 " where T : new() {\n"
1324 "class ItemFactory<T>\n"
1325 " where T : new() {\n"
1328 Style
, {tooling::Range(43, 13)});
1330 verifyFormat("class Dictionary<TKey, TVal>\n"
1331 " where TKey : IComparable<TKey>\n"
1332 " where TVal : IMyInterface {\n"
1333 " public void MyMethod<T>(T t)\n"
1334 " where T : IMyInterface {\n"
1340 verifyFormat("class ItemFactory<T>\n"
1341 " where T : new(), IAnInterface<T>, IAnotherInterface<T>, "
1342 "IAnotherInterfaceStill<T> {\n"
1346 Style
.ColumnLimit
= 50; // Force lines to be wrapped.
1348 class ItemFactory<T, U>
1351 IAnotherInterface<T, U>,
1352 IAnotherInterfaceStill<T, U> {
1356 // In other languages `where` can be used as a normal identifier.
1357 // This example is in C++!
1362 getGoogleStyle(FormatStyle::LK_Cpp
));
1365 TEST_F(FormatTestCSharp
, CSharpAfterEnum
) {
1366 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1367 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1368 Style
.BraceWrapping
.AfterEnum
= false;
1369 Style
.AllowShortEnumsOnASingleLine
= false;
1371 verifyFormat("enum MyEnum {\n"
1376 verifyFormat("internal enum MyEnum {\n"
1381 verifyFormat("public enum MyEnum {\n"
1386 verifyFormat("protected enum MyEnum {\n"
1391 verifyFormat("private enum MyEnum {\n"
1397 Style
.BraceWrapping
.AfterEnum
= true;
1398 Style
.AllowShortEnumsOnASingleLine
= false;
1400 verifyFormat("enum MyEnum\n"
1406 verifyFormat("internal enum MyEnum\n"
1412 verifyFormat("public enum MyEnum\n"
1418 verifyFormat("protected enum MyEnum\n"
1424 verifyFormat("private enum MyEnum\n"
1430 verifyFormat("/* Foo */ private enum MyEnum\n"
1436 verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n"
1444 TEST_F(FormatTestCSharp
, CSharpAfterClass
) {
1445 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1446 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1447 Style
.BraceWrapping
.AfterClass
= false;
1449 verifyFormat("class MyClass {\n"
1454 verifyFormat("internal class MyClass {\n"
1459 verifyFormat("public class MyClass {\n"
1464 verifyFormat("protected class MyClass {\n"
1469 verifyFormat("private class MyClass {\n"
1475 verifyFormat("interface Interface {\n"
1480 verifyFormat("internal interface Interface {\n"
1485 verifyFormat("public interface Interface {\n"
1490 verifyFormat("protected interface Interface {\n"
1495 verifyFormat("private interface Interface {\n"
1501 Style
.BraceWrapping
.AfterClass
= true;
1503 verifyFormat("class MyClass\n"
1509 verifyFormat("internal class MyClass\n"
1515 verifyFormat("public class MyClass\n"
1521 verifyFormat("protected class MyClass\n"
1527 verifyFormat("private class MyClass\n"
1534 verifyFormat("interface MyInterface\n"
1540 verifyFormat("internal interface MyInterface\n"
1546 verifyFormat("public interface MyInterface\n"
1552 verifyFormat("protected interface MyInterface\n"
1558 verifyFormat("private interface MyInterface\n"
1564 verifyFormat("/* Foo */ private interface MyInterface\n"
1570 verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n"
1578 TEST_F(FormatTestCSharp
, NamespaceIndentation
) {
1579 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1580 Style
.NamespaceIndentation
= FormatStyle::NI_None
;
1582 verifyFormat("namespace A\n"
1584 "public interface Name1\n"
1590 verifyFormat("namespace A.B\n"
1592 "public interface Name1\n"
1598 Style
.NamespaceIndentation
= FormatStyle::NI_Inner
;
1600 verifyFormat("namespace A\n"
1604 " public interface Name1\n"
1611 Style
.NamespaceIndentation
= FormatStyle::NI_All
;
1613 verifyFormat("namespace A.B\n"
1615 " public interface Name1\n"
1621 verifyFormat("namespace A\n"
1625 " public interface Name1\n"
1633 TEST_F(FormatTestCSharp
, SwitchExpression
) {
1634 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1635 verifyFormat("int x = a switch {\n"
1636 " 1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n"
1643 TEST_F(FormatTestCSharp
, EmptyShortBlock
) {
1644 auto Style
= getLLVMStyle();
1645 Style
.AllowShortBlocksOnASingleLine
= FormatStyle::SBS_Empty
;
1647 verifyFormat("try {\n"
1649 "} catch (Exception e) {\n"
1650 " e.printStackTrace();\n"
1654 verifyFormat("try {\n"
1656 "} catch (Exception e) {}",
1660 TEST_F(FormatTestCSharp
, ShortFunctions
) {
1661 FormatStyle Style
= getLLVMStyle(FormatStyle::LK_CSharp
);
1662 Style
.NamespaceIndentation
= FormatStyle::NI_All
;
1663 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_Inline
;
1664 verifyFormat("interface Interface {\n"
1665 " void f() { return; }\n"
1668 verifyFormat("public interface Interface {\n"
1669 " void f() { return; }\n"
1672 verifyFormat("namespace {\n"
1678 // "union" is not a keyword in C#.
1679 verifyFormat("namespace union {\n"
1687 TEST_F(FormatTestCSharp
, BrokenBrackets
) {
1688 EXPECT_NE("", format("int where b <")); // reduced from crasher
1691 TEST_F(FormatTestCSharp
, GotoCaseLabel
) {
1692 verifyFormat("switch (i)\n"
1715 } // namespace format
1716 } // namespace clang