Index: cfe/trunk/lib/Format/Format.cpp =================================================================== --- cfe/trunk/lib/Format/Format.cpp +++ cfe/trunk/lib/Format/Format.cpp @@ -1309,8 +1309,7 @@ std::set 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); } } @@ -1347,9 +1346,7 @@ 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; Index: cfe/trunk/lib/Format/FormatToken.h =================================================================== --- cfe/trunk/lib/Format/FormatToken.h +++ cfe/trunk/lib/Format/FormatToken.h @@ -520,8 +520,8 @@ 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; Index: cfe/trunk/lib/Format/NamespaceEndCommentsFixer.cpp =================================================================== --- cfe/trunk/lib/Format/NamespaceEndCommentsFixer.cpp +++ cfe/trunk/lib/Format/NamespaceEndCommentsFixer.cpp @@ -125,12 +125,7 @@ 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, Index: cfe/trunk/lib/Format/TokenAnnotator.h =================================================================== --- cfe/trunk/lib/Format/TokenAnnotator.h +++ cfe/trunk/lib/Format/TokenAnnotator.h @@ -105,6 +105,13 @@ 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; Index: cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp +++ cfe/trunk/lib/Format/UnwrappedLineFormatter.cpp @@ -535,7 +535,7 @@ 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; @@ -1160,7 +1160,7 @@ // 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; Index: cfe/trunk/lib/Format/UnwrappedLineParser.cpp =================================================================== --- cfe/trunk/lib/Format/UnwrappedLineParser.cpp +++ cfe/trunk/lib/Format/UnwrappedLineParser.cpp @@ -992,13 +992,6 @@ 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: @@ -1066,6 +1059,16 @@ 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)) { Index: cfe/trunk/unittests/Format/FormatTest.cpp =================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp +++ cfe/trunk/unittests/Format/FormatTest.cpp @@ -200,6 +200,42 @@ "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" @@ -1220,12 +1256,25 @@ "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" @@ -1597,16 +1646,36 @@ "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(); }", @@ -7602,6 +7671,12 @@ 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"