r212591 - clang-format: Revamp function declaration/definition indentation.
Daniel Jasper
djasper at google.com
Wed Jul 9 00:50:34 PDT 2014
Author: djasper
Date: Wed Jul 9 02:50:33 2014
New Revision: 212591
URL: http://llvm.org/viewvc/llvm-project?rev=212591&view=rev
Log:
clang-format: Revamp function declaration/definition indentation.
Key changes:
- Correctly (well ...) distinguish function declarations and variable
declarations with ()-initialization.
- Don't indent when breaking function declarations/definitions after the
return type.
- Indent variable declarations and typedefs when breaking after the
type.
This fixes llvm.org/PR17999.
Modified:
cfe/trunk/include/clang/Format/Format.h
cfe/trunk/lib/Format/ContinuationIndenter.cpp
cfe/trunk/lib/Format/Format.cpp
cfe/trunk/lib/Format/FormatToken.h
cfe/trunk/lib/Format/TokenAnnotator.cpp
cfe/trunk/lib/Format/TokenAnnotator.h
cfe/trunk/unittests/Format/FormatTest.cpp
Modified: cfe/trunk/include/clang/Format/Format.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=212591&r1=212590&r2=212591&view=diff
==============================================================================
--- cfe/trunk/include/clang/Format/Format.h (original)
+++ cfe/trunk/include/clang/Format/Format.h Wed Jul 9 02:50:33 2014
@@ -293,10 +293,6 @@ struct FormatStyle {
/// a zero-length name is assumed.
bool Cpp11BracedListStyle;
- /// \brief If \c true, indent when breaking function declarations which
- /// are not also definitions after the type.
- bool IndentFunctionDeclarationAfterType;
-
/// \brief If \c true, spaces will be inserted after '(' and before ')'.
bool SpacesInParentheses;
@@ -387,8 +383,6 @@ struct FormatStyle {
ExperimentalAutoDetectBinPacking ==
R.ExperimentalAutoDetectBinPacking &&
IndentCaseLabels == R.IndentCaseLabels &&
- IndentFunctionDeclarationAfterType ==
- R.IndentFunctionDeclarationAfterType &&
IndentWidth == R.IndentWidth && Language == R.Language &&
MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep &&
KeepEmptyLinesAtTheStartOfBlocks ==
Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=212591&r1=212590&r2=212591&view=diff
==============================================================================
--- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original)
+++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Wed Jul 9 02:50:33 2014
@@ -203,10 +203,12 @@ bool ContinuationIndenter::mustBreak(con
!Current.isTrailingComment())
return true;
- if ((Current.Type == TT_StartOfName || Current.is(tok::kw_operator)) &&
- State.Line->MightBeFunctionDecl &&
- State.Stack.back().BreakBeforeParameter && Current.NestingLevel == 0)
+ // If the return type spans multiple lines, wrap before the function name.
+ if ((Current.Type == TT_FunctionDeclarationName ||
+ Current.is(tok::kw_operator)) &&
+ State.Stack.back().BreakBeforeParameter)
return true;
+
if (startsSegmentOfBuilderTypeCall(Current) &&
(State.Stack.back().CallContinuation != 0 ||
(State.Stack.back().BreakBeforeParameter &&
@@ -518,11 +520,8 @@ unsigned ContinuationIndenter::getNewLin
return State.Stack.back().VariablePos;
if ((PreviousNonComment && (PreviousNonComment->ClosesTemplateDeclaration ||
PreviousNonComment->Type == TT_AttributeParen)) ||
- ((NextNonComment->Type == TT_StartOfName ||
- NextNonComment->is(tok::kw_operator)) &&
- Current.NestingLevel == 0 &&
- (!Style.IndentFunctionDeclarationAfterType ||
- State.Line->StartsDefinition)))
+ NextNonComment->is(tok::kw_operator) ||
+ NextNonComment->Type == TT_FunctionDeclarationName)
return std::max(State.Stack.back().LastSpace, State.Stack.back().Indent);
if (NextNonComment->Type == TT_SelectorName) {
if (!State.Stack.back().ObjCSelectorNameFound) {
Modified: cfe/trunk/lib/Format/Format.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=212591&r1=212590&r2=212591&view=diff
==============================================================================
--- cfe/trunk/lib/Format/Format.cpp (original)
+++ cfe/trunk/lib/Format/Format.cpp Wed Jul 9 02:50:33 2014
@@ -216,8 +216,6 @@ template <> struct MappingTraits<FormatS
IO.mapOptional("TabWidth", Style.TabWidth);
IO.mapOptional("UseTab", Style.UseTab);
IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
- IO.mapOptional("IndentFunctionDeclarationAfterType",
- Style.IndentFunctionDeclarationAfterType);
IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
@@ -328,7 +326,6 @@ FormatStyle getLLVMStyle() {
LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
LLVMStyle.IndentCaseLabels = false;
- LLVMStyle.IndentFunctionDeclarationAfterType = false;
LLVMStyle.IndentWidth = 2;
LLVMStyle.TabWidth = 8;
LLVMStyle.MaxEmptyLinesToKeep = 1;
@@ -373,7 +370,6 @@ FormatStyle getGoogleStyle(FormatStyle::
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
GoogleStyle.DerivePointerAlignment = true;
GoogleStyle.IndentCaseLabels = true;
- GoogleStyle.IndentFunctionDeclarationAfterType = true;
GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
GoogleStyle.ObjCSpaceAfterProperty = false;
GoogleStyle.ObjCSpaceBeforeProtocolList = false;
Modified: cfe/trunk/lib/Format/FormatToken.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=212591&r1=212590&r2=212591&view=diff
==============================================================================
--- cfe/trunk/lib/Format/FormatToken.h (original)
+++ cfe/trunk/lib/Format/FormatToken.h Wed Jul 9 02:50:33 2014
@@ -40,6 +40,7 @@ enum TokenType {
TT_CtorInitializerComma,
TT_DesignatedInitializerPeriod,
TT_DictLiteral,
+ TT_FunctionDeclarationName,
TT_FunctionLBrace,
TT_FunctionTypeLParen,
TT_ImplicitStringLiteral,
Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=212591&r1=212590&r2=212591&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.cpp (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed Jul 9 02:50:33 2014
@@ -325,8 +325,6 @@ private:
return false;
}
}
- // No closing "}" found, this probably starts a definition.
- Line.StartsDefinition = true;
return true;
}
@@ -1201,6 +1199,43 @@ void TokenAnnotator::annotate(AnnotatedL
Line.First->CanBreakBefore = Line.First->MustBreakBefore;
}
+// This function heuristically determines whether 'Current' starts the name of a
+// function declaration.
+static bool isFunctionDeclarationName(const FormatToken &Current) {
+ if (Current.Type != TT_StartOfName ||
+ Current.NestingLevel != 0 ||
+ Current.Previous->Type == TT_StartOfName)
+ return false;
+ const FormatToken *Next = Current.Next;
+ for (; Next; Next = Next->Next) {
+ if (Next->Type == TT_TemplateOpener) {
+ Next = Next->MatchingParen;
+ } else if (Next->is(tok::coloncolon)) {
+ Next = Next->Next;
+ if (!Next || !Next->is(tok::identifier))
+ return false;
+ } else if (Next->is(tok::l_paren)) {
+ break;
+ } else {
+ return false;
+ }
+ }
+ if (!Next)
+ return false;
+ assert(Next->is(tok::l_paren));
+ if (Next->Next == Next->MatchingParen)
+ return true;
+ for (const FormatToken *Tok = Next->Next; Tok != Next->MatchingParen;
+ Tok = Tok->Next) {
+ if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() ||
+ Tok->Type == TT_PointerOrReference || Tok->Type == TT_StartOfName)
+ return true;
+ if (Tok->isOneOf(tok::l_brace, tok::string_literal) || Tok->Tok.isLiteral())
+ return false;
+ }
+ return false;
+}
+
void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) {
for (SmallVectorImpl<AnnotatedLine *>::iterator I = Line.Children.begin(),
E = Line.Children.end();
@@ -1215,6 +1250,8 @@ void TokenAnnotator::calculateFormatting
FormatToken *Current = Line.First->Next;
bool InFunctionDecl = Line.MightBeFunctionDecl;
while (Current) {
+ if (isFunctionDeclarationName(*Current))
+ Current->Type = TT_FunctionDeclarationName;
if (Current->Type == TT_LineComment) {
if (Current->Previous->BlockKind == BK_BracedInit &&
Current->Previous->opensScope())
@@ -1320,7 +1357,8 @@ unsigned TokenAnnotator::splitPenalty(co
if (Right.Type != TT_ObjCMethodExpr && Right.Type != TT_LambdaLSquare)
return 500;
}
- if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator)) {
+ if (Right.Type == TT_StartOfName ||
+ Right.Type == TT_FunctionDeclarationName || Right.is(tok::kw_operator)) {
if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
return 3;
if (Left.Type == TT_StartOfName)
@@ -1674,7 +1712,8 @@ bool TokenAnnotator::canBreakBefore(cons
return false;
if (Left.Tok.getObjCKeywordID() == tok::objc_interface)
return false;
- if (Right.Type == TT_StartOfName || Right.is(tok::kw_operator))
+ if (Right.Type == TT_StartOfName ||
+ Right.Type == TT_FunctionDeclarationName || Right.is(tok::kw_operator))
return true;
if (Right.isTrailingComment())
// We rely on MustBreakBefore being set correctly here as we should not
Modified: cfe/trunk/lib/Format/TokenAnnotator.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.h?rev=212591&r1=212590&r2=212591&view=diff
==============================================================================
--- cfe/trunk/lib/Format/TokenAnnotator.h (original)
+++ cfe/trunk/lib/Format/TokenAnnotator.h Wed Jul 9 02:50:33 2014
@@ -41,8 +41,8 @@ public:
: First(Line.Tokens.front().Tok), Level(Line.Level),
InPPDirective(Line.InPPDirective),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
- StartsDefinition(false), Affected(false),
- LeadingEmptyLinesAffected(false), ChildrenAffected(false) {
+ Affected(false), LeadingEmptyLinesAffected(false),
+ ChildrenAffected(false) {
assert(!Line.Tokens.empty());
// Calculate Next and Previous for all tokens. Note that we must overwrite
@@ -86,7 +86,6 @@ public:
bool InPPDirective;
bool MustBeDeclaration;
bool MightBeFunctionDecl;
- bool StartsDefinition;
/// \c True if this line should be formatted, i.e. intersects directly or
/// indirectly with one of the input ranges.
Modified: cfe/trunk/unittests/Format/FormatTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=212591&r1=212590&r2=212591&view=diff
==============================================================================
--- cfe/trunk/unittests/Format/FormatTest.cpp (original)
+++ cfe/trunk/unittests/Format/FormatTest.cpp Wed Jul 9 02:50:33 2014
@@ -1264,13 +1264,13 @@ TEST_F(FormatTest, DontSplitLineComments
getLLVMStyleWithColumns(50)));
// FIXME: One day we might want to implement adjustment of leading whitespace
// of the consecutive lines in this kind of comment:
- EXPECT_EQ("int\n"
- "a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
- " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
- " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
- format("int a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
- " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
- " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ EXPECT_EQ("double\n"
+ " a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
+ " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
+ " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
+ format("double a; // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
+ " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\\\n"
+ " // AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
getLLVMStyleWithColumns(49)));
}
@@ -2687,7 +2687,7 @@ TEST_F(FormatTest, LayoutStatementsAroun
EXPECT_EQ("int\n"
"#define A\n"
" a;",
- format("int\n#define A\na;", getGoogleStyle()));
+ format("int\n#define A\na;"));
verifyFormat("functionCallTo(\n"
" someOtherFunction(\n"
" withSomeParameters, whichInSequence,\n"
@@ -3359,7 +3359,7 @@ TEST_F(FormatTest, BreaksFunctionDeclara
// 2) break after return type.
verifyFormat(
"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " bbbbbbbbbbbbbb(Cccccccccccccc cccccccccccccccccccccccccc);",
+ "bbbbbbbbbbbbbb(Cccccccccccccc cccccccccccccccccccccccccc);",
getGoogleStyle());
// 3) break after (.
@@ -3371,8 +3371,8 @@ TEST_F(FormatTest, BreaksFunctionDeclara
// 4) break before after nested name specifiers.
verifyFormat(
"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " SomeClasssssssssssssssssssssssssssssssssssssss::\n"
- " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(Cccccccccccccc cccccccccc);",
+ "SomeClasssssssssssssssssssssssssssssssssssssss::\n"
+ " bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(Cccccccccccccc cccccccccc);",
getGoogleStyle());
// However, there are exceptions, if a sufficient amount of lines can be
@@ -3386,9 +3386,9 @@ TEST_F(FormatTest, BreaksFunctionDeclara
" Cccccccccccccc cccccccccc);");
verifyFormat(
"Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n"
- " bbbbbbbbbbb(Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
- " Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
- " Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc);",
+ "bbbbbbbbbbb(Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
+ " Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc,\n"
+ " Cccccccccccccc cccccccccc, Cccccccccccccc cccccccccc);",
getGoogleStyle());
verifyFormat(
"Aaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb(Cccccccccccccc cccccccccc,\n"
@@ -5054,22 +5054,28 @@ TEST_F(FormatTest, FormatsFunctionTypes)
verifyFormat("void f() { function(*some_pointer_var)[0] = 10; }");
}
+TEST_F(FormatTest, BreaksLongVariableDeclarations) {
+ verifyFormat("LoooooooooooooooooooooooooooooooooooooooongType\n"
+ " LoooooooooooooooooooooooooooooooooooooooongVariable;");
+ verifyFormat("LoooooooooooooooooooooooooooooooooooooooongType const\n"
+ " LoooooooooooooooooooooooooooooooooooooooongVariable;");
+
+ // Different ways of ()-initializiation.
+ verifyFormat("LoooooooooooooooooooooooooooooooooooooooongType\n"
+ " LoooooooooooooooooooooooooooooooooooooooongVariable(1);");
+ verifyFormat("LoooooooooooooooooooooooooooooooooooooooongType\n"
+ " LoooooooooooooooooooooooooooooooooooooooongVariable(a);");
+ verifyFormat("LoooooooooooooooooooooooooooooooooooooooongType\n"
+ " LoooooooooooooooooooooooooooooooooooooooongVariable({});");
+}
+
TEST_F(FormatTest, BreaksLongDeclarations) {
verifyFormat("typedef LoooooooooooooooooooooooooooooooooooooooongType\n"
- " AnotherNameForTheLongType;",
- getGoogleStyle());
+ " AnotherNameForTheLongType;");
verifyFormat("typedef LongTemplateType<aaaaaaaaaaaaaaaaaaa()>\n"
- " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;",
- getGoogleStyle());
- verifyFormat("LoooooooooooooooooooooooooooooooooooooooongType\n"
- " LoooooooooooooooooooooooooooooooooooooooongVariable;",
- getGoogleStyle());
- verifyFormat("LoooooooooooooooooooooooooooooooooooooooongType const\n"
- " LoooooooooooooooooooooooooooooooooooooooongVariable;",
- getGoogleStyle());
+ " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa;");
verifyFormat("LoooooooooooooooooooooooooooooooooooooooongReturnType\n"
- " LoooooooooooooooooooooooooooooooongFunctionDeclaration();",
- getGoogleStyle());
+ "LoooooooooooooooooooooooooooooooongFunctionDeclaration();");
verifyFormat("LoooooooooooooooooooooooooooooooooooooooongReturnType\n"
"LooooooooooooooooooooooooooooooooooongFunctionDefinition() {}");
verifyFormat("LoooooooooooooooooooooooooooooooooooooooongReturnType const\n"
@@ -8101,7 +8107,6 @@ TEST_F(FormatTest, ParsesConfiguration)
CHECK_PARSE_BOOL(ObjCSpaceAfterProperty);
CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);
CHECK_PARSE_BOOL(Cpp11BracedListStyle);
- CHECK_PARSE_BOOL(IndentFunctionDeclarationAfterType);
CHECK_PARSE_BOOL(SpacesInParentheses);
CHECK_PARSE_BOOL(SpacesInAngles);
CHECK_PARSE_BOOL(SpaceInEmptyParentheses);
@@ -9044,7 +9049,7 @@ TEST_F(FormatTest, HandleConflictMarkers
"=======\n"
"Other \\\n"
">>>>>>>\n"
- "End int i;\n",
+ " End int i;\n",
format("#define Macro \\\n"
"<<<<<<<\n"
" Something \\\n"
More information about the cfe-commits
mailing list