Skip to content

Commit

Permalink
[clang-format] Support text proto extensions
Browse files Browse the repository at this point in the history
Summary:
This adds support for text proto extensions, like:
```
msg {
  [type.type/ext] {
    key: value
  }
}
```

Reviewers: djasper

Reviewed By: djasper

Subscribers: klimek, cfe-commits

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

llvm-svn: 324995
  • Loading branch information
krasimirgg committed Feb 13, 2018
1 parent 1f95ef1 commit 4e29064
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 6 deletions.
2 changes: 2 additions & 0 deletions clang/lib/Format/ContinuationIndenter.cpp
Expand Up @@ -943,6 +943,8 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
!Current.isOneOf(tok::colon, tok::comment))
return ContinuationIndent;
if (Current.is(TT_ProtoExtensionLSquare))
return State.Stack.back().Indent;
if (State.Stack.back().Indent == State.FirstIndent && PreviousNonComment &&
PreviousNonComment->isNot(tok::r_brace))
// Ensure that we fall back to the continuation indent width instead of
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Format/FormatToken.h
Expand Up @@ -88,6 +88,7 @@ namespace format {
TYPE(TemplateCloser) \
TYPE(TemplateOpener) \
TYPE(TemplateString) \
TYPE(ProtoExtensionLSquare) \
TYPE(TrailingAnnotation) \
TYPE(TrailingReturnArrow) \
TYPE(TrailingUnaryOperator) \
Expand Down
44 changes: 38 additions & 6 deletions clang/lib/Format/TokenAnnotator.cpp
Expand Up @@ -368,12 +368,35 @@ class AnnotatingParser {
Parent->is(TT_TemplateCloser)) {
Left->Type = TT_ArraySubscriptLSquare;
} else if (Style.Language == FormatStyle::LK_Proto ||
(!CppArrayTemplates && Parent &&
Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,
tok::comma, tok::l_paren, tok::l_square,
tok::question, tok::colon, tok::kw_return,
// Should only be relevant to JavaScript:
tok::kw_default))) {
Style.Language == FormatStyle::LK_TextProto) {
// Square braces in LK_Proto can either be message field attributes:
//
// optional Aaa aaa = 1 [
// (aaa) = aaa
// ];
//
// or text proto extensions (in options):
//
// option (Aaa.options) = {
// [type.type/type] {
// key: value
// }
// }
//
// In the first case we want to spread the contents inside the square
// braces; in the second we want to keep them inline.
Left->Type = TT_ArrayInitializerLSquare;
if (!Left->endsSequence(tok::l_square, tok::numeric_constant,
tok::equal)) {
Left->Type = TT_ProtoExtensionLSquare;
BindingIncrease = 10;
}
} else if (!CppArrayTemplates && Parent &&
Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at,
tok::comma, tok::l_paren, tok::l_square,
tok::question, tok::colon, tok::kw_return,
// Should only be relevant to JavaScript:
tok::kw_default)) {
Left->Type = TT_ArrayInitializerLSquare;
} else {
BindingIncrease = 10;
Expand Down Expand Up @@ -2396,6 +2419,12 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return true;
if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))
return true;
// Slashes occur in text protocol extension syntax: [type/type] { ... }.
if (Left.is(tok::slash) || Right.is(tok::slash))
return false;
if (Left.MatchingParen && Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&
Right.isOneOf(tok::l_brace, tok::less))
return !Style.Cpp11BracedListStyle;
} else if (Style.Language == FormatStyle::LK_JavaScript) {
if (Left.is(TT_JsFatArrow))
return true;
Expand Down Expand Up @@ -2732,6 +2761,9 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
(Line.Last->is(tok::l_brace) || Style.BreakAfterJavaFieldAnnotations))
return true;

if (Right.is(TT_ProtoExtensionLSquare))
return true;

return false;
}

Expand Down
11 changes: 11 additions & 0 deletions clang/unittests/Format/FormatTestProto.cpp
Expand Up @@ -421,5 +421,16 @@ TEST_F(FormatTestProto, KeepsLongStringLiteralsOnSameLine) {
"}");
}

TEST_F(FormatTestProto, FormatsOptionsExtensions) {
verifyFormat("option (MyProto.options) = {\n"
" msg_field: { field_d: 123 }\n"
" [ext.t/u] { key: value }\n"
" key: value\n"
" [t.u/v] <\n"
" [ext] { key: value }\n"
" >\n"
"};");
}

} // end namespace tooling
} // end namespace clang
61 changes: 61 additions & 0 deletions clang/unittests/Format/FormatTestTextProto.cpp
Expand Up @@ -325,5 +325,66 @@ TEST_F(FormatTestTextProto, KeepsCommentsIndentedInList) {
"cccccccccccccccccccccccc: 3849");
}

TEST_F(FormatTestTextProto, FormatsExtensions) {
verifyFormat("[type] { key: value }");
verifyFormat("[type] {\n"
" keyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy: value\n"
"}");
verifyFormat("[type.type] { key: value }");
verifyFormat("[type.type] < key: value >");
verifyFormat("[type.type/type.type] { key: value }");
verifyFormat("msg {\n"
" [type.type] { key: value }\n"
"}");
verifyFormat("msg {\n"
" [type.type] {\n"
" keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
" }\n"
"}");
verifyFormat("key: value\n"
"[a.b] { key: value }");
verifyFormat("msg: <\n"
" key: value\n"
" [a.b.c/d.e]: < key: value >\n"
" [f.g]: <\n"
" key: valueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n"
" key: {}\n"
" >\n"
" key {}\n"
" [h.i.j] < key: value >\n"
" [a]: {\n"
" [b.c]: {}\n"
" [d] <>\n"
" [e/f]: 1\n"
" }\n"
">");
verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
" .longg.longlong] { key: value }");
verifyFormat("[longg.long.long.long.long.long.long.long.long.long.long\n"
" .longg.longlong] {\n"
" key: value\n"
" key: value\n"
" key: value\n"
" key: value\n"
"}");
verifyFormat("[longg.long.long.long.long.long.long.long.long.long\n"
" .long/longg.longlong] { key: value }");
verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
" bbbbbbbbbbbbbb] { key: value }");
verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
"] { key: value }");
verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
"] {\n"
" [type.type] {\n"
" keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
" }\n"
"}");
verifyFormat("[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/\n"
" bbbbbbb] {\n"
" [type.type] {\n"
" keyyyyyyyyyyyyyy: valuuuuuuuuuuuuuuuuuuuuuuuuue\n"
" }\n"
"}");
}
} // end namespace tooling
} // end namespace clang

0 comments on commit 4e29064

Please sign in to comment.