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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits