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(llvm::StringRef Code
, unsigned Offset
,
25 unsigned Length
, 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(llvm::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
.AlwaysBreakAfterReturnType
= 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; }
1154 TEST_F(FormatTestCSharp
, DefaultLiteral
) {
1155 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1158 "T[] InitializeArray<T>(int length, T initialValue = default) {}", Style
);
1159 verifyFormat("System.Numerics.Complex fillValue = default;", Style
);
1160 verifyFormat("int Value { get } = default;", Style
);
1161 verifyFormat("int Value { get } = default!;", Style
);
1163 public record Person {
1164 public string GetInit { get; init; } = default!;
1168 public record Person {
1169 public string GetSet { get; set; } = default!;
1174 TEST_F(FormatTestCSharp
, CSharpSpaces
) {
1175 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1176 Style
.SpaceBeforeSquareBrackets
= false;
1177 Style
.SpacesInSquareBrackets
= false;
1178 Style
.SpaceBeforeCpp11BracedList
= true;
1179 Style
.Cpp11BracedListStyle
= false;
1180 Style
.SpacesInContainerLiterals
= false;
1181 Style
.SpaceAfterCStyleCast
= false;
1183 verifyFormat(R
"(new Car { "Door
", 0.1 })", Style
);
1184 verifyFormat(R
"(new Car { 0.1, "Door
" })", Style
);
1185 verifyFormat(R
"(new string[] { "A
" })", Style
);
1186 verifyFormat(R
"(new string[] {})", Style
);
1187 verifyFormat(R
"(new Car { someVariableName })", Style
);
1188 verifyFormat(R
"(new Car { someVariableName })", Style
);
1189 verifyFormat(R
"(new Dictionary<string, string> { ["Key
"] = "Value
" };)",
1191 verifyFormat(R
"(Apply(x => x.Name, x => () => x.ID);)", Style
);
1192 verifyFormat(R
"(bool[] xs = { true, true };)", Style
);
1193 verifyIncompleteFormat(
1194 R
"(taskContext.Factory.Run(async () => doThing(args);)", Style
);
1195 verifyFormat(R
"(catch (TestException) when (innerFinallyExecuted))", Style
);
1196 verifyFormat(R
"(private float[,] Values;)", Style
);
1197 verifyFormat(R
"(Result this[Index x] => Foo(x);)", Style
);
1199 verifyFormat(R
"(char[,,] rawCharArray = MakeCharacterGrid();)", Style
);
1200 verifyFormat(R
"(var (key, value))", Style
);
1202 // `&&` is not seen as a reference.
1203 verifyFormat(R
"(A == typeof(X) && someBool)", Style
);
1205 // Not seen as a C-style cast.
1207 foreach ((A a, B b) in someList) {
1211 // space after lock in `lock (processes)`.
1212 verifyFormat("lock (process)", Style
);
1214 Style
.SpacesInSquareBrackets
= true;
1215 verifyFormat(R
"(private float[ , ] Values;)", Style
);
1216 verifyFormat(R
"(string dirPath = args?[ 0 ];)", Style
);
1217 verifyFormat(R
"(char[ ,, ] rawCharArray = MakeCharacterGrid();)", Style
);
1219 // Method returning tuple
1220 verifyFormat(R
"(public (string name, int age) methodTuple() {})", Style
);
1221 verifyFormat(R
"(private (string name, int age) methodTuple() {})", Style
);
1222 verifyFormat(R
"(protected (string name, int age) methodTuple() {})", Style
);
1223 verifyFormat(R
"(virtual (string name, int age) methodTuple() {})", Style
);
1224 verifyFormat(R
"(extern (string name, int age) methodTuple() {})", Style
);
1225 verifyFormat(R
"(static (string name, int age) methodTuple() {})", Style
);
1226 verifyFormat(R
"(internal (string name, int age) methodTuple() {})", Style
);
1227 verifyFormat(R
"(abstract (string name, int age) methodTuple() {})", Style
);
1228 verifyFormat(R
"(sealed (string name, int age) methodTuple() {})", Style
);
1229 verifyFormat(R
"(override (string name, int age) methodTuple() {})", Style
);
1230 verifyFormat(R
"(async (string name, int age) methodTuple() {})", Style
);
1231 verifyFormat(R
"(unsafe (string name, int age) methodTuple() {})", Style
);
1233 Style
.SpacesInSquareBrackets
= false;
1234 Style
.SpaceBeforeSquareBrackets
= true;
1235 verifyFormat("return a is [1, 2, 3];", Style
);
1236 verifyFormat("return a is [..];", Style
);
1237 Style
.SpaceBeforeSquareBrackets
= false;
1238 verifyFormat("return a is [1, 2, 3];", Style
);
1239 verifyFormat("return a is [..];", Style
);
1242 TEST_F(FormatTestCSharp
, CSharpNullableTypes
) {
1243 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1244 Style
.SpacesInSquareBrackets
= false;
1249 int? value = some.bar();
1252 Style
); // int? is nullable not a conditional expression.
1254 verifyFormat(R
"(void foo(int? x, int? y, int? z) {})",
1255 Style
); // Nullables in function definitions.
1257 verifyFormat(R
"(public float? Value;)", Style
); // no space before `?`.
1259 verifyFormat(R
"(int?[] arr = new int?[10];)",
1260 Style
); // An array of a nullable type.
1262 verifyFormat(R
"(var x = (int?)y;)", Style
); // Cast to a nullable type.
1264 verifyFormat(R
"(var x = new MyContainer<int?>();)", Style
); // Generics.
1267 public interface I {
1270 Style
); // Interface methods.
1272 Style
.ColumnLimit
= 10;
1274 public VeryLongType? Function(
1279 Style
); // ? sticks with identifier.
1282 TEST_F(FormatTestCSharp
, CSharpArraySubscripts
) {
1283 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1285 // Do not format array subscript operators as attributes.
1287 if (someThings[index].Contains(myThing)) {
1292 if (someThings[i][j][k].Contains(myThing)) {
1297 TEST_F(FormatTestCSharp
, CSharpGenericTypeConstraints
) {
1298 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1300 EXPECT_TRUE(Style
.BraceWrapping
.SplitEmptyRecord
);
1302 verifyFormat("class ItemFactory<T>\n"
1303 " where T : new() {\n"
1307 verifyFormat("class Dictionary<TKey, TVal>\n"
1308 " where TKey : IComparable<TKey>\n"
1309 " where TVal : IMyInterface {\n"
1310 " public void MyMethod<T>(T t)\n"
1311 " where T : IMyInterface {\n"
1317 verifyFormat("class ItemFactory<T>\n"
1318 " where T : new(), IAnInterface<T>, IAnotherInterface<T>, "
1319 "IAnotherInterfaceStill<T> {\n"
1323 Style
.ColumnLimit
= 50; // Force lines to be wrapped.
1325 class ItemFactory<T, U>
1328 IAnotherInterface<T, U>,
1329 IAnotherInterfaceStill<T, U> {
1333 // In other languages `where` can be used as a normal identifier.
1334 // This example is in C++!
1339 getGoogleStyle(FormatStyle::LK_Cpp
));
1342 TEST_F(FormatTestCSharp
, CSharpAfterEnum
) {
1343 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1344 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1345 Style
.BraceWrapping
.AfterEnum
= false;
1346 Style
.AllowShortEnumsOnASingleLine
= false;
1348 verifyFormat("enum MyEnum {\n"
1353 verifyFormat("internal enum MyEnum {\n"
1358 verifyFormat("public enum MyEnum {\n"
1363 verifyFormat("protected enum MyEnum {\n"
1368 verifyFormat("private enum MyEnum {\n"
1374 Style
.BraceWrapping
.AfterEnum
= true;
1375 Style
.AllowShortEnumsOnASingleLine
= false;
1377 verifyFormat("enum MyEnum\n"
1383 verifyFormat("internal enum MyEnum\n"
1389 verifyFormat("public enum MyEnum\n"
1395 verifyFormat("protected enum MyEnum\n"
1401 verifyFormat("private enum MyEnum\n"
1407 verifyFormat("/* Foo */ private enum MyEnum\n"
1413 verifyFormat("/* Foo */ /* Bar */ private enum MyEnum\n"
1421 TEST_F(FormatTestCSharp
, CSharpAfterClass
) {
1422 FormatStyle Style
= getGoogleStyle(FormatStyle::LK_CSharp
);
1423 Style
.BreakBeforeBraces
= FormatStyle::BS_Custom
;
1424 Style
.BraceWrapping
.AfterClass
= false;
1426 verifyFormat("class MyClass {\n"
1431 verifyFormat("internal class MyClass {\n"
1436 verifyFormat("public class MyClass {\n"
1441 verifyFormat("protected class MyClass {\n"
1446 verifyFormat("private class MyClass {\n"
1452 verifyFormat("interface Interface {\n"
1457 verifyFormat("internal interface Interface {\n"
1462 verifyFormat("public interface Interface {\n"
1467 verifyFormat("protected interface Interface {\n"
1472 verifyFormat("private interface Interface {\n"
1478 Style
.BraceWrapping
.AfterClass
= true;
1480 verifyFormat("class MyClass\n"
1486 verifyFormat("internal class MyClass\n"
1492 verifyFormat("public class MyClass\n"
1498 verifyFormat("protected class MyClass\n"
1504 verifyFormat("private class MyClass\n"
1511 verifyFormat("interface MyInterface\n"
1517 verifyFormat("internal interface MyInterface\n"
1523 verifyFormat("public interface MyInterface\n"
1529 verifyFormat("protected interface MyInterface\n"
1535 verifyFormat("private interface MyInterface\n"
1541 verifyFormat("/* Foo */ private interface MyInterface\n"
1547 verifyFormat("/* Foo */ /* Bar */ private interface MyInterface\n"
1555 TEST_F(FormatTestCSharp
, NamespaceIndentation
) {
1556 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1557 Style
.NamespaceIndentation
= FormatStyle::NI_None
;
1559 verifyFormat("namespace A\n"
1561 "public interface Name1\n"
1567 verifyFormat("namespace A.B\n"
1569 "public interface Name1\n"
1575 Style
.NamespaceIndentation
= FormatStyle::NI_Inner
;
1577 verifyFormat("namespace A\n"
1581 " public interface Name1\n"
1588 Style
.NamespaceIndentation
= FormatStyle::NI_All
;
1590 verifyFormat("namespace A.B\n"
1592 " public interface Name1\n"
1598 verifyFormat("namespace A\n"
1602 " public interface Name1\n"
1610 TEST_F(FormatTestCSharp
, SwitchExpression
) {
1611 FormatStyle Style
= getMicrosoftStyle(FormatStyle::LK_CSharp
);
1612 verifyFormat("int x = a switch {\n"
1613 " 1 => (0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0),\n"
1620 TEST_F(FormatTestCSharp
, EmptyShortBlock
) {
1621 auto Style
= getLLVMStyle();
1622 Style
.AllowShortBlocksOnASingleLine
= FormatStyle::SBS_Empty
;
1624 verifyFormat("try {\n"
1626 "} catch (Exception e) {\n"
1627 " e.printStackTrace();\n"
1631 verifyFormat("try {\n"
1633 "} catch (Exception e) {}",
1637 TEST_F(FormatTestCSharp
, ShortFunctions
) {
1638 FormatStyle Style
= getLLVMStyle(FormatStyle::LK_CSharp
);
1639 Style
.NamespaceIndentation
= FormatStyle::NI_All
;
1640 Style
.AllowShortFunctionsOnASingleLine
= FormatStyle::SFS_Inline
;
1641 verifyFormat("interface Interface {\n"
1642 " void f() { return; }\n"
1645 verifyFormat("public interface Interface {\n"
1646 " void f() { return; }\n"
1649 verifyFormat("namespace {\n"
1655 // "union" is not a keyword in C#.
1656 verifyFormat("namespace union {\n"
1664 TEST_F(FormatTestCSharp
, BrokenBrackets
) {
1665 EXPECT_NE("", format("int where b <")); // reduced from crasher
1670 } // namespace format
1671 } // namespace clang