This fixes formatting namespaces with preceding 'inline' and 'export' (Modules TS) specifiers.
This change fixes namespaces not being identified as such with preceding 'inline' or 'export' specifiers.
Motivation: I was experimenting with the Modules TS (-fmodules-ts) and found it would be useful if clang-format would correctly format 'export namespace'. While making the changes, I noticed that similar issues still exist with 'inline namespace', and addressed them as well.
Patch by Marco Elver!
Reviewers: klimek, djasper, owenpan, sammccall
Reviewed By: owenpan, sammccall
Subscribers: owenpan, cfe-commits
Differential Revision: https://reviews.llvm.org/D51036
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341450
91177308-0d34-0410-b5e6-
96231b3b80d8
std::set<unsigned> DeletedLines;
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
auto &Line = *AnnotatedLines[i];
- if (Line.startsWith(tok::kw_namespace) ||
- Line.startsWith(tok::kw_inline, tok::kw_namespace)) {
+ if (Line.startsWithNamespace()) {
checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
}
}
if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
break;
- if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
- AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
- tok::kw_namespace)) {
+ if (AnnotatedLines[CurrentLine]->startsWithNamespace()) {
if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
DeletedLines))
return false;
const FormatToken *NamespaceTok = this;
if (is(tok::comment))
NamespaceTok = NamespaceTok->getNextNonComment();
- // Detect "(inline)? namespace" in the beginning of a line.
- if (NamespaceTok && NamespaceTok->is(tok::kw_inline))
+ // Detect "(inline|export)? namespace" in the beginning of a line.
+ if (NamespaceTok && NamespaceTok->isOneOf(tok::kw_inline, tok::kw_export))
NamespaceTok = NamespaceTok->getNextNonComment();
return NamespaceTok && NamespaceTok->is(tok::kw_namespace) ? NamespaceTok
: nullptr;
if (StartLineIndex > 0)
NamespaceTok = AnnotatedLines[StartLineIndex - 1]->First;
}
- // Detect "(inline)? namespace" in the beginning of a line.
- if (NamespaceTok->is(tok::kw_inline))
- NamespaceTok = NamespaceTok->getNextNonComment();
- if (!NamespaceTok || NamespaceTok->isNot(tok::kw_namespace))
- return nullptr;
- return NamespaceTok;
+ return NamespaceTok->getNamespaceToken();
}
NamespaceEndCommentsFixer::NamespaceEndCommentsFixer(const Environment &Env,
return !Last->isOneOf(tok::semi, tok::comment);
}
+ /// \c true if this line starts a namespace definition.
+ bool startsWithNamespace() const {
+ return startsWith(tok::kw_namespace) ||
+ startsWith(tok::kw_inline, tok::kw_namespace) ||
+ startsWith(tok::kw_export, tok::kw_namespace);
+ }
+
FormatToken *First;
FormatToken *Last;
Tok->SpacesRequiredBefore = 0;
Tok->CanBreakBefore = true;
return 1;
- } else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
+ } else if (Limit != 0 && !Line.startsWithNamespace() &&
!startsExternCBlock(Line)) {
// We don't merge short records.
FormatToken *RecordTok = Line.First;
// Remove empty lines after "{".
if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
PreviousLine->Last->is(tok::l_brace) &&
- PreviousLine->First->isNot(tok::kw_namespace) &&
+ !PreviousLine->startsWithNamespace() &&
!startsExternCBlock(*PreviousLine))
Newlines = 1;
case tok::kw_namespace:
parseNamespace();
return;
- case tok::kw_inline:
- nextToken();
- if (FormatTok->Tok.is(tok::kw_namespace)) {
- parseNamespace();
- return;
- }
- break;
case tok::kw_public:
case tok::kw_protected:
case tok::kw_private:
parseJavaScriptEs6ImportExport();
return;
}
+ if (!Style.isCpp())
+ break;
+ // Handle C++ "(inline|export) namespace".
+ LLVM_FALLTHROUGH;
+ case tok::kw_inline:
+ nextToken();
+ if (FormatTok->Tok.is(tok::kw_namespace)) {
+ parseNamespace();
+ return;
+ }
break;
case tok::identifier:
if (FormatTok->is(TT_ForEachMacro)) {
"int i;\n"
"}",
getGoogleStyle()));
+ EXPECT_EQ("/* something */ namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("/* something */ namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
+ EXPECT_EQ("inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
+ EXPECT_EQ("/* something */ inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("/* something */ inline namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
+ EXPECT_EQ("export namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ format("export namespace N {\n"
+ "\n"
+ "int i;\n"
+ "}",
+ getGoogleStyle()));
EXPECT_EQ("extern /**/ \"C\" /**/ {\n"
"\n"
"int i;\n"
"private:\n"
" void f() {}\n"
"};");
+ verifyFormat("export class A {\n"
+ "public:\n"
+ "public: // comment\n"
+ "protected:\n"
+ "private:\n"
+ " void f() {}\n"
+ "};");
verifyGoogleFormat("class A {\n"
" public:\n"
" protected:\n"
" private:\n"
" void f() {}\n"
"};");
+ verifyGoogleFormat("export class A {\n"
+ " public:\n"
+ " protected:\n"
+ " private:\n"
+ " void f() {}\n"
+ "};");
verifyFormat("class A {\n"
"public slots:\n"
" void f1() {}\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
+ verifyFormat("/* something */ namespace some_namespace {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
verifyFormat("namespace {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
+ verifyFormat("/* something */ namespace {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
verifyFormat("inline namespace X {\n"
"class A {};\n"
"void f() { f(); }\n"
"}",
LLVMWithNoNamespaceFix);
+ verifyFormat("/* something */ inline namespace X {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
+ verifyFormat("export namespace X {\n"
+ "class A {};\n"
+ "void f() { f(); }\n"
+ "}",
+ LLVMWithNoNamespaceFix);
verifyFormat("using namespace some_namespace;\n"
"class A {};\n"
"void f() { f(); }",
verifyFormat("inline namespace Foo\n"
"{};",
Style);
+ verifyFormat("/* something */ inline namespace Foo\n"
+ "{};",
+ Style);
+ verifyFormat("export namespace Foo\n"
+ "{};",
+ Style);
verifyFormat("namespace Foo\n"
"{\n"
"void Bar();\n"