jbcoe updated this revision to Diff 253925. jbcoe added a comment. Fix failing test by preventing inconsistent states from being constructed where canBreak is false and mustBreak is true.
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D77064/new/ https://reviews.llvm.org/D77064 Files: clang/lib/Format/ContinuationIndenter.cpp clang/lib/Format/TokenAnnotator.cpp 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 @@ -564,7 +564,7 @@ TEST_F(FormatTestCSharp, CSharpArrayInitializers) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); - + verifyFormat(R"(// private MySet<Node>[] setPoints = { new Point<Node>(), @@ -710,6 +710,15 @@ IAnotherInterfaceStill<T> {})", Style); + Style.ColumnLimit = 50; // Force lines to be wrapped. + verifyFormat(R"(// +class ItemFactory<T, U> + where T : new(), + IAnInterface<T>, + IAnotherInterface<T, U>, + IAnotherInterfaceStill<T, U> {})", + Style); + // In other languages `where` can be used as a normal identifier. // This example is in C++! verifyFormat(R"(// Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -2340,6 +2340,12 @@ } if (FormatTok->Tok.is(tok::semi)) return; + if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) { + addUnwrappedLine(); + nextToken(); + parseCSharpGenericTypeConstraint(); + break; + } nextToken(); } } Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1060,15 +1060,20 @@ } void parseCSharpGenericTypeConstraint() { + int OpenAngleBracketsCount = 0; while (CurrentToken) { if (CurrentToken->is(tok::less)) { // parseAngle is too greedy and will consume the whole line. CurrentToken->Type = TT_TemplateOpener; + ++OpenAngleBracketsCount; next(); } else if (CurrentToken->is(tok::greater)) { CurrentToken->Type = TT_TemplateCloser; + --OpenAngleBracketsCount; next(); - } else if (CurrentToken->is(tok::comma)) { + } else if (CurrentToken->is(tok::comma) && OpenAngleBracketsCount == 0) { + // We allow line breaks after GenericTypeConstraintComma's + // so do not flag commas in Generics as GenericTypeConstraintComma's. CurrentToken->Type = TT_CSharpGenericTypeConstraintComma; next(); } else if (CurrentToken->is(Keywords.kw_where)) { Index: clang/lib/Format/ContinuationIndenter.cpp =================================================================== --- clang/lib/Format/ContinuationIndenter.cpp +++ clang/lib/Format/ContinuationIndenter.cpp @@ -346,6 +346,11 @@ Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) { return true; } + // Avoid producing inconsistent states by requiring breaks where they are not + // permitted for C# generic type constraints. + if (State.Stack.back().IsCSharpGenericTypeConstraint && + Previous.isNot(TT_CSharpGenericTypeConstraintComma)) + return false; if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) && Style.isCpp() &&
Index: clang/unittests/Format/FormatTestCSharp.cpp =================================================================== --- clang/unittests/Format/FormatTestCSharp.cpp +++ clang/unittests/Format/FormatTestCSharp.cpp @@ -564,7 +564,7 @@ TEST_F(FormatTestCSharp, CSharpArrayInitializers) { FormatStyle Style = getGoogleStyle(FormatStyle::LK_CSharp); - + verifyFormat(R"(// private MySet<Node>[] setPoints = { new Point<Node>(), @@ -710,6 +710,15 @@ IAnotherInterfaceStill<T> {})", Style); + Style.ColumnLimit = 50; // Force lines to be wrapped. + verifyFormat(R"(// +class ItemFactory<T, U> + where T : new(), + IAnInterface<T>, + IAnotherInterface<T, U>, + IAnotherInterfaceStill<T, U> {})", + Style); + // In other languages `where` can be used as a normal identifier. // This example is in C++! verifyFormat(R"(// Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -2340,6 +2340,12 @@ } if (FormatTok->Tok.is(tok::semi)) return; + if (Style.isCSharp() && FormatTok->is(Keywords.kw_where)) { + addUnwrappedLine(); + nextToken(); + parseCSharpGenericTypeConstraint(); + break; + } nextToken(); } } Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1060,15 +1060,20 @@ } void parseCSharpGenericTypeConstraint() { + int OpenAngleBracketsCount = 0; while (CurrentToken) { if (CurrentToken->is(tok::less)) { // parseAngle is too greedy and will consume the whole line. CurrentToken->Type = TT_TemplateOpener; + ++OpenAngleBracketsCount; next(); } else if (CurrentToken->is(tok::greater)) { CurrentToken->Type = TT_TemplateCloser; + --OpenAngleBracketsCount; next(); - } else if (CurrentToken->is(tok::comma)) { + } else if (CurrentToken->is(tok::comma) && OpenAngleBracketsCount == 0) { + // We allow line breaks after GenericTypeConstraintComma's + // so do not flag commas in Generics as GenericTypeConstraintComma's. CurrentToken->Type = TT_CSharpGenericTypeConstraintComma; next(); } else if (CurrentToken->is(Keywords.kw_where)) { Index: clang/lib/Format/ContinuationIndenter.cpp =================================================================== --- clang/lib/Format/ContinuationIndenter.cpp +++ clang/lib/Format/ContinuationIndenter.cpp @@ -346,6 +346,11 @@ Current.startsSequence(TT_SelectorName, tok::colon, tok::caret)) { return true; } + // Avoid producing inconsistent states by requiring breaks where they are not + // permitted for C# generic type constraints. + if (State.Stack.back().IsCSharpGenericTypeConstraint && + Previous.isNot(TT_CSharpGenericTypeConstraintComma)) + return false; if ((startsNextParameter(Current, Style) || Previous.is(tok::semi) || (Previous.is(TT_TemplateCloser) && Current.is(TT_StartOfName) && Style.isCpp() &&
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits