diff options
Diffstat (limited to 'clang/lib/Format/TokenAnnotator.cpp')
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 3280f25fef0..68ea02296b7 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2949,15 +2949,32 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, // // Be careful to exclude the case [proto.ext] { ... } since the `]` is // the TT_SelectorName there, but we don't want to break inside the brackets. + // + // Another edge case is @submessage { key: value }, which is a common + // substitution placeholder. In this case we want to keep `@` and `submessage` + // together. + // // We ensure elsewhere that extensions are always on their own line. if ((Style.Language == FormatStyle::LK_Proto || Style.Language == FormatStyle::LK_TextProto) && Right.is(TT_SelectorName) && !Right.is(tok::r_square) && Right.Next) { + // Keep `@submessage` together in: + // @submessage { key: value } + if (Right.Previous && Right.Previous->is(tok::at)) + return false; // Look for the scope opener after selector in cases like: // selector { ... // selector: { ... - FormatToken *LBrace = - Right.Next->is(tok::colon) ? Right.Next->Next : Right.Next; + // selector: @base { ... + FormatToken *LBrace = Right.Next; + if (LBrace && LBrace->is(tok::colon)) { + LBrace = LBrace->Next; + if (LBrace && LBrace->is(tok::at)) { + LBrace = LBrace->Next; + if (LBrace) + LBrace = LBrace->Next; + } + } if (LBrace && // The scope opener is one of {, [, <: // selector { ... } |