Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -1828,6 +1828,20 @@ {} { } + * ``bool AfterCSharpProperty`` Wrap C# setter/getter properties. + + .. code-block:: c++ + + true: + get + {} + set + {} + + false: + get {} + set {} + .. _BreakAfterAttributes: Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -461,6 +461,8 @@ - Add additional Qualifier Ordering support for special cases such as templates, requires clauses, long qualified names. - Fix all known issues associated with ``LambdaBodyIndentation: OuterScope``. +- Add ``AfterCSharpProperty`` style to option ``BraceWrapping`` to allow + newline before the opening brace of ``set;get;``. libclang -------- Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -1205,6 +1205,19 @@ /// \endcode /// bool SplitEmptyNamespace; + /// Wrap C# setter/getter properties. + /// \code + /// true: + /// get + /// {} + /// set + /// {} + /// + /// false: + /// get {} + /// set {} + /// \endcode + bool AfterCSharpProperty; }; /// Control of individual brace wrapping cases. Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -181,6 +181,7 @@ IO.mapOptional("AfterEnum", Wrapping.AfterEnum); IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock); IO.mapOptional("AfterFunction", Wrapping.AfterFunction); + IO.mapOptional("AfterCSharpProperty", Wrapping.AfterCSharpProperty); IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace); IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration); IO.mapOptional("AfterStruct", Wrapping.AfterStruct); @@ -1188,7 +1189,8 @@ /*IndentBraces=*/false, /*SplitEmptyFunction=*/true, /*SplitEmptyRecord=*/true, - /*SplitEmptyNamespace=*/true}; + /*SplitEmptyNamespace=*/true, + /*AfterCSharpProperty=*/false}; switch (Expanded.BreakBeforeBraces) { case FormatStyle::BS_Linux: Expanded.BraceWrapping.AfterClass = true; @@ -1354,7 +1356,8 @@ /*IndentBraces=*/false, /*SplitEmptyFunction=*/true, /*SplitEmptyRecord=*/true, - /*SplitEmptyNamespace=*/true}; + /*SplitEmptyNamespace=*/true, + /*AfterCSharpProperty=*/false}; LLVMStyle.BreakAfterAttributes = FormatStyle::ABS_Never; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakArrays = true; Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -4984,6 +4984,13 @@ return true; } + // Handle `string Foo {{set {} get {}}`. + if (Style.isCSharp() && Style.BraceWrapping.AfterCSharpProperty && + (Line.startsWith(Keywords.kw_get) || + Line.startsWith(Keywords.kw_set))) { + return true; + } + // Don't attempt to interpret struct return types as structs. if (Right.isNot(TT_FunctionLBrace)) { return (Line.startsWith(tok::kw_class) && @@ -4993,6 +5000,17 @@ } } + // Handle default `string Foo {set;get }`. + if (Style.isCSharp() && Style.BraceWrapping.AfterCSharpProperty && + ((Left.isOneOf(tok::l_brace, tok::semi) && + Right.isOneOf(Keywords.kw_set, Keywords.kw_get)) || + (Left.is(tok::semi) && Left.Previous && + Left.Previous->is(Keywords.kw_get) && Right.is(tok::r_brace)) || + (Left.is(tok::semi) && Left.Previous && + Left.Previous->is(Keywords.kw_set) && Right.is(tok::r_brace)))) { + return true; + } + if (Left.is(TT_ObjCBlockLBrace) && Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) { return true; Index: clang/unittests/Format/FormatTestCSharp.cpp =================================================================== --- clang/unittests/Format/FormatTestCSharp.cpp +++ clang/unittests/Format/FormatTestCSharp.cpp @@ -1604,5 +1604,81 @@ EXPECT_NE("", format("int where b <")); // reduced from crasher } +TEST_F(FormatTestCSharp, PropertyWrapping) { + FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); + + Style.BraceWrapping.AfterCSharpProperty = false; + verifyFormat("class A\n" + "{\n" + " string Foo { set; get; }\n" + "}\n", + Style); + verifyFormat("class A\n" + "{\n" + " string Foo { get; set; }\n" + "}\n", + Style); + verifyFormat("class A\n" + "{\n" + " string Foo\n" + " {\n" + " set {\n" + " val = value;\n" + " }\n" + " get {\n" + " return value;\n" + " }\n" + " }\n" + "}\n", + Style); + + Style.BraceWrapping.AfterCSharpProperty = true; + + verifyFormat("class A\n" + "{\n" + " string Bar {\n" + " set;\n" + " get;\n" + " }\n" + "}\n", + Style); + verifyFormat("class A\n" + "{\n" + " string Bar {\n" + " get;\n" + " set;\n" + " }\n" + "}\n", + Style); + verifyFormat("class A\n" + "{\n" + " string Bar\n" + " {\n" + " set\n" + " {\n" + " val = value;\n" + " }\n" + " get\n" + " {\n" + " return value;\n" + " }\n" + " }\n" + "}\n", + Style); + /* TODO fix the indentation of get; + verifyFormat("class A\n" + "{\n" + " string Bar {\n" + " get;\n" + " set\n" + " {\n" + " val = value;\n" + " }\n" + " }\n" + "}\n", + Style); + */ +} + } // namespace format } // end namespace clang