Skip to content

Commit

Permalink
[clang-format] Support repeated field lists in protos
Browse files Browse the repository at this point in the history
Summary:
This patch adds support for list initialization of proto repeated fields:
```
keys: [1, 2, 3]
```

Reviewers: djasper

Reviewed By: djasper

Subscribers: klimek, cfe-commits

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

llvm-svn: 325252
  • Loading branch information
krasimirgg committed Feb 15, 2018
1 parent 1e002a2 commit b79987a
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 11 deletions.
31 changes: 24 additions & 7 deletions clang/lib/Format/TokenAnnotator.cpp
Expand Up @@ -383,11 +383,18 @@ class AnnotatingParser {
// }
// }
//
// In the first case we want to spread the contents inside the square
// braces; in the second we want to keep them inline.
// or repeated fields (in options):
//
// option (Aaa.options) = {
// keys: [ 1, 2, 3 ]
// }
//
// In the first and the third 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)) {
tok::equal) &&
!Left->endsSequence(tok::l_square, tok::colon, TT_SelectorName)) {
Left->Type = TT_ProtoExtensionLSquare;
BindingIncrease = 10;
}
Expand Down Expand Up @@ -2331,16 +2338,26 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
!Left.Previous->isOneOf(tok::l_paren, tok::coloncolon));
if (Right.is(tok::star) && Left.is(tok::l_paren))
return false;
const auto SpaceRequiredForArrayInitializerLSquare =
[](const FormatToken &LSquareTok, const FormatStyle &Style) {
return Style.SpacesInContainerLiterals ||
((Style.Language == FormatStyle::LK_Proto ||
Style.Language == FormatStyle::LK_TextProto) &&
!Style.Cpp11BracedListStyle &&
LSquareTok.endsSequence(tok::l_square, tok::colon,
TT_SelectorName));
};
if (Left.is(tok::l_square))
return (Left.is(TT_ArrayInitializerLSquare) &&
Style.SpacesInContainerLiterals && Right.isNot(tok::r_square)) ||
return (Left.is(TT_ArrayInitializerLSquare) && Right.isNot(tok::r_square) &&
SpaceRequiredForArrayInitializerLSquare(Left, Style)) ||
(Left.isOneOf(TT_ArraySubscriptLSquare,
TT_StructuredBindingLSquare) &&
Style.SpacesInSquareBrackets && Right.isNot(tok::r_square));
if (Right.is(tok::r_square))
return Right.MatchingParen &&
((Style.SpacesInContainerLiterals &&
Right.MatchingParen->is(TT_ArrayInitializerLSquare)) ||
((Right.MatchingParen->is(TT_ArrayInitializerLSquare) &&
SpaceRequiredForArrayInitializerLSquare(*Right.MatchingParen,
Style)) ||
(Style.SpacesInSquareBrackets &&
Right.MatchingParen->isOneOf(TT_ArraySubscriptLSquare,
TT_StructuredBindingLSquare)));
Expand Down
30 changes: 30 additions & 0 deletions clang/unittests/Format/FormatTestProto.cpp
Expand Up @@ -438,5 +438,35 @@ TEST_F(FormatTestProto, NoSpaceAfterPercent) {
"};");
}

TEST_F(FormatTestProto, FormatsRepeatedListInitializersInOptions) {
verifyFormat("option (MyProto.options) = {\n"
" key: item\n"
" keys: [\n"
" 'ala',\n"
" 'bala',\n"
" 'porto',\n"
" 'kala',\n"
" 'too',\n"
" 'long',\n"
" 'long',\n"
" 'long'\n"
" ]\n"
" key: [ item ]\n"
" msg {\n"
" key: item\n"
" keys: [\n"
" 'ala',\n"
" 'bala',\n"
" 'porto',\n"
" 'kala',\n"
" 'too',\n"
" 'long',\n"
" 'long'\n"
" ]\n"
" }\n"
" key: value\n"
"};");
}

} // end namespace tooling
} // end namespace clang
50 changes: 46 additions & 4 deletions clang/unittests/Format/FormatTestTextProto.cpp
Expand Up @@ -31,14 +31,18 @@ class FormatTestTextProto : public ::testing::Test {
return *Result;
}

static std::string format(llvm::StringRef Code) {
FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
Style.ColumnLimit = 60; // To make writing tests easier.
static std::string format(llvm::StringRef Code, const FormatStyle &Style) {
return format(Code, 0, Code.size(), Style);
}

static void verifyFormat(llvm::StringRef Code, const FormatStyle &Style) {
EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
}

static void verifyFormat(llvm::StringRef Code) {
EXPECT_EQ(Code.str(), format(test::messUp(Code)));
FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
Style.ColumnLimit = 60; // To make writing tests easier.
verifyFormat(Code, Style);
}
};

Expand Down Expand Up @@ -390,5 +394,43 @@ TEST_F(FormatTestTextProto, FormatsExtensions) {
TEST_F(FormatTestTextProto, NoSpaceAfterPercent) {
verifyFormat("key: %d");
}

TEST_F(FormatTestTextProto, FormatsRepeatedListInitializers) {
verifyFormat("keys: []");
verifyFormat("keys: [ 1 ]");
verifyFormat("keys: [ 'ala', 'bala' ]");
verifyFormat("keys:\n"
" [ 'ala', 'bala', 'porto', 'kala', 'too', 'long', 'ng' ]");
verifyFormat("key: item\n"
"keys: [\n"
" 'ala',\n"
" 'bala',\n"
" 'porto',\n"
" 'kala',\n"
" 'too',\n"
" 'long',\n"
" 'long',\n"
" 'long'\n"
"]\n"
"key: item\n"
"msg {\n"
" key: item\n"
" keys: [\n"
" 'ala',\n"
" 'bala',\n"
" 'porto',\n"
" 'kala',\n"
" 'too',\n"
" 'long',\n"
" 'long'\n"
" ]\n"
"}\n"
"key: value"
);
FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
Style.ColumnLimit = 60; // To make writing tests easier.
Style.Cpp11BracedListStyle = true;
verifyFormat("keys: [1]", Style);
}
} // end namespace tooling
} // end namespace clang

0 comments on commit b79987a

Please sign in to comment.