From e05dc6d1b5eb12d47c8d3cb5120452ceef720568 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Wed, 24 Jul 2013 13:10:59 +0000 Subject: [PATCH] clang-format: Initial (incomplete) support for the WebKit coding style. This is far from implementing all the rules given by http://www.webkit.org/coding/coding-style.html The important new feature is the support for styles that don't have a column limit. For such styles, clang-format will (at the moment) simply respect the input's formatting decisions within statements. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@187033 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Format/Format.h | 8 ++++ lib/Format/Format.cpp | 28 ++++++++++++ unittests/Format/FormatTest.cpp | 78 +++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+) diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index a6998bc7ff..e5a35fbe21 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -31,6 +31,10 @@ namespace format { /// specific guidelines. struct FormatStyle { /// \brief The column limit. + /// + /// A column limit of \c 0 means that there is no column limit. In this case, + /// clang-format will respect the input's line breaking decisions within + /// statements. unsigned ColumnLimit; /// \brief The maximum number of consecutive empty lines to keep. @@ -218,6 +222,10 @@ FormatStyle getChromiumStyle(); /// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style. FormatStyle getMozillaStyle(); +/// \brief Returns a format style complying with Webkit's style guide: +/// http://www.webkit.org/coding/coding-style.html +FormatStyle getWebKitStyle(); + /// \brief Gets a predefined style by name. /// /// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index a4495ba62e..2dee5678b7 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -219,6 +219,15 @@ FormatStyle getMozillaStyle() { return MozillaStyle; } +FormatStyle getWebKitStyle() { + FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 0; + Style.IndentWidth = 4; + Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup; + Style.PointerBindsToType = true; + return Style; +} + bool getPredefinedStyle(StringRef Name, FormatStyle *Style) { if (Name.equals_lower("llvm")) *Style = getLLVMStyle(); @@ -228,6 +237,8 @@ bool getPredefinedStyle(StringRef Name, FormatStyle *Style) { *Style = getMozillaStyle(); else if (Name.equals_lower("google")) *Style = getGoogleStyle(); + else if (Name.equals_lower("webkit")) + *Style = getWebKitStyle(); else return false; @@ -299,6 +310,11 @@ public: // The first token has already been indented and thus consumed. moveStateToNextToken(State, /*DryRun=*/false, /*Newline=*/false); + if (Style.ColumnLimit == 0) { + formatWithoutColumnLimit(State); + return; + } + // If everything fits on a single line, just put it there. unsigned ColumnLimit = Style.ColumnLimit; if (NextLine && NextLine->InPPDirective && @@ -506,6 +522,15 @@ private: } }; + /// \brief Formats the line starting at \p State, simply keeping all of the + /// input's line breaking decisions. + void formatWithoutColumnLimit(LineState &State) { + while (State.NextToken != NULL) { + bool Newline = State.NextToken->NewlinesBefore > 0; + addTokenToState(Newline, /*DryRun=*/false, State); + } + } + /// \brief Appends the next token to \p State and updates information /// necessary for indentation. /// @@ -1592,6 +1617,9 @@ private: if (I->Last->Type == TT_LineComment) return; + if (Indent > Style.ColumnLimit) + return; + unsigned Limit = Style.ColumnLimit - Indent; // If we already exceed the column limit, we set 'Limit' to 0. The different // tryMerge..() functions can then decide whether to still do merging. diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index ecdb7216ba..9f41491924 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -5361,6 +5361,11 @@ TEST_F(FormatTest, GetsPredefinedStyleByName) { EXPECT_TRUE(getPredefinedStyle("moZILla", &Styles[2])); EXPECT_TRUE(allStylesEqual(Styles)); + Styles[0] = getWebKitStyle(); + EXPECT_TRUE(getPredefinedStyle("WebKit", &Styles[1])); + EXPECT_TRUE(getPredefinedStyle("wEbKit", &Styles[2])); + EXPECT_TRUE(allStylesEqual(Styles)); + EXPECT_FALSE(getPredefinedStyle("qwerty", &Styles[0])); } @@ -5515,6 +5520,79 @@ TEST_F(FormatTest, SplitsUTF8BlockComments) { format("/* 𝓣𝓮𝓼𝓽 𝔣𝔬𝔲𝔯 𝕓𝕪𝕥𝕖 𝖀𝕿𝕱-𝟠 */", getLLVMStyleWithColumns(12))); } +TEST_F(FormatTest, FormatsWithWebKitStyle) { + FormatStyle Style = getWebKitStyle(); + + // Don't indent in outer namespaces. + verifyFormat("namespace outer {\n" + "int i;\n" + "namespace inner {\n" + "int i;\n" // FIXME: This should be indented. + "} // namespace inner\n" + "} // namespace outer\n" + "namespace other_outer {\n" + "int i;\n" + "}", + Style); + + // Don't indent case labels. + verifyFormat("switch (variable) {\n" + "case 1:\n" + "case 2:\n" + " doSomething();\n" + " break;\n" + "default:\n" + " ++variable;\n" + "}", + Style); + + // Wrap before binary operators. + EXPECT_EQ( + "void f()\n" + "{\n" + " if (aaaaaaaaaaaaaaaa\n" + " && bbbbbbbbbbbbbbbbbbbbbbbb\n" + " && (cccccccccccccccccccccccccc || dddddddddddddddddddd))\n" + " return;\n" + "}", + format( + "void f() {\n" + "if (aaaaaaaaaaaaaaaa\n" + "&& bbbbbbbbbbbbbbbbbbbbbbbb\n" + "&& (cccccccccccccccccccccccccc || dddddddddddddddddddd))\n" + "return;\n" + "}", + Style)); + + // Constructor initializers are formatted one per line with the "," on the + // new line. + // FIXME: This needs to be implemented. + // verifyFormat("Constructor()\n" + // " : aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + // " , aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + // " aaaaaaaaaaaaaaaaaaaaaaaaaaa)\n" + // " , aaaaaaaaaaaaaaaaaaaaaaa() {}", + // Style); + + // Do not align comments. + // FIXME: Implement option to suppress comment alignment. + // verifyFormat("int a; // Do not\n" + // "double b; // align comments."); + + // Accept input's line breaks. + EXPECT_EQ("if (aaaaaaaaaaaaaaa\n" + " || bbbbbbbbbbbbbbb) {\n" + " i++;\n" + "}", + format("if (aaaaaaaaaaaaaaa\n" + "|| bbbbbbbbbbbbbbb) { i++; }", + Style)); + EXPECT_EQ("if (aaaaaaaaaaaaaaa || bbbbbbbbbbbbbbb) {\n" + " i++;\n" + "}", + format("if (aaaaaaaaaaaaaaa || bbbbbbbbbbbbbbb) { i++; }", Style)); +} + #endif } // end namespace tooling -- 2.40.0