[clang] 1fb9c29 - [clang-format] Improved identification of C# nullables

Jonathan Coe via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 11 06:06:55 PDT 2020


Author: Jonathan Coe
Date: 2020-03-11T12:58:52Z
New Revision: 1fb9c29833ab88c4a3d6fda9911117839754d998

URL: https://github.com/llvm/llvm-project/commit/1fb9c29833ab88c4a3d6fda9911117839754d998
DIFF: https://github.com/llvm/llvm-project/commit/1fb9c29833ab88c4a3d6fda9911117839754d998.diff

LOG: [clang-format] Improved identification of C# nullables

Summary:
Allow `?` inside C# generics.

Do not mistake casts like `(Type?)` as conditional operators.

Reviewers: krasimir

Subscribers: cfe-commits, MyDeveloperDay

Tags: #clang-format, #clang

Differential Revision: https://reviews.llvm.org/D75983

Added: 
    

Modified: 
    clang/lib/Format/TokenAnnotator.cpp
    clang/unittests/Format/FormatTestCSharp.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index cf481a1dcb62..d546a9f7c606 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -131,7 +131,7 @@ class AnnotatingParser {
       }
       if (CurrentToken->isOneOf(tok::r_paren, tok::r_square, tok::r_brace) ||
           (CurrentToken->isOneOf(tok::colon, tok::question) && InExprContext &&
-           Style.Language != FormatStyle::LK_Proto &&
+           !Style.isCSharp() && Style.Language != FormatStyle::LK_Proto &&
            Style.Language != FormatStyle::LK_TextProto))
         return false;
       // If a && or || is found and interpreted as a binary operator, this set
@@ -1013,12 +1013,13 @@ class AnnotatingParser {
           Style.Language == FormatStyle::LK_JavaScript)
         break;
       if (Style.isCSharp()) {
-        // `Type? name;` and `Type? name =` can only be nullable types.
+        // `Type?)`, `Type?>`, `Type? name;` and `Type? name =` can only be
+        // nullable types.
         // Line.MustBeDeclaration will be true for `Type? name;`.
-        if (!Contexts.back().IsExpression &&
-            (Line.MustBeDeclaration ||
-             (Tok->Next && Tok->Next->is(tok::identifier) && Tok->Next->Next &&
-              Tok->Next->Next->is(tok::equal)))) {
+        if ((!Contexts.back().IsExpression && Line.MustBeDeclaration) ||
+            (Tok->Next && Tok->Next->isOneOf(tok::r_paren, tok::greater)) ||
+            (Tok->Next && Tok->Next->is(tok::identifier) && Tok->Next->Next &&
+             Tok->Next->Next->is(tok::equal))) {
           Tok->Type = TT_CSharpNullable;
           break;
         }
@@ -2969,9 +2970,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
     if (Right.is(TT_CSharpNullable))
       return false;
 
-    // Require space after ? in nullable types.
+    // Require space after ? in nullable types except in generics and casts.
     if (Left.is(TT_CSharpNullable))
-      return true;
+      return !Right.isOneOf(TT_TemplateCloser, tok::r_paren);
 
     // No space before or after '?.'.
     if (Left.is(TT_CSharpNullConditional) || Right.is(TT_CSharpNullConditional))

diff  --git a/clang/unittests/Format/FormatTestCSharp.cpp b/clang/unittests/Format/FormatTestCSharp.cpp
index 824eb51bd693..03ebe337e76c 100644
--- a/clang/unittests/Format/FormatTestCSharp.cpp
+++ b/clang/unittests/Format/FormatTestCSharp.cpp
@@ -652,6 +652,10 @@ public class A {
 
   verifyFormat(R"(int?[] arr = new int?[10];)",
                Style); // An array of a nullable type.
+
+  verifyFormat(R"(var x = (int?)y;)", Style); // Cast to a nullable type.
+
+  verifyFormat(R"(var x = new MyContainer<int?>();)", Style); // Generics.
 }
 
 TEST_F(FormatTestCSharp, CSharpArraySubscripts) {


        


More information about the cfe-commits mailing list