Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -1628,6 +1628,32 @@ {} + * ``bool AfterCSharpProperty`` Wrap C# setter/getter properties. + + .. code-block:: c++ + + true: + string Foo { + get + { + return _foo; + } + set + { + _foo = value; + } + } + + false: + string Foo { + get { + return _foo; + } + set { + return _value + } + } + * ``bool AfterEnum`` Wrap enum definitions. .. code-block:: c++ Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -468,6 +468,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 @@ -1002,6 +1002,7 @@ /// } /// \endcode bool AfterCaseLabel; + /// Wrap class definitions. /// \code /// true: @@ -1015,6 +1016,33 @@ /// Wrap control statements (``if``/``for``/``while``/``switch``/..). BraceWrappingAfterControlStatementStyle AfterControlStatement; + + /// Wrap C# setter/getter properties. + /// \code + /// true: + /// string Foo { + /// get + /// { + /// return _foo; + /// } + /// set + /// { + /// _foo = value; + /// } + /// } + /// + /// false: + /// string Foo { + /// get { + /// return _foo; + /// } + /// set { + /// return _value + /// } + /// } + /// \endcode + bool AfterCSharpProperty; + /// Wrap enum definitions. /// \code /// true: @@ -1205,6 +1233,28 @@ /// \endcode /// bool SplitEmptyNamespace; + + bool operator==(const BraceWrappingFlags &Other) const { + return AfterCaseLabel == Other.AfterCaseLabel && + AfterClass == Other.AfterClass && + AfterControlStatement == Other.AfterControlStatement && + AfterCSharpProperty == Other.AfterCSharpProperty && + AfterEnum == Other.AfterEnum && + AfterFunction == Other.AfterFunction && + AfterNamespace == Other.AfterNamespace && + AfterObjCDeclaration == Other.AfterObjCDeclaration && + AfterStruct == Other.AfterStruct && + AfterUnion == Other.AfterUnion && + AfterExternBlock == Other.AfterExternBlock && + BeforeCatch == Other.BeforeCatch && + BeforeElse == Other.BeforeElse && + BeforeLambdaBody == Other.BeforeLambdaBody && + BeforeWhile == Other.BeforeWhile && + IndentBraces == Other.IndentBraces && + SplitEmptyFunction == Other.SplitEmptyFunction && + SplitEmptyRecord == Other.SplitEmptyRecord && + SplitEmptyNamespace == Other.SplitEmptyNamespace; + } }; /// Control of individual brace wrapping cases. Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -178,6 +178,7 @@ IO.mapOptional("AfterCaseLabel", Wrapping.AfterCaseLabel); IO.mapOptional("AfterClass", Wrapping.AfterClass); IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement); + IO.mapOptional("AfterCSharpProperty", Wrapping.AfterCSharpProperty); IO.mapOptional("AfterEnum", Wrapping.AfterEnum); IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock); IO.mapOptional("AfterFunction", Wrapping.AfterFunction); @@ -1174,6 +1175,7 @@ Expanded.BraceWrapping = {/*AfterCaseLabel=*/false, /*AfterClass=*/false, /*AfterControlStatement=*/FormatStyle::BWACS_Never, + /*AfterCSharpProperty=*/false, /*AfterEnum=*/false, /*AfterFunction=*/false, /*AfterNamespace=*/false, @@ -1247,6 +1249,7 @@ /*AfterCaseLabel=*/true, /*AfterClass=*/true, /*AfterControlStatement=*/FormatStyle::BWACS_Always, + /*AfterCSharpProperty=*/false, /*AfterEnum=*/true, /*AfterFunction=*/true, /*AfterNamespace=*/true, @@ -1337,24 +1340,27 @@ LLVMStyle.BitFieldColonSpacing = FormatStyle::BFCS_Both; LLVMStyle.BinPackArguments = true; LLVMStyle.BinPackParameters = true; - LLVMStyle.BraceWrapping = {/*AfterCaseLabel=*/false, - /*AfterClass=*/false, - /*AfterControlStatement=*/FormatStyle::BWACS_Never, - /*AfterEnum=*/false, - /*AfterFunction=*/false, - /*AfterNamespace=*/false, - /*AfterObjCDeclaration=*/false, - /*AfterStruct=*/false, - /*AfterUnion=*/false, - /*AfterExternBlock=*/false, - /*BeforeCatch=*/false, - /*BeforeElse=*/false, - /*BeforeLambdaBody=*/false, - /*BeforeWhile=*/false, - /*IndentBraces=*/false, - /*SplitEmptyFunction=*/true, - /*SplitEmptyRecord=*/true, - /*SplitEmptyNamespace=*/true}; + LLVMStyle.BraceWrapping = { + /*AfterCaseLabel=*/false, + /*AfterClass=*/false, + /*AfterControlStatement=*/FormatStyle::BWACS_Never, + /*AfterCSharpProperty=*/false, + /*AfterEnum=*/false, + /*AfterFunction=*/false, + /*AfterNamespace=*/false, + /*AfterObjCDeclaration=*/false, + /*AfterStruct=*/false, + /*AfterUnion=*/false, + /*AfterExternBlock=*/false, + /*BeforeCatch=*/false, + /*BeforeElse=*/false, + /*BeforeLambdaBody=*/false, + /*BeforeWhile=*/false, + /*IndentBraces=*/false, + /*SplitEmptyFunction=*/true, + /*SplitEmptyRecord=*/true, + /*SplitEmptyNamespace=*/true, + }; 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 @@ -5011,6 +5011,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) && @@ -5020,6 +5027,16 @@ } } + // 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->isOneOf(Keywords.kw_get, 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 @@ -1612,5 +1612,93 @@ 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" + "}", + Style); + verifyFormat("class A\n" + "{\n" + " string Foo { get; set; }\n" + "}", + Style); + verifyFormat("class A\n" + "{\n" + " string Foo\n" + " {\n" + " set {\n" + " val = value;\n" + " }\n" + " get {\n" + " return value;\n" + " }\n" + " }\n" + "}", + Style); + /* TODO fix the indentation of get; + verifyFormat("class A\n" + "{\n" + " string Bar {\n" + " get;\n" + " set {\n" + " val = value;\n" + " }\n" + " }\n" + "}", + Style); + */ + + Style.BraceWrapping.AfterCSharpProperty = true; + + verifyFormat("class A\n" + "{\n" + " string Bar {\n" + " set;\n" + " get;\n" + " }\n" + "}", + Style); + verifyFormat("class A\n" + "{\n" + " string Bar {\n" + " get;\n" + " set;\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" + "}", + 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" + "}", + Style); + */ +} + } // namespace format } // end namespace clang