return false;
}
}
- return true;
+ // There are no top-level unbalanced braces in text protos.
+ return Style.Language != FormatStyle::LK_TextProto;
}
void updateParameterCount(FormatToken *Left, FormatToken *Current) {
} else if (Contexts.back().ContextKind == tok::l_paren) {
Tok->Type = TT_InlineASMColon;
}
+ // Detects trailing pieces like key:
+ if ((Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto) &&
+ !CurrentToken)
+ return false;
break;
case tok::pipe:
case tok::amp:
if (Previous && Previous->Type != TT_DictLiteral)
Previous->Type = TT_SelectorName;
}
+ } else if (Style.Language == FormatStyle::LK_TextProto ||
+ Style.Language == FormatStyle::LK_Proto) {
+ // In TT_Proto and TT_TextProto, tok::less cannot be a binary operator.
+ return false;
} else {
Tok->Type = TT_BinaryOperator;
NonTemplateLess.insert(Tok);
case tok::r_square:
return false;
case tok::r_brace:
- // Lines can start with '}'.
- if (Tok->Previous)
+ // Lines can start with '}' except in text protos.
+ if (Tok->Previous || Style.Language == FormatStyle::LK_TextProto)
return false;
break;
case tok::greater:
- if (Style.Language != FormatStyle::LK_TextProto)
- Tok->Type = TT_BinaryOperator;
+ // In protos and text protos tok::greater cannot be a binary operator.
+ if (Style.Language == FormatStyle::LK_Proto ||
+ Style.Language == FormatStyle::LK_TextProto)
+ return false;
+ Tok->Type = TT_BinaryOperator;
break;
case tok::kw_operator:
if (Style.Language == FormatStyle::LK_TextProto ||
namespace format {
class FormatTestProto : public ::testing::Test {
+ enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete };
+
protected:
static std::string format(llvm::StringRef Code, unsigned Offset,
- unsigned Length, const FormatStyle &Style) {
+ unsigned Length, const FormatStyle &Style,
+ StatusCheck CheckComplete = SC_ExpectComplete) {
DEBUG(llvm::errs() << "---\n");
DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
- tooling::Replacements Replaces = reformat(Style, Code, Ranges);
+ FormattingAttemptStatus Status;
+ tooling::Replacements Replaces =
+ reformat(Style, Code, Ranges, "<stdin>", &Status);
+ bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
+ EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
+ << Code << "\n\n";
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
EXPECT_EQ(Code.str(), format(Code)) << "Expected code is not stable";
EXPECT_EQ(Code.str(), format(test::messUp(Code)));
}
+
+ static void verifyIncompleteFormat(llvm::StringRef Code) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_Proto);
+ EXPECT_EQ(Code.str(),
+ format(Code, 0, Code.size(), Style, SC_ExpectIncomplete));
+ }
};
TEST_F(FormatTestProto, FormatsMessages) {
"};");
}
+TEST_F(FormatTestProto, IncompleteFormat) {
+ verifyIncompleteFormat("option (");
+ verifyIncompleteFormat("option (MyProto.options) = { bbbbbbbbb:");
+ verifyIncompleteFormat("option (MyProto.options) = { bbbbbbbbb: <\n");
+ verifyIncompleteFormat("option (MyProto.options) = { bbbbbbbbb: [\n");
+}
+
} // end namespace tooling
} // end namespace clang
class FormatTestTextProto : public ::testing::Test {
protected:
+ enum StatusCheck { SC_ExpectComplete, SC_ExpectIncomplete };
+
static std::string format(llvm::StringRef Code, unsigned Offset,
- unsigned Length, const FormatStyle &Style) {
+ unsigned Length, const FormatStyle &Style,
+ StatusCheck CheckComplete = SC_ExpectComplete) {
DEBUG(llvm::errs() << "---\n");
DEBUG(llvm::errs() << Code << "\n\n");
std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
- tooling::Replacements Replaces = reformat(Style, Code, Ranges);
+ FormattingAttemptStatus Status;
+ tooling::Replacements Replaces =
+ reformat(Style, Code, Ranges, "<stdin>", &Status);
+ bool ExpectedCompleteFormat = CheckComplete == SC_ExpectComplete;
+ EXPECT_EQ(ExpectedCompleteFormat, Status.FormatComplete)
+ << Code << "\n\n";
auto Result = applyAllReplacements(Code, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
Style.ColumnLimit = 60; // To make writing tests easier.
verifyFormat(Code, Style);
}
+
+ static void verifyIncompleteFormat(llvm::StringRef Code) {
+ FormatStyle Style = getGoogleStyle(FormatStyle::LK_TextProto);
+ EXPECT_EQ(Code.str(),
+ format(Code, 0, Code.size(), Style, SC_ExpectIncomplete));
+ }
};
TEST_F(FormatTestTextProto, KeepsTopLevelEntriesFittingALine) {
"}", Style);
}
+TEST_F(FormatTestTextProto, IncompleteFormat) {
+ verifyIncompleteFormat("data {");
+ verifyIncompleteFormat("data <");
+ verifyIncompleteFormat("data [");
+ verifyIncompleteFormat("data: {");
+ verifyIncompleteFormat("data: <");
+ verifyIncompleteFormat("data: [");
+ verifyIncompleteFormat("key:");
+ verifyIncompleteFormat("key:}");
+ verifyIncompleteFormat("key: ]");
+ verifyIncompleteFormat("key: >");
+ verifyIncompleteFormat(": value");
+ verifyIncompleteFormat(": {}");
+ verifyIncompleteFormat(": <>");
+ verifyIncompleteFormat(": []");
+ verifyIncompleteFormat("}\n"
+ "key: value");
+ verifyIncompleteFormat("]\n"
+ "key: value");
+ verifyIncompleteFormat("> key: value");
+ verifyIncompleteFormat("data { key: {");
+ verifyIncompleteFormat("data < key: [");
+ verifyIncompleteFormat("data [ key: {");
+ verifyIncompleteFormat("> key: value {");
+ verifyIncompleteFormat("> key: [");
+ verifyIncompleteFormat("}\n"
+ "key: {");
+ verifyIncompleteFormat("data { key: 1 id:");
+ verifyIncompleteFormat("}\n"
+ "key {");
+ verifyIncompleteFormat("> <");
+}
+
} // end namespace tooling
} // end namespace clang