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.

llvm-svn: 187033
This commit is contained in:
Daniel Jasper 2013-07-24 13:10:59 +00:00
parent c467c94e0b
commit ffefb3d1e0
3 changed files with 114 additions and 0 deletions

View File

@ -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

View File

@ -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.

View File

@ -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