MyDeveloperDay updated this revision to Diff 514029.
MyDeveloperDay added a comment.

for default `set;get` or `get;set` for when `AfterCSharpProperty` is true,

  public Foo {
      set;
      get;
  }


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D148467/new/

https://reviews.llvm.org/D148467

Files:
  clang/docs/ClangFormatStyleOptions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/lib/Format/TokenAnnotator.cpp
  clang/unittests/Format/FormatTestCSharp.cpp

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
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,16 +5000,28 @@
     }
   }
 
-  if (Left.is(TT_ObjCBlockLBrace) &&
-      Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
+  // Handle `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;
   }
 
-  // Ensure wrapping after __attribute__((XX)) and @interface etc.
-  if (Left.is(TT_AttributeParen) && Right.is(TT_ObjCDecl))
+if (Left.is(TT_ObjCBlockLBrace) &&
+    Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) {
     return true;
+}
 
-  if (Left.is(TT_LambdaLBrace)) {
+// Ensure wrapping after __attribute__((XX)) and @interface etc.
+if (Left.is(TT_AttributeParen) && Right.is(TT_ObjCDecl))
+  return true;
+
+if (Left.is(TT_LambdaLBrace)) {
     if (IsFunctionArgument(Left) &&
         Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Inline) {
       return false;
@@ -5014,54 +5033,54 @@
          Style.AllowShortLambdasOnASingleLine == FormatStyle::SLS_Empty)) {
       return true;
     }
-  }
+}
 
-  if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&
-      Left.isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser)) {
+if (Style.BraceWrapping.BeforeLambdaBody && Right.is(TT_LambdaLBrace) &&
+    Left.isOneOf(tok::star, tok::amp, tok::ampamp, TT_TemplateCloser)) {
     return true;
-  }
+}
 
-  // Put multiple Java annotation on a new line.
-  if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
-      Left.is(TT_LeadingJavaAnnotation) &&
-      Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
-      (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {
+// Put multiple Java annotation on a new line.
+if ((Style.Language == FormatStyle::LK_Java || Style.isJavaScript()) &&
+    Left.is(TT_LeadingJavaAnnotation) &&
+    Right.isNot(TT_LeadingJavaAnnotation) && Right.isNot(tok::l_paren) &&
+    (Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations)) {
     return true;
-  }
+}
 
-  if (Right.is(TT_ProtoExtensionLSquare))
-    return true;
+if (Right.is(TT_ProtoExtensionLSquare))
+  return true;
 
-  // In text proto instances if a submessage contains at least 2 entries and at
-  // least one of them is a submessage, like A { ... B { ... } ... },
-  // put all of the entries of A on separate lines by forcing the selector of
-  // the submessage B to be put on a newline.
-  //
-  // Example: these can stay on one line:
-  // a { scalar_1: 1 scalar_2: 2 }
-  // a { b { key: value } }
-  //
-  // and these entries need to be on a new line even if putting them all in one
-  // line is under the column limit:
-  // a {
-  //   scalar: 1
-  //   b { key: value }
-  // }
-  //
-  // We enforce this by breaking before a submessage field that has previous
-  // siblings, *and* breaking before a field that follows a submessage field.
-  //
-  // Be careful to exclude the case  [proto.ext] { ... } since the `]` is
-  // the TT_SelectorName there, but we don't want to break inside the brackets.
-  //
-  // Another edge case is @submessage { key: value }, which is a common
-  // substitution placeholder. In this case we want to keep `@` and `submessage`
-  // together.
-  //
-  // We ensure elsewhere that extensions are always on their own line.
-  if ((Style.Language == FormatStyle::LK_Proto ||
-       Style.Language == FormatStyle::LK_TextProto) &&
-      Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) {
+// In text proto instances if a submessage contains at least 2 entries and at
+// least one of them is a submessage, like A { ... B { ... } ... },
+// put all of the entries of A on separate lines by forcing the selector of
+// the submessage B to be put on a newline.
+//
+// Example: these can stay on one line:
+// a { scalar_1: 1 scalar_2: 2 }
+// a { b { key: value } }
+//
+// and these entries need to be on a new line even if putting them all in one
+// line is under the column limit:
+// a {
+//   scalar: 1
+//   b { key: value }
+// }
+//
+// We enforce this by breaking before a submessage field that has previous
+// siblings, *and* breaking before a field that follows a submessage field.
+//
+// Be careful to exclude the case  [proto.ext] { ... } since the `]` is
+// the TT_SelectorName there, but we don't want to break inside the brackets.
+//
+// Another edge case is @submessage { key: value }, which is a common
+// substitution placeholder. In this case we want to keep `@` and `submessage`
+// together.
+//
+// We ensure elsewhere that extensions are always on their own line.
+if ((Style.Language == FormatStyle::LK_Proto ||
+     Style.Language == FormatStyle::LK_TextProto) &&
+    Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) {
     // Keep `@submessage` together in:
     // @submessage { key: value }
     if (Left.is(tok::at))
@@ -5115,15 +5134,15 @@
     // put on a new line anyways.
     if (Left.isOneOf(tok::r_brace, tok::greater, tok::r_square))
       return true;
-  }
+}
 
-  // Deal with lambda arguments in C++ - we want consistent line breaks whether
-  // they happen to be at arg0, arg1 or argN. The selection is a bit nuanced
-  // as aggressive line breaks are placed when the lambda is not the last arg.
-  if ((Style.Language == FormatStyle::LK_Cpp ||
-       Style.Language == FormatStyle::LK_ObjC) &&
-      Left.is(tok::l_paren) && Left.BlockParameterCount > 0 &&
-      !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) {
+// Deal with lambda arguments in C++ - we want consistent line breaks whether
+// they happen to be at arg0, arg1 or argN. The selection is a bit nuanced
+// as aggressive line breaks are placed when the lambda is not the last arg.
+if ((Style.Language == FormatStyle::LK_Cpp ||
+     Style.Language == FormatStyle::LK_ObjC) &&
+    Left.is(tok::l_paren) && Left.BlockParameterCount > 0 &&
+    !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) {
     // Multiple lambdas in the same function call force line breaks.
     if (Left.BlockParameterCount > 1)
       return true;
@@ -5139,9 +5158,9 @@
       return false;
     if (!Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret))
       return true;
-  }
+}
 
-  return false;
+return false;
 }
 
 bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
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/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/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/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:
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to