cbeck88 removed rL LLVM as the repository for this revision. cbeck88 updated this revision to Diff 32249. cbeck88 added a comment.
- Fixed formatting in header - Fixed handling of nested namespaces - Added unit tests djasper: I thought about it, I guess I don't have a particularly good reason that the namespaces logic should be a separate function from "tryMergeSimpleBlock", and maybe it should indeed be refactored to be part of the case analysis of that function. When I began I thought this would just be simpler and make it easier to customize the namespace handling vs. other blocks, but now I'm less sure of this. At least with the way I'm now trying to handle the nested namespaces, this seems a bit simpler, but maybe that part should be changed. http://reviews.llvm.org/D11851 Files: include/clang/Format/Format.h lib/Format/Format.cpp lib/Format/UnwrappedLineFormatter.cpp unittests/Format/FormatTest.cpp
Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -3226,16 +3226,19 @@ Style.MacroBlockEnd = "^[A-Z_]+_END$"; verifyFormat("FOO_BEGIN\n" " FOO_ENTRY\n" - "FOO_END", Style); + "FOO_END", + Style); verifyFormat("FOO_BEGIN\n" " NESTED_FOO_BEGIN\n" " NESTED_FOO_ENTRY\n" " NESTED_FOO_END\n" - "FOO_END", Style); + "FOO_END", + Style); verifyFormat("FOO_BEGIN(Foo, Bar)\n" " int x;\n" " x = 1;\n" - "FOO_END(Baz)", Style); + "FOO_END(Baz)", + Style); } //===----------------------------------------------------------------------===// @@ -7649,14 +7652,13 @@ // Verify that splitting the strings understands // Style::AlwaysBreakBeforeMultilineStrings. - EXPECT_EQ( - "aaaaaaaaaaaa(\n" - " \"aaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaa \"\n" - " \"aaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaa\");", - format("aaaaaaaaaaaa(\"aaaaaaaaaaaaaaaaaaaaaaaaaa " - "aaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaa " - "aaaaaaaaaaaaaaaaaaaaaa\");", - getGoogleStyle())); + EXPECT_EQ("aaaaaaaaaaaa(\n" + " \"aaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaa \"\n" + " \"aaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaa\");", + format("aaaaaaaaaaaa(\"aaaaaaaaaaaaaaaaaaaaaaaaaa " + "aaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaa " + "aaaaaaaaaaaaaaaaaaaaaa\");", + getGoogleStyle())); EXPECT_EQ("return \"aaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaa \"\n" " \"aaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaa\";", format("return \"aaaaaaaaaaaaaaaaaaaaaa " @@ -10433,6 +10435,45 @@ verifyNoCrash("#define a\\\n /**/}"); } +TEST_F(FormatTest, ShortNamespacesOption) { + FormatStyle style = getLLVMStyle(); + style.AllowShortNamespacesOnASingleLine = true; + + verifyFormat("namespace foo { class bar; }", style); + verifyFormat("namespace foo {\n" + "class bar;\n" + "class baz;\n" + "}", + style); + verifyFormat("namespace foo { namespace bar { class baz; } }", style); + verifyFormat("namespace foo {\n" + "namespace bar { class baz; }\n" + "namespace quar { class quaz; }\n" + "}", + style); + verifyFormat("namespace foo {\n" + "int f() { return 5; }\n" + "}", + style); + verifyFormat("namespace foo { template <T> struct bar; }", style); + verifyFormat("namespace foo { constexpr int num = 42; }", style); + + // test column limit + verifyFormat("namespace boost {\n" + "namespace spirit {\n" + "namespace qi {\n" + "namespace unicode { namespace foo { class bar; } }\n" + "}\n" + "}\n" + "}", + style); + + style.ColumnLimit = 0; + verifyFormat("namespace boost { namespace spirit { namespace qi { namespace " + "unicode { namespace foo { class bar; } } } } }", + style); +} + } // end namespace } // end namespace format } // end namespace clang Index: lib/Format/UnwrappedLineFormatter.cpp =================================================================== --- lib/Format/UnwrappedLineFormatter.cpp +++ lib/Format/UnwrappedLineFormatter.cpp @@ -199,6 +199,11 @@ return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0; } if (TheLine->Last->is(tok::l_brace)) { + if (Style.AllowShortNamespacesOnASingleLine && + TheLine->First->is(tok::kw_namespace)) { + if (unsigned result = tryMergeNamespace(I, E, Limit)) + return result; + } return Style.BreakBeforeBraces == FormatStyle::BS_Attach ? tryMergeSimpleBlock(I, E, Limit) : 0; @@ -258,6 +263,65 @@ return 1; } + unsigned tryMergeNamespace(SmallVectorImpl<AnnotatedLine *>::const_iterator I, + SmallVectorImpl<AnnotatedLine *>::const_iterator E, + unsigned Limit) { + if (Limit == 0) + return 0; + if (I[1]->InPPDirective != (*I)->InPPDirective || + (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline)) + return 0; + + Limit = limitConsideringMacros(I + 1, E, Limit); + + if (1 + I[1]->Last->TotalLength > Limit) + return 0; + + // An assumption of the function is that the first line begins with + // keyword namespace (i.e. I[0]->First->is(tok::kw_namespace)) + // Check also that the second token after 'namespace' exists and is an + // l_brace which we aren't requried to break before + if (!I[0]->First->Next || !I[0]->First->Next->Next) + return 0; + FormatToken *Tok = I[0]->First->Next->Next; + if (!Tok->is(tok::l_brace) || Tok->MustBreakBefore) + return 0; + + // Check if it's a namespace inside a namespace, and call recursively if so + // 10 + 2 + 2 is the sizes of the strings "namespace " " {" and " }" + if (I[1]->First->is(tok::kw_namespace)) { + unsigned inner_limit = + Limit - 10 - 2 - 2 - + (I[0]->First->Next ? I[0]->First->Next->TotalLength : 0); + unsigned inner_result = tryMergeNamespace(I + 1, E, inner_limit); + if (!inner_result) + return 0; + // check if there is even a line after the inner result + if (I + 2 + inner_result >= E) + return 0; + // check that the line after the inner result starts with a closing brace + // which we are permitted to merge into one line + if (I[2 + inner_result]->First->is(tok::r_brace) && + !I[2 + inner_result]->First->MustBreakBefore) + return 2 + inner_result; + return 0; + } + + // There's no inner namespace, so we are considering to merge at most one + // line. + + // The line which is in the namespace should end with semicolon + if (I[1]->Last->isNot(tok::semi)) + return 0; + + // Last, check that the third line starts with a closing brace. + if (I[2]->First->isNot(tok::r_brace) || I[2]->First->MustBreakBefore) + return 0; + + // If so, merge all three lines. + return 2; + } + unsigned tryMergeSimpleControlStatement( SmallVectorImpl<AnnotatedLine *>::const_iterator I, SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) { Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -212,6 +212,8 @@ Style.AllowShortIfStatementsOnASingleLine); IO.mapOptional("AllowShortLoopsOnASingleLine", Style.AllowShortLoopsOnASingleLine); + IO.mapOptional("AllowShortNamespacesOnASingleLine", + Style.AllowShortNamespacesOnASingleLine); IO.mapOptional("AlwaysBreakAfterDefinitionReturnType", Style.AlwaysBreakAfterDefinitionReturnType); IO.mapOptional("AlwaysBreakBeforeMultilineStrings", @@ -354,6 +356,7 @@ LLVMStyle.AllowShortCaseLabelsOnASingleLine = false; LLVMStyle.AllowShortIfStatementsOnASingleLine = false; LLVMStyle.AllowShortLoopsOnASingleLine = false; + LLVMStyle.AllowShortNamespacesOnASingleLine = false; LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None; LLVMStyle.AlwaysBreakBeforeMultilineStrings = false; LLVMStyle.AlwaysBreakTemplateDeclarations = false; Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -112,6 +112,13 @@ /// single line. bool AllowShortLoopsOnASingleLine; + /// \brief If \c true, + /// \code + /// namespace a { class b; } + /// \endcode + /// can be put on a single line + bool AllowShortNamespacesOnASingleLine; + /// \brief Different ways to break after the function definition return type. enum DefinitionReturnTypeBreakingStyle { /// Break after return type automatically.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits