[clang-format] fix namepsace format when the name is macro expansion
Originally filed at crbug.com/1184570. When the name of a namespace is a macro that takes arguments, - It fixed the indentation. - It fixed the namepsace end comments. Differential Revision: https://reviews.llvm.org/D120931
This commit is contained in:
parent
9129743dde
commit
be5705767a
|
@ -40,12 +40,32 @@ std::string computeName(const FormatToken *NamespaceTok) {
|
|||
Tok = Tok->getNextNonComment();
|
||||
}
|
||||
} else {
|
||||
// Skip attributes.
|
||||
if (Tok && Tok->is(tok::l_square)) {
|
||||
for (int NestLevel = 1; NestLevel > 0;) {
|
||||
Tok = Tok->getNextNonComment();
|
||||
if (!Tok)
|
||||
break;
|
||||
if (Tok->is(tok::l_square))
|
||||
++NestLevel;
|
||||
else if (Tok->is(tok::r_square))
|
||||
--NestLevel;
|
||||
}
|
||||
if (Tok)
|
||||
Tok = Tok->getNextNonComment();
|
||||
}
|
||||
|
||||
// Use the string after `namespace` as a name candidate until `{` or `::` or
|
||||
// `(`. If the name is empty, use the candicate.
|
||||
std::string FirstNSName;
|
||||
// For `namespace [[foo]] A::B::inline C {` or
|
||||
// `namespace MACRO1 MACRO2 A::B::inline C {`, returns "A::B::inline C".
|
||||
// Peek for the first '::' (or '{') and then return all tokens from one
|
||||
// token before that up until the '{'.
|
||||
// Peek for the first '::' (or '{' or '(')) and then return all tokens from
|
||||
// one token before that up until the '{'. A '(' might be a macro with
|
||||
// arguments.
|
||||
const FormatToken *FirstNSTok = Tok;
|
||||
while (Tok && !Tok->is(tok::l_brace) && !Tok->is(tok::coloncolon)) {
|
||||
while (Tok && !Tok->isOneOf(tok::l_brace, tok::coloncolon, tok::l_paren)) {
|
||||
FirstNSName += FirstNSTok->TokenText;
|
||||
FirstNSTok = Tok;
|
||||
Tok = Tok->getNextNonComment();
|
||||
}
|
||||
|
@ -57,6 +77,8 @@ std::string computeName(const FormatToken *NamespaceTok) {
|
|||
name += " ";
|
||||
Tok = Tok->getNextNonComment();
|
||||
}
|
||||
if (name.empty())
|
||||
name = FirstNSName;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
|
|
@ -2597,10 +2597,12 @@ void UnwrappedLineParser::parseNamespace() {
|
|||
parseParens();
|
||||
} else {
|
||||
while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw_inline,
|
||||
tok::l_square, tok::period) ||
|
||||
tok::l_square, tok::period, tok::l_paren) ||
|
||||
(Style.isCSharp() && FormatTok->is(tok::kw_union)))
|
||||
if (FormatTok->is(tok::l_square))
|
||||
parseSquare();
|
||||
else if (FormatTok->is(tok::l_paren))
|
||||
parseParens();
|
||||
else
|
||||
nextToken();
|
||||
}
|
||||
|
|
|
@ -3738,6 +3738,36 @@ TEST_F(FormatTest, FormatsNamespaces) {
|
|||
"void f() { f(); }\n"
|
||||
"}",
|
||||
LLVMWithNoNamespaceFix);
|
||||
verifyFormat("#define M(x) x##x\n"
|
||||
"namespace M(x) {\n"
|
||||
"class A {};\n"
|
||||
"void f() { f(); }\n"
|
||||
"}",
|
||||
LLVMWithNoNamespaceFix);
|
||||
verifyFormat("#define M(x) x##x\n"
|
||||
"namespace N::inline M(x) {\n"
|
||||
"class A {};\n"
|
||||
"void f() { f(); }\n"
|
||||
"}",
|
||||
LLVMWithNoNamespaceFix);
|
||||
verifyFormat("#define M(x) x##x\n"
|
||||
"namespace M(x)::inline N {\n"
|
||||
"class A {};\n"
|
||||
"void f() { f(); }\n"
|
||||
"}",
|
||||
LLVMWithNoNamespaceFix);
|
||||
verifyFormat("#define M(x) x##x\n"
|
||||
"namespace N::M(x) {\n"
|
||||
"class A {};\n"
|
||||
"void f() { f(); }\n"
|
||||
"}",
|
||||
LLVMWithNoNamespaceFix);
|
||||
verifyFormat("#define M(x) x##x\n"
|
||||
"namespace M::N(x) {\n"
|
||||
"class A {};\n"
|
||||
"void f() { f(); }\n"
|
||||
"}",
|
||||
LLVMWithNoNamespaceFix);
|
||||
verifyFormat("namespace N::inline D {\n"
|
||||
"class A {};\n"
|
||||
"void f() { f(); }\n"
|
||||
|
|
|
@ -68,6 +68,127 @@ TEST_F(NamespaceEndCommentsFixerTest, AddsEndComment) {
|
|||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace M(x)",
|
||||
fixNamespaceEndComments("#define M(x) x##x\n"
|
||||
"namespace M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace A::M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace A::M(x)",
|
||||
fixNamespaceEndComments("#define M(x) x##x\n"
|
||||
"namespace A::M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace M(x)::A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace M(x)::A",
|
||||
fixNamespaceEndComments("#define M(x) x##x\n"
|
||||
"namespace M(x)::A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace A::inline M(x)::B {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace A::inline M(x)::B",
|
||||
fixNamespaceEndComments("#define M(x) x##x\n"
|
||||
"namespace A::inline M(x)::B {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace [[deprecated(\"foo\")]] A::inline M(x)::A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace A::inline M(x)::A",
|
||||
fixNamespaceEndComments(
|
||||
"#define M(x) x##x\n"
|
||||
"namespace [[deprecated(\"foo\")]] A::inline M(x)::A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ(
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment */ A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace A",
|
||||
fixNamespaceEndComments(
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment */ A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("namespace /* comment */ [[deprecated(\"foo\")]] A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace A",
|
||||
fixNamespaceEndComments(
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ(
|
||||
"#define M(x) x##x\n"
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment */ M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace M(x)",
|
||||
fixNamespaceEndComments("#define M(x) x##x\n"
|
||||
"namespace /* comment */ "
|
||||
"[[deprecated(\"foo\")]] /* comment */ M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment */ "
|
||||
"A::M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace A::M(x)",
|
||||
fixNamespaceEndComments(
|
||||
"#define M(x) x##x\n"
|
||||
"namespace /* comment */ "
|
||||
"[[deprecated(\"foo\")]] /* comment */ A::M(x) {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment */ "
|
||||
"M(x) /* comment */ {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace M(x)",
|
||||
fixNamespaceEndComments(
|
||||
"#define M(x) x##x\n"
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment "
|
||||
"*/ M(x) /* comment */ {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("#define M(x) x##x\n"
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment */ "
|
||||
"A::M(x) /* comment */ {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}// namespace A::M(x)",
|
||||
fixNamespaceEndComments(
|
||||
"#define M(x) x##x\n"
|
||||
"namespace /* comment */ [[deprecated(\"foo\")]] /* comment "
|
||||
"*/ A::M(x) /* comment */ {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
"}"));
|
||||
EXPECT_EQ("inline namespace A {\n"
|
||||
"int i;\n"
|
||||
"int j;\n"
|
||||
|
|
Loading…
Reference in a new issue