jbcoe updated this revision to Diff 260316.
jbcoe added a comment.

Format patch.


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

https://reviews.llvm.org/D78915

Files:
  clang/lib/Format/UnwrappedLineParser.cpp
  clang/unittests/Format/FormatTestCSharp.cpp

Index: clang/unittests/Format/FormatTestCSharp.cpp
===================================================================
--- clang/unittests/Format/FormatTestCSharp.cpp
+++ clang/unittests/Format/FormatTestCSharp.cpp
@@ -611,6 +611,64 @@
 public string Name {
   get => _name;
   set => _name = value;
+})",
+               Style);
+
+  // Examples taken from
+  // https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/properties
+  verifyFormat(R"(
+// Expression body definitions
+public class SaleItem {
+  public decimal Price {
+    get => _cost;
+    set => _cost = value;
+  }
+})",
+               Style);
+
+  verifyFormat(R"(
+// Properties with backing fields
+class TimePeriod {
+  public double Hours {
+    get { return _seconds / 3600; }
+    set {
+      if (value < 0 || value > 24)
+        throw new ArgumentOutOfRangeException(
+            $"{nameof(value)} must be between 0 and 24.");
+      _seconds = value * 3600;
+    }
+  }
+})",
+               Style);
+
+  verifyFormat(R"(
+// Auto-implemented properties
+public class SaleItem {
+  public decimal Price { get; set; }
+})",
+               Style);
+
+  // Add column limit to wrap long lines.
+  Style.ColumnLimit = 100;
+
+  // Examples with assignment to default value.
+  verifyFormat(R"(
+// Long assignment to default value
+class MyClass {
+  public override VeryLongNamedTypeIndeed VeryLongNamedValue { get; set } =
+      VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
+                                     DefaultThirdArgument);
+})",
+               Style);
+
+  verifyFormat(R"(
+// Long assignment to default value with expression body
+class MyClass {
+  public override VeryLongNamedTypeIndeed VeryLongNamedValue {
+    get => veryLongNamedField;
+    set => veryLongNamedField = value;
+  } = VeryLongNamedTypeIndeed.Create(DefaultFirstArgument, DefaultSecondArgument,
+                                     DefaultThirdArgument);
 })",
                Style);
 }
Index: clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "UnwrappedLineParser.h"
+#include "FormatToken.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
@@ -1495,9 +1496,7 @@
   if (FormatTok->Previous->isNot(tok::identifier))
     return false;
 
-  // Try to parse the property accessor braces and contents:
-  // `{ get; set; } = new MyType(defaultValue);`
-  //  ^^^^^^^^^^^^^
+  // See if we are inside a property accessor.
   //
   // Record the current tokenPosition so that we can advance and
   // reset the current token. `Next` is not set yet so we need
@@ -1506,19 +1505,20 @@
   FormatToken *Tok = Tokens->getNextToken();
 
   bool HasGetOrSet = false;
+  bool IsTrivialPropertyAccessor = true;
   while (!eof()) {
     if (Tok->isOneOf(tok::semi, tok::kw_public, tok::kw_private,
                      tok::kw_protected, Keywords.kw_internal, Keywords.kw_get,
                      Keywords.kw_set)) {
-      if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_set))
+      if (Tok->isOneOf(Keywords.kw_get, Keywords.kw_set)) {
         HasGetOrSet = true;
+      }
       Tok = Tokens->getNextToken();
       continue;
     }
-    if (Tok->is(tok::r_brace))
-      break;
-    Tokens->setPosition(StoredPosition);
-    return false;
+    if (Tok->isNot(tok::r_brace))
+      IsTrivialPropertyAccessor = false;
+    break;
   }
 
   if (!HasGetOrSet) {
@@ -1526,33 +1526,53 @@
     return false;
   }
 
-  Tokens->setPosition(StoredPosition);
-  while (FormatTok->isNot(tok::r_brace)) {
-    nextToken();
-  }
-
-  // Try to parse (optional) assignment to default value:
+  // Try to parse the property accessor:
   // `{ get; set; } = new MyType(defaultValue);`
-  //                ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-  // There may be some very complicated expressions inside default value
-  // assignment, the simple parse block below will not handle them.
-  // The parse block below would need extending to handle opening parens etc.
-  StoredPosition = Tokens->getPosition();
-  Tok = Tokens->getNextToken();
-  bool NextTokenIsEqual = Tok->is(tok::equal);
   Tokens->setPosition(StoredPosition);
-
-  if (NextTokenIsEqual) {
-    do {
+  nextToken();
+  do {
+    switch (FormatTok->Tok.getKind()) {
+    case tok::r_brace:
       nextToken();
-      if (FormatTok->is(tok::semi))
+      if (FormatTok->is(tok::equal)) {
+        while (!eof() && FormatTok->isNot(tok::semi))
+          nextToken();
+        nextToken();
+      }
+      addUnwrappedLine();
+      return true;
+    case tok::l_brace:
+      ++Line->Level;
+      parseBlock(/*MustBeDeclaration=*/true);
+      addUnwrappedLine();
+      --Line->Level;
+      break;
+    case tok::equal:
+      if (FormatTok->is(TT_JsFatArrow)) {
+        ++Line->Level;
+        do {
+          nextToken();
+        } while (!eof() && FormatTok->isNot(tok::semi));
+        nextToken();
+        addUnwrappedLine();
+        --Line->Level;
         break;
-    } while (!eof());
-  }
+      }
+      // if(FormatTok->Previous->isNot(tok::r_brace))
+      //  --Line->Level;
+      nextToken();
+      break;
+    default:
+      if (FormatTok->isOneOf(Keywords.kw_get, Keywords.kw_set) &&
+          !IsTrivialPropertyAccessor) {
+        // get/set needs to be on its own line.
+        addUnwrappedLine();
+      }
+      nextToken();
+    }
+  } while (!eof());
 
-  // Add an unwrapped line for the whole property accessor.
-  nextToken();
-  addUnwrappedLine();
+  // Unreachable for well-formed code (paired '{' and '}').
   return true;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to