[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv created this revision. exv added reviewers: krasimir, MyDeveloperDay. exv requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits. This adds support for the null-coalescing assignment and null-forgiving oeprators. https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-forgiving Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D101702 Files: clang/lib/Format/FormatToken.h clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/FormatTokenLexer.h 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 @@ -358,6 +358,21 @@ verifyFormat("return _name ?? \"DEF\";"); } +TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) { + verifyFormat("test \?\?= ABC;"); + verifyFormat("test \?\?= true;"); +} + +TEST_F(FormatTestCSharp, CSharpNullForgiving) { + verifyFormat("var test = null!;"); + verifyFormat("string test = someFunctionCall()! + \"ABC\"!"); + verifyFormat("int test = (1! + 2 + bar! + foo())!"); + verifyFormat("test \?\?= !foo!;"); + verifyFormat("test = !bar! \?\? !foo!;"); + verifyFormat("bool test = !(!true || !null! || !false && !false! && !bar()! " + "+ (!foo()))!"); +} + TEST_F(FormatTestCSharp, AttributesIndentation) { FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; Index: clang/lib/Format/TokenAnnotator.cpp === --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1579,24 +1579,29 @@ } } -if (Style.Language == FormatStyle::LK_JavaScript) { - if (Current.is(tok::exclaim)) { -if (Current.Previous && -(Keywords.IsJavaScriptIdentifier( - *Current.Previous, /* AcceptIdentifierName= */ true) || - Current.Previous->isOneOf( - tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, - Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) || - Current.Previous->Tok.isLiteral())) { - Current.setType(TT_JsNonNullAssertion); - return; -} -if (Current.Next && -Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) { +if ((Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) && +Current.is(tok::exclaim)) { + if (Current.Previous) { +bool isIdentifier = +Style.Language == FormatStyle::LK_JavaScript +? Keywords.IsJavaScriptIdentifier( + *Current.Previous, /* AcceptIdentifierName= */ true) +: Current.Previous->is(tok::identifier); +if (isIdentifier || +Current.Previous->isOneOf( +tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, +tok::kw_false, tok::kw_true, Keywords.kw_type, Keywords.kw_get, +Keywords.kw_set) || +Current.Previous->Tok.isLiteral()) { Current.setType(TT_JsNonNullAssertion); return; } } + if (Current.Next && + Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) { +Current.setType(TT_JsNonNullAssertion); +return; + } } // Line.MightBeFunctionDecl can only be true after the parentheses of a @@ -3186,6 +3191,15 @@ if (Left.is(TT_CSharpNullCoalescing) || Right.is(TT_CSharpNullCoalescing)) return true; +// Space before and after '??='. +if (Left.is(TT_CSharpNullCoalescingAssignment) || +Right.is(TT_CSharpNullCoalescingAssignment)) + return true; + +// No space before null forgiving '!'. +if (Right.is(TT_JsNonNullAssertion)) + return false; + // No space before '?['. if (Right.is(TT_CSharpNullConditionalLSquare)) return false; Index: clang/lib/Format/FormatTokenLexer.h === --- clang/lib/Format/FormatTokenLexer.h +++ clang/lib/Format/FormatTokenLexer.h @@ -54,7 +54,8 @@ bool tryMergeJSPrivateIdentifier(); bool tryMergeCSharpStringLiteral(); bool tryMergeCSharpKeywordVariables(); - bool tryMergeCSharpDoubleQuestion(); + bool tryMergeCSharpNullCoalescing(); + bool tryMergeCSharpNullCoalescingAssignment(); bool tryMergeCSharpNullConditional(); bool tryTransformCSharpForEach(); bool tryMergeForEach(); Index: clang/lib/Format/FormatTokenLexer.cpp === --- clang/lib/Format/FormatTokenLexer.cpp +++ clang/lib/Format/For
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv updated this revision to Diff 342497. exv added a comment. Remove special whitespace handling for ??= Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 Files: 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 @@ -359,8 +359,16 @@ } TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) { - verifyFormat("test \?\?= ABC;"); - verifyFormat("test \?\?= true;"); + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + Style.SpaceBeforeAssignmentOperators = true; + + verifyFormat("test \?\?= ABC;", Style); + verifyFormat("test \?\?= true;", Style); + + Style.SpaceBeforeAssignmentOperators = false; + + verifyFormat("test\?\?= ABC;", Style); + verifyFormat("test\?\?= true;", Style); } TEST_F(FormatTestCSharp, CSharpNullForgiving) { Index: clang/lib/Format/TokenAnnotator.cpp === --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -3191,11 +3191,6 @@ if (Left.is(TT_CSharpNullCoalescing) || Right.is(TT_CSharpNullCoalescing)) return true; -// Space before and after '??='. -if (Left.is(TT_CSharpNullCoalescingAssignment) || -Right.is(TT_CSharpNullCoalescingAssignment)) - return true; - // No space before null forgiving '!'. if (Right.is(TT_JsNonNullAssertion)) return false; Index: clang/unittests/Format/FormatTestCSharp.cpp === --- clang/unittests/Format/FormatTestCSharp.cpp +++ clang/unittests/Format/FormatTestCSharp.cpp @@ -359,8 +359,16 @@ } TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) { - verifyFormat("test \?\?= ABC;"); - verifyFormat("test \?\?= true;"); + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + Style.SpaceBeforeAssignmentOperators = true; + + verifyFormat("test \?\?= ABC;", Style); + verifyFormat("test \?\?= true;", Style); + + Style.SpaceBeforeAssignmentOperators = false; + + verifyFormat("test\?\?= ABC;", Style); + verifyFormat("test\?\?= true;", Style); } TEST_F(FormatTestCSharp, CSharpNullForgiving) { Index: clang/lib/Format/TokenAnnotator.cpp === --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -3191,11 +3191,6 @@ if (Left.is(TT_CSharpNullCoalescing) || Right.is(TT_CSharpNullCoalescing)) return true; -// Space before and after '??='. -if (Left.is(TT_CSharpNullCoalescingAssignment) || -Right.is(TT_CSharpNullCoalescingAssignment)) - return true; - // No space before null forgiving '!'. if (Right.is(TT_JsNonNullAssertion)) return false; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv added inline comments. Comment at: clang/lib/Format/TokenAnnotator.cpp:3197 +Right.is(TT_CSharpNullCoalescingAssignment)) + return true; + MyDeveloperDay wrote: > should this honour SpaceBeforeAssignmentOperators ? Good point. Looking more closely, since I have called setKind(tok::equal) on the operator, it seems that the rest of clang-format reliably understands it as an assignment operator and formats it correctly if I don't intervene. I have updated the test case to test this behavior. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv updated this revision to Diff 342521. exv added a comment. Herald added a subscriber: JDevlieghere. Fixing arc, hopefully? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 Files: clang/lib/Format/FormatToken.h clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/FormatTokenLexer.h 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 @@ -358,6 +358,29 @@ verifyFormat("return _name ?? \"DEF\";"); } +TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + Style.SpaceBeforeAssignmentOperators = true; + + verifyFormat("test \?\?= ABC;", Style); + verifyFormat("test \?\?= true;", Style); + + Style.SpaceBeforeAssignmentOperators = false; + + verifyFormat("test\?\?= ABC;", Style); + verifyFormat("test\?\?= true;", Style); +} + +TEST_F(FormatTestCSharp, CSharpNullForgiving) { + verifyFormat("var test = null!;"); + verifyFormat("string test = someFunctionCall()! + \"ABC\"!"); + verifyFormat("int test = (1! + 2 + bar! + foo())!"); + verifyFormat("test \?\?= !foo!;"); + verifyFormat("test = !bar! \?\? !foo!;"); + verifyFormat("bool test = !(!true || !null! || !false && !false! && !bar()! " + "+ (!foo()))!"); +} + TEST_F(FormatTestCSharp, AttributesIndentation) { FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; Index: clang/lib/Format/TokenAnnotator.cpp === --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1579,24 +1579,29 @@ } } -if (Style.Language == FormatStyle::LK_JavaScript) { - if (Current.is(tok::exclaim)) { -if (Current.Previous && -(Keywords.IsJavaScriptIdentifier( - *Current.Previous, /* AcceptIdentifierName= */ true) || - Current.Previous->isOneOf( - tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, - Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) || - Current.Previous->Tok.isLiteral())) { - Current.setType(TT_JsNonNullAssertion); - return; -} -if (Current.Next && -Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) { +if ((Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) && +Current.is(tok::exclaim)) { + if (Current.Previous) { +bool isIdentifier = +Style.Language == FormatStyle::LK_JavaScript +? Keywords.IsJavaScriptIdentifier( + *Current.Previous, /* AcceptIdentifierName= */ true) +: Current.Previous->is(tok::identifier); +if (isIdentifier || +Current.Previous->isOneOf( +tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, +tok::kw_false, tok::kw_true, Keywords.kw_type, Keywords.kw_get, +Keywords.kw_set) || +Current.Previous->Tok.isLiteral()) { Current.setType(TT_JsNonNullAssertion); return; } } + if (Current.Next && + Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) { +Current.setType(TT_JsNonNullAssertion); +return; + } } // Line.MightBeFunctionDecl can only be true after the parentheses of a @@ -3186,6 +3191,10 @@ if (Left.is(TT_CSharpNullCoalescing) || Right.is(TT_CSharpNullCoalescing)) return true; +// No space before null forgiving '!'. +if (Right.is(TT_JsNonNullAssertion)) + return false; + // No space before '?['. if (Right.is(TT_CSharpNullConditionalLSquare)) return false; Index: clang/lib/Format/FormatTokenLexer.h === --- clang/lib/Format/FormatTokenLexer.h +++ clang/lib/Format/FormatTokenLexer.h @@ -54,7 +54,8 @@ bool tryMergeJSPrivateIdentifier(); bool tryMergeCSharpStringLiteral(); bool tryMergeCSharpKeywordVariables(); - bool tryMergeCSharpDoubleQuestion(); + bool tryMergeCSharpNullCoalescing(); + bool tryMergeCSharpNullCoalescingAssignment(); bool tryMergeCSharpNullConditional(); bool tryTransformCSharpForEach(); bool tryMergeForEach(); Index: clang/lib/Format/FormatTokenLexer.cpp === --- clang/lib/Format/FormatTokenLexer.cpp +++ clang/lib/Format/FormatTokenLexer.cpp @@ -97,7 +97,9 @@ return; if (tryMergeCSharpStringLiteral()) return; -if (tryMergeCSharpDoubleQuestion()) +if (tryMergeCSharpN
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv updated this revision to Diff 342520. exv added a comment. Herald added subscribers: llvm-commits, libcxx-commits, lldb-commits, Sanitizers, dcaballe, cota, teijeong, frasercrmck, dexonsmith, rdzhabarov, tatianashp, lxfind, dang, msifontes, jurahul, Kayjukh, grosul1, Joonsoo, stephenneuendorffer, kerbowa, liufengdb, aartbik, lucyrfox, mgester, arpith-jacob, csigg, nicolasvasilache, antiagainst, shauheen, rriddle, mehdi_amini, luismarques, apazos, sameer.abuasal, pengfei, s.egerton, Jim, jocewei, PkmX, jfb, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, MaskRay, jrtc27, gbedwell, niosHD, cryptoad, sabuasal, simoncook, johnrusso, rbar, asb, javed.absar, kbarton, hiraditya, mgorny, nhaehnle, jvesely, nemanjai, emaste, jholewinski. Herald added a reviewer: andreadb. Herald added a reviewer: rriddle. Herald added a reviewer: aartbik. Herald added a reviewer: aartbik. Herald added projects: Sanitizers, LLDB, libc++, MLIR, LLVM, clang-tools-extra. Herald added a reviewer: libc++. Fix incorrect arc usage Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 Files: clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp clang/include/clang/Basic/CodeGenOptions.def clang/include/clang/Basic/DiagnosticDriverKinds.td clang/include/clang/Driver/Options.td clang/lib/AST/TemplateBase.cpp clang/lib/CodeGen/TargetInfo.cpp clang/lib/Driver/ToolChains/Darwin.cpp clang/lib/Format/FormatToken.h clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/FormatTokenLexer.h clang/lib/Format/TokenAnnotator.cpp clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Headers/altivec.h clang/test/CodeGen/RISCV/rvv-intrinsics-overloaded/vcompress.c clang/test/CodeGen/RISCV/rvv-intrinsics/vcompress.c clang/test/CodeGen/builtins-ppc-altivec.c clang/test/CodeGen/builtins-ppc-vsx.c clang/test/CodeGenCXX/debug-info-codeview-display-name.cpp clang/test/CodeGenOpenCL/amdgpu-ieee.cl clang/test/Driver/darwin-ld-platform-version-macos.c clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp clang/unittests/Format/FormatTestCSharp.cpp compiler-rt/lib/scudo/standalone/combined.h compiler-rt/lib/scudo/standalone/internal_defs.h compiler-rt/lib/scudo/standalone/list.h compiler-rt/lib/scudo/standalone/local_cache.h compiler-rt/lib/scudo/standalone/mutex.h compiler-rt/lib/scudo/standalone/options.h compiler-rt/lib/scudo/standalone/primary32.h compiler-rt/lib/scudo/standalone/primary64.h compiler-rt/lib/scudo/standalone/quarantine.h compiler-rt/lib/scudo/standalone/secondary.h compiler-rt/lib/scudo/standalone/stack_depot.h compiler-rt/lib/scudo/standalone/stats.h compiler-rt/lib/scudo/standalone/tsd.h compiler-rt/lib/scudo/standalone/tsd_exclusive.h compiler-rt/lib/scudo/standalone/wrappers_c.cpp compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp libcxx/include/__config libcxx/include/__iterator/concepts.h libcxx/include/span libcxx/test/libcxx/iterators/iterator.concepts/iterator.concept.input/subsumption.compile.pass.cpp libcxx/test/libcxx/iterators/iterator.requirements/iterator.assoc.types/iterator.traits/legacy_bidirectional_iterator.compile.pass.cpp libcxx/test/libcxx/iterators/iterator.requirements/iterator.assoc.types/iterator.traits/legacy_forward_iterator.compile.pass.cpp libcxx/test/libcxx/iterators/iterator.requirements/iterator.assoc.types/iterator.traits/legacy_input_iterator.compile.pass.cpp libcxx/test/libcxx/iterators/iterator.requirements/iterator.assoc.types/iterator.traits/legacy_iterator.compile.pass.cpp libcxx/test/libcxx/iterators/iterator.requirements/iterator.assoc.types/iterator.traits/legacy_random_access_iterator.compile.pass.cpp libcxx/test/libcxx/iterators/iterator.requirements/iterator.assoc.types/iterator.traits/locale_dependent.compile.pass.cpp libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/integer_like.compile.pass.cpp libcxx/test/std/containers/associative/map/iterator_concept_conformance.compile.pass.cpp libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp libcxx/test/std/containers/associative/multimap/iterator_concept_conformance.compile.pass.cpp libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp libcxx/test/std/containers/associative/multiset/iterator_concept_conformance.compile.pass.cpp libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp libcxx/test/std/containers/associative/set/iterator_concept_conformance.compile.pass.cpp libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp libcxx/test/std/containers/sequences/array/iterator_concept_conformance.compile.pass.cpp libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp libcxx/test/std/containers/sequences/deque/it
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv added a comment. Hey all, I'm really sorry for the noise, I screwed up my arc command to revise the submission. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv added inline comments. Comment at: clang/unittests/Format/FormatTestCSharp.cpp:365 + + verifyFormat("test \?\?= ABC;", Style); + verifyFormat("test \?\?= true;", Style); HazardyKnusperkeks wrote: > Why do you escape `?`? I've never seen that. Apparently, ??= is a trigraph for "#" in C, so it must be escaped: https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C To be honest, I'd never heard of this bizarre language "feature" until I wrote this patch. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv updated this revision to Diff 342594. exv marked 2 inline comments as done. exv added a comment. - [clang-format] Add more support for C# 8 nullables - Fix null-coalescing assignment whitespace behavior - Incorporate feedback from curdeius - Combine JS and CS types/parsing Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 Files: clang/lib/Format/FormatToken.h clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/FormatTokenLexer.h 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 @@ -358,6 +358,39 @@ verifyFormat("return _name ?? \"DEF\";"); } +TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + Style.SpaceBeforeAssignmentOperators = true; + + verifyFormat("test \?\?= ABC;", Style); + verifyFormat("test \?\?= true;", Style); + + Style.SpaceBeforeAssignmentOperators = false; + + verifyFormat("test\?\?= ABC;", Style); + verifyFormat("test\?\?= true;", Style); +} + +TEST_F(FormatTestCSharp, CSharpNullForgiving) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + + verifyFormat("var test = null!;", Style); + verifyFormat("string test = someFunctionCall()! + \"ABC\"!", Style); + verifyFormat("int test = (1! + 2 + bar! + foo())!", Style); + verifyFormat("test \?\?= !foo!;", Style); + verifyFormat("test = !bar! \?\? !foo!;", Style); + verifyFormat("bool test = !(!true && !true! || !null && !null! || !false && " + "!false! && !bar()! + (!foo()))!", + Style); + + // Check that line break keeps identifier with the bang. + Style.ColumnLimit = 14; + + verifyFormat("var test =\n" + "foo!;", + Style); +} + TEST_F(FormatTestCSharp, AttributesIndentation) { FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; Index: clang/lib/Format/TokenAnnotator.cpp === --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1048,13 +1048,6 @@ CurrentToken->Previous->setType(TT_OverloadedOperator); break; case tok::question: - if (Tok->is(TT_CSharpNullConditionalLSquare)) { -if (!parseSquare()) - return false; -break; - } - if (Tok->isOneOf(TT_CSharpNullConditional, TT_CSharpNullCoalescing)) -break; if (Style.Language == FormatStyle::LK_JavaScript && Tok->Next && Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren, tok::r_brace)) { @@ -1078,7 +1071,7 @@ (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->setType(TT_CSharpNullable); + Tok->setType(TT_JsTypeOptionalQuestion); break; } } @@ -1564,39 +1557,29 @@ // The token type is already known. return; -if (Style.isCSharp() && CurrentToken->is(tok::question)) { - if (CurrentToken->TokenText == "??") { -Current.setType(TT_CSharpNullCoalescing); -return; - } - if (CurrentToken->TokenText == "?.") { -Current.setType(TT_CSharpNullConditional); -return; - } - if (CurrentToken->TokenText == "?[") { -Current.setType(TT_CSharpNullConditionalLSquare); -return; - } -} - -if (Style.Language == FormatStyle::LK_JavaScript) { - if (Current.is(tok::exclaim)) { -if (Current.Previous && -(Keywords.IsJavaScriptIdentifier( - *Current.Previous, /* AcceptIdentifierName= */ true) || - Current.Previous->isOneOf( - tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, - Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) || - Current.Previous->Tok.isLiteral())) { - Current.setType(TT_JsNonNullAssertion); - return; -} -if (Current.Next && -Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) { +if ((Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) && +Current.is(tok::exclaim)) { + if (Current.Previous) { +bool isIdentifier = +Style.Language == FormatStyle::LK_JavaScript +? Keywords.IsJavaScriptIdentifier( + *Current.Previous, /* AcceptIdentifierName= */ true) +: Current.Previous->is(tok::identifier); +if (isIdentifier || +
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv added inline comments. Comment at: clang/lib/Format/TokenAnnotator.cpp:1593 +tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, +tok::kw_false, tok::kw_true, Keywords.kw_type, Keywords.kw_get, +Keywords.kw_set) || curdeius wrote: > Does adding false and true here may negatively affect JS in any way? (Just > thinking out loud) Nothing I can see: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator Comment at: clang/lib/Format/TokenAnnotator.cpp:3195 +// No space before null forgiving '!'. +if (Right.is(TT_JsNonNullAssertion)) + return false; curdeius wrote: > Should it be renamed to include C#? Now that you've mentioned it, I do see that JS also defines an almost duplicate set of null-related operators, including null-propagating, null-coalescing and null-coalescing assignment operators, and clang-format handles them with a different code path than C# 😅. They do have slightly different names, but the way they should be parsed and interpreted is the same, and I think it makes sense to use the same logic and token definitions for both of these languages. This resulted in a lot of special-handling for C# tokens that wasn't necessary being removed too. However, renaming them would introduce a lot of noise, so I think I would prefer to do that in a separate commit. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv updated this revision to Diff 342813. exv marked an inline comment as done. exv added a comment. - Remove obsolete comment Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 Files: clang/lib/Format/FormatToken.h clang/lib/Format/FormatTokenLexer.cpp clang/lib/Format/FormatTokenLexer.h 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 @@ -358,6 +358,39 @@ verifyFormat("return _name ?? \"DEF\";"); } +TEST_F(FormatTestCSharp, CSharpNullCoalescingAssignment) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + Style.SpaceBeforeAssignmentOperators = true; + + verifyFormat("test \?\?= ABC;", Style); + verifyFormat("test \?\?= true;", Style); + + Style.SpaceBeforeAssignmentOperators = false; + + verifyFormat("test\?\?= ABC;", Style); + verifyFormat("test\?\?= true;", Style); +} + +TEST_F(FormatTestCSharp, CSharpNullForgiving) { + FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); + + verifyFormat("var test = null!;", Style); + verifyFormat("string test = someFunctionCall()! + \"ABC\"!", Style); + verifyFormat("int test = (1! + 2 + bar! + foo())!", Style); + verifyFormat("test \?\?= !foo!;", Style); + verifyFormat("test = !bar! \?\? !foo!;", Style); + verifyFormat("bool test = !(!true && !true! || !null && !null! || !false && " + "!false! && !bar()! + (!foo()))!", + Style); + + // Check that line break keeps identifier with the bang. + Style.ColumnLimit = 14; + + verifyFormat("var test =\n" + "foo!;", + Style); +} + TEST_F(FormatTestCSharp, AttributesIndentation) { FormatStyle Style = getMicrosoftStyle(FormatStyle::LK_CSharp); Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None; Index: clang/lib/Format/TokenAnnotator.cpp === --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1048,13 +1048,6 @@ CurrentToken->Previous->setType(TT_OverloadedOperator); break; case tok::question: - if (Tok->is(TT_CSharpNullConditionalLSquare)) { -if (!parseSquare()) - return false; -break; - } - if (Tok->isOneOf(TT_CSharpNullConditional, TT_CSharpNullCoalescing)) -break; if (Style.Language == FormatStyle::LK_JavaScript && Tok->Next && Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren, tok::r_brace)) { @@ -1078,7 +1071,7 @@ (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->setType(TT_CSharpNullable); + Tok->setType(TT_JsTypeOptionalQuestion); break; } } @@ -1564,39 +1557,29 @@ // The token type is already known. return; -if (Style.isCSharp() && CurrentToken->is(tok::question)) { - if (CurrentToken->TokenText == "??") { -Current.setType(TT_CSharpNullCoalescing); -return; - } - if (CurrentToken->TokenText == "?.") { -Current.setType(TT_CSharpNullConditional); -return; - } - if (CurrentToken->TokenText == "?[") { -Current.setType(TT_CSharpNullConditionalLSquare); -return; - } -} - -if (Style.Language == FormatStyle::LK_JavaScript) { - if (Current.is(tok::exclaim)) { -if (Current.Previous && -(Keywords.IsJavaScriptIdentifier( - *Current.Previous, /* AcceptIdentifierName= */ true) || - Current.Previous->isOneOf( - tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, - Keywords.kw_type, Keywords.kw_get, Keywords.kw_set) || - Current.Previous->Tok.isLiteral())) { - Current.setType(TT_JsNonNullAssertion); - return; -} -if (Current.Next && -Current.Next->isOneOf(TT_BinaryOperator, Keywords.kw_as)) { +if ((Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) && +Current.is(tok::exclaim)) { + if (Current.Previous) { +bool isIdentifier = +Style.Language == FormatStyle::LK_JavaScript +? Keywords.IsJavaScriptIdentifier( + *Current.Previous, /* AcceptIdentifierName= */ true) +: Current.Previous->is(tok::identifier); +if (isIdentifier || +Current.Previous->isOneOf( +tok::kw_namespace, tok::r_paren, tok::r_square, tok::r_brace, +tok::kw_false, tok::kw_tru
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv marked an inline comment as done. exv added a comment. According to the wiki, it seems like someone who has commit access must now submit this change. Comment at: clang/lib/Format/FormatTokenLexer.cpp:102 + +// FIXME: Investigate what token type gives the correct operator priority. +if (tryMergeTokens(FatArrow, TT_JsFatArrow)) curdeius wrote: > Could you explain in what case the operator precedence may be wrong here? It's unlikely this comment is still relevant for this section. I will delete it. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D101702: [clang-format] Add more support for C# 8 nullables
exv marked an inline comment as done. exv added a comment. Eliza Velasquez Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101702/new/ https://reviews.llvm.org/D101702 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits