summaryrefslogtreecommitdiffstats
path: root/lib/Format
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Format')
-rw-r--r--lib/Format/BreakableToken.cpp14
-rw-r--r--lib/Format/ContinuationIndenter.cpp40
-rw-r--r--lib/Format/ContinuationIndenter.h81
-rw-r--r--lib/Format/Format.cpp17
-rw-r--r--lib/Format/FormatToken.cpp7
-rw-r--r--lib/Format/FormatToken.h18
-rw-r--r--lib/Format/TokenAnnotator.cpp100
-rw-r--r--lib/Format/TokenAnnotator.h20
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp25
-rw-r--r--lib/Format/UnwrappedLineFormatter.h3
-rw-r--r--lib/Format/UnwrappedLineParser.cpp54
-rw-r--r--lib/Format/WhitespaceManager.h6
12 files changed, 220 insertions, 165 deletions
diff --git a/lib/Format/BreakableToken.cpp b/lib/Format/BreakableToken.cpp
index e3e162d..36a8c4d 100644
--- a/lib/Format/BreakableToken.cpp
+++ b/lib/Format/BreakableToken.cpp
@@ -183,7 +183,7 @@ void BreakableStringLiteral::insertBreak(unsigned LineIndex,
}
static StringRef getLineCommentIndentPrefix(StringRef Comment) {
- static const char *const KnownPrefixes[] = { "///", "//", "//!" };
+ static const char *const KnownPrefixes[] = {"///", "//", "//!"};
StringRef LongestPrefix;
for (StringRef KnownPrefix : KnownPrefixes) {
if (Comment.startswith(KnownPrefix)) {
@@ -239,9 +239,8 @@ void BreakableLineComment::replaceWhitespace(unsigned LineIndex,
/*Spaces=*/1);
}
-void
-BreakableLineComment::replaceWhitespaceBefore(unsigned LineIndex,
- WhitespaceManager &Whitespaces) {
+void BreakableLineComment::replaceWhitespaceBefore(
+ unsigned LineIndex, WhitespaceManager &Whitespaces) {
if (OriginalPrefix != Prefix) {
Whitespaces.replaceWhitespaceInToken(Tok, OriginalPrefix.size(), 0, "", "",
/*InPPDirective=*/false,
@@ -345,7 +344,7 @@ void BreakableBlockComment::adjustWhitespace(unsigned LineIndex,
// Calculate the start of the non-whitespace text in the current line.
size_t StartOfLine = Lines[LineIndex].find_first_not_of(Blanks);
if (StartOfLine == StringRef::npos)
- StartOfLine = Lines[LineIndex].size();
+ StartOfLine = Lines[LineIndex].rtrim("\r\n").size();
StringRef Whitespace = Lines[LineIndex].substr(0, StartOfLine);
// Adjust Lines to only contain relevant text.
@@ -415,9 +414,8 @@ void BreakableBlockComment::replaceWhitespace(unsigned LineIndex,
/*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1);
}
-void
-BreakableBlockComment::replaceWhitespaceBefore(unsigned LineIndex,
- WhitespaceManager &Whitespaces) {
+void BreakableBlockComment::replaceWhitespaceBefore(
+ unsigned LineIndex, WhitespaceManager &Whitespaces) {
if (LineIndex == 0)
return;
StringRef Prefix = Decoration;
diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp
index 91bc64b..2357abd 100644
--- a/lib/Format/ContinuationIndenter.cpp
+++ b/lib/Format/ContinuationIndenter.cpp
@@ -150,12 +150,6 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
State.Stack.back().BreakBeforeParameter && !Current.isTrailingComment() &&
!Current.isOneOf(tok::r_paren, tok::r_brace))
return true;
- if (Style.AlwaysBreakBeforeMultilineStrings &&
- State.Column > State.Stack.back().Indent && // Breaking saves columns.
- !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) &&
- !Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
- nextIsMultilineString(State))
- return true;
if (((Previous.is(TT_DictLiteral) && Previous.is(tok::l_brace)) ||
Previous.is(TT_ArrayInitializerLSquare)) &&
Style.ColumnLimit > 0 &&
@@ -170,9 +164,18 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
State.Stack.back().BreakBeforeParameter)
return true;
- if (State.Column < getNewLineColumn(State))
+ unsigned NewLineColumn = getNewLineColumn(State);
+ if (State.Column < NewLineColumn)
return false;
+ if (Style.AlwaysBreakBeforeMultilineStrings &&
+ (NewLineColumn == State.FirstIndent + Style.ContinuationIndentWidth ||
+ Previous.is(tok::comma) || Current.NestingLevel < 2) &&
+ !Previous.isOneOf(tok::kw_return, tok::lessless, tok::at) &&
+ !Previous.isOneOf(TT_InlineASMColon, TT_ConditionalExpr) &&
+ nextIsMultilineString(State))
+ return true;
+
// Using CanBreakBefore here and below takes care of the decision whether the
// current style uses wrapping before or after operators for the given
// operator.
@@ -416,7 +419,21 @@ unsigned ContinuationIndenter::addTokenOnNewLine(LineState &State,
Penalty += Style.PenaltyBreakFirstLessLess;
State.Column = getNewLineColumn(State);
- State.Stack.back().NestedBlockIndent = State.Column;
+
+ // Indent nested blocks relative to this column, unless in a very specific
+ // JavaScript special case where:
+ //
+ // var loooooong_name =
+ // function() {
+ // // code
+ // }
+ //
+ // is common and should be formatted like a free-standing function.
+ if (Style.Language != FormatStyle::LK_JavaScript ||
+ Current.NestingLevel != 0 || !PreviousNonComment->is(tok::equal) ||
+ !Current.is(Keywords.kw_function))
+ State.Stack.back().NestedBlockIndent = State.Column;
+
if (NextNonComment->isMemberAccess()) {
if (State.Stack.back().CallContinuation == 0)
State.Stack.back().CallContinuation = State.Column;
@@ -688,7 +705,8 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
// foo();
// bar();
// }, a, b, c);
- if (Current.isNot(tok::comment) && Previous && Previous->is(tok::l_brace) &&
+ if (Current.isNot(tok::comment) && Previous &&
+ Previous->isOneOf(tok::l_brace, TT_ArrayInitializerLSquare) &&
State.Stack.size() > 1) {
if (State.Stack[State.Stack.size() - 2].NestedBlockInlined && Newline)
for (unsigned i = 0, e = State.Stack.size() - 1; i != e; ++i)
@@ -713,7 +731,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
if (Current.is(TT_ObjCStringLiteral) && State.StartOfStringLiteral == 0)
State.StartOfStringLiteral = State.Column + 1;
else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&
- !Current.isStringLiteral())
+ !Current.isStringLiteral())
State.StartOfStringLiteral = 0;
State.Column += Current.ColumnWidth;
@@ -891,7 +909,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State,
// be a line break within this call.
for (const FormatToken *Tok = &Current;
Tok && Tok != Current.MatchingParen; Tok = Tok->Next) {
- if (Tok->MustBreakBefore ||
+ if (Tok->MustBreakBefore ||
(Tok->CanBreakBefore && Tok->NewlinesBefore > 0)) {
BreakBeforeParameter = true;
break;
diff --git a/lib/Format/ContinuationIndenter.h b/lib/Format/ContinuationIndenter.h
index 1da6bd9..9b9154e 100644
--- a/lib/Format/ContinuationIndenter.h
+++ b/lib/Format/ContinuationIndenter.h
@@ -148,13 +148,10 @@ struct ParenState {
ParenState(unsigned Indent, unsigned IndentLevel, unsigned LastSpace,
bool AvoidBinPacking, bool NoLineBreak)
: Indent(Indent), IndentLevel(IndentLevel), LastSpace(LastSpace),
- NestedBlockIndent(Indent), FirstLessLess(0),
- BreakBeforeClosingBrace(false), QuestionColumn(0),
+ NestedBlockIndent(Indent), BreakBeforeClosingBrace(false),
AvoidBinPacking(AvoidBinPacking), BreakBeforeParameter(false),
- NoLineBreak(NoLineBreak), LastOperatorWrapped(true), ColonPos(0),
- StartOfFunctionCall(0), StartOfArraySubscripts(0),
- NestedNameSpecifierContinuation(0), CallContinuation(0), VariablePos(0),
- ContainsLineBreak(false), ContainsUnwrappedBuilder(0),
+ NoLineBreak(NoLineBreak), LastOperatorWrapped(true),
+ ContainsLineBreak(false), ContainsUnwrappedBuilder(false),
AlignColons(true), ObjCSelectorNameFound(false),
HasMultipleNestedBlocks(false), NestedBlockInlined(false) {}
@@ -180,90 +177,90 @@ struct ParenState {
///
/// Used to align "<<" operators. 0 if no such operator has been encountered
/// on a level.
- unsigned FirstLessLess;
-
- /// \brief Whether a newline needs to be inserted before the block's closing
- /// brace.
- ///
- /// We only want to insert a newline before the closing brace if there also
- /// was a newline after the beginning left brace.
- bool BreakBeforeClosingBrace;
+ unsigned FirstLessLess = 0;
/// \brief The column of a \c ? in a conditional expression;
- unsigned QuestionColumn;
-
- /// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple
- /// lines, in this context.
- bool AvoidBinPacking;
-
- /// \brief Break after the next comma (or all the commas in this context if
- /// \c AvoidBinPacking is \c true).
- bool BreakBeforeParameter;
-
- /// \brief Line breaking in this context would break a formatting rule.
- bool NoLineBreak;
-
- /// \brief True if the last binary operator on this level was wrapped to the
- /// next line.
- bool LastOperatorWrapped;
+ unsigned QuestionColumn = 0;
/// \brief The position of the colon in an ObjC method declaration/call.
- unsigned ColonPos;
+ unsigned ColonPos = 0;
/// \brief The start of the most recent function in a builder-type call.
- unsigned StartOfFunctionCall;
+ unsigned StartOfFunctionCall = 0;
/// \brief Contains the start of array subscript expressions, so that they
/// can be aligned.
- unsigned StartOfArraySubscripts;
+ unsigned StartOfArraySubscripts = 0;
/// \brief If a nested name specifier was broken over multiple lines, this
/// contains the start column of the second line. Otherwise 0.
- unsigned NestedNameSpecifierContinuation;
+ unsigned NestedNameSpecifierContinuation = 0;
/// \brief If a call expression was broken over multiple lines, this
/// contains the start column of the second line. Otherwise 0.
- unsigned CallContinuation;
+ unsigned CallContinuation = 0;
/// \brief The column of the first variable name in a variable declaration.
///
/// Used to align further variables if necessary.
- unsigned VariablePos;
+ unsigned VariablePos = 0;
+
+ /// \brief Whether a newline needs to be inserted before the block's closing
+ /// brace.
+ ///
+ /// We only want to insert a newline before the closing brace if there also
+ /// was a newline after the beginning left brace.
+ bool BreakBeforeClosingBrace : 1;
+
+ /// \brief Avoid bin packing, i.e. multiple parameters/elements on multiple
+ /// lines, in this context.
+ bool AvoidBinPacking : 1;
+
+ /// \brief Break after the next comma (or all the commas in this context if
+ /// \c AvoidBinPacking is \c true).
+ bool BreakBeforeParameter : 1;
+
+ /// \brief Line breaking in this context would break a formatting rule.
+ bool NoLineBreak : 1;
+
+ /// \brief True if the last binary operator on this level was wrapped to the
+ /// next line.
+ bool LastOperatorWrapped : 1;
/// \brief \c true if this \c ParenState already contains a line-break.
///
/// The first line break in a certain \c ParenState causes extra penalty so
/// that clang-format prefers similar breaks, i.e. breaks in the same
/// parenthesis.
- bool ContainsLineBreak;
+ bool ContainsLineBreak : 1;
/// \brief \c true if this \c ParenState contains multiple segments of a
/// builder-type call on one line.
- bool ContainsUnwrappedBuilder;
+ bool ContainsUnwrappedBuilder : 1;
/// \brief \c true if the colons of the curren ObjC method expression should
/// be aligned.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
- bool AlignColons;
+ bool AlignColons : 1;
/// \brief \c true if at least one selector name was found in the current
/// ObjC method expression.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
- bool ObjCSelectorNameFound;
+ bool ObjCSelectorNameFound : 1;
/// \brief \c true if there are multiple nested blocks inside these parens.
///
/// Not considered for memoization as it will always have the same value at
/// the same token.
- bool HasMultipleNestedBlocks;
+ bool HasMultipleNestedBlocks : 1;
// \brief The start of a nested block (e.g. lambda introducer in C++ or
// "function" in JavaScript) is not wrapped to a new line.
- bool NestedBlockInlined;
+ bool NestedBlockInlined : 1;
bool operator<(const ParenState &Other) const {
if (Indent != Other.Indent)
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index c725b4b..0feeaa0 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -174,7 +174,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
IO.mapOptional("AlignOperands", Style.AlignOperands);
IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
- IO.mapOptional("AlignConsecutiveAssignments", Style.AlignConsecutiveAssignments);
+ IO.mapOptional("AlignConsecutiveAssignments",
+ Style.AlignConsecutiveAssignments);
IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
Style.AllowAllParametersOfDeclarationOnNextLine);
IO.mapOptional("AllowShortBlocksOnASingleLine",
@@ -785,7 +786,8 @@ private:
// Backticks get lexed as tok::unknown tokens. If a template string contains
// a comment start, it gets lexed as a tok::comment, or tok::unknown if
// unterminated.
- if (!EndBacktick->isOneOf(tok::comment, tok::unknown))
+ if (!EndBacktick->isOneOf(tok::comment, tok::string_literal,
+ tok::char_constant, tok::unknown))
return false;
size_t CommentBacktickPos = EndBacktick->TokenText.find('`');
// Unknown token that's not actually a backtick, or a comment that doesn't
@@ -1122,7 +1124,10 @@ private:
Column = FormatTok->LastLineColumnWidth;
}
- if (std::find(ForEachMacros.begin(), ForEachMacros.end(),
+ if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() &&
+ Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() ==
+ tok::pp_define) &&
+ std::find(ForEachMacros.begin(), ForEachMacros.end(),
FormatTok->Tok.getIdentifierInfo()) != ForEachMacros.end())
FormatTok->Type = TT_ForEachMacro;
@@ -1254,7 +1259,8 @@ public:
}
tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
- FormatTokenLexer &Tokens, bool *IncompleteFormat) {
+ FormatTokenLexer &Tokens,
+ bool *IncompleteFormat) {
TokenAnnotator Annotator(Style, Tokens.getKeywords());
for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
Annotator.annotate(*AnnotatedLines[i]);
@@ -1500,8 +1506,7 @@ tooling::Replacements reformat(const FormatStyle &Style,
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
ArrayRef<tooling::Range> Ranges,
- StringRef FileName,
- bool *IncompleteFormat) {
+ StringRef FileName, bool *IncompleteFormat) {
if (Style.DisableFormat)
return tooling::Replacements();
diff --git a/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp
index 88678ca..316171d 100644
--- a/lib/Format/FormatToken.cpp
+++ b/lib/Format/FormatToken.cpp
@@ -203,11 +203,14 @@ void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) {
// We can never place more than ColumnLimit / 3 items in a row (because of the
// spaces and the comma).
- for (unsigned Columns = 1; Columns <= Style.ColumnLimit / 3; ++Columns) {
+ unsigned MaxItems = Style.ColumnLimit / 3;
+ std::vector<unsigned> MinSizeInColumn;
+ MinSizeInColumn.reserve(MaxItems);
+ for (unsigned Columns = 1; Columns <= MaxItems; ++Columns) {
ColumnFormat Format;
Format.Columns = Columns;
Format.ColumnSizes.resize(Columns);
- std::vector<unsigned> MinSizeInColumn(Columns, UINT_MAX);
+ MinSizeInColumn.assign(Columns, UINT_MAX);
Format.LineCount = 1;
bool HasRowWithSufficientColumns = false;
unsigned Column = 0;
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index dd12969..5b7dadb 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -86,24 +86,12 @@ enum TokenType {
};
// Represents what type of block a set of braces open.
-enum BraceBlockKind {
- BK_Unknown,
- BK_Block,
- BK_BracedInit
-};
+enum BraceBlockKind { BK_Unknown, BK_Block, BK_BracedInit };
// The packing kind of a function's parameters.
-enum ParameterPackingKind {
- PPK_BinPacked,
- PPK_OnePerLine,
- PPK_Inconclusive
-};
+enum ParameterPackingKind { PPK_BinPacked, PPK_OnePerLine, PPK_Inconclusive };
-enum FormatDecision {
- FD_Unformatted,
- FD_Continue,
- FD_Break
-};
+enum FormatDecision { FD_Unformatted, FD_Continue, FD_Break };
class TokenRole;
class AnnotatedLine;
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp
index 78e6103..8d08c3d 100644
--- a/lib/Format/TokenAnnotator.cpp
+++ b/lib/Format/TokenAnnotator.cpp
@@ -87,7 +87,7 @@ private:
if (CurrentToken->Previous->isOneOf(tok::pipepipe, tok::ampamp) &&
CurrentToken->Previous->is(TT_BinaryOperator) &&
Contexts[Contexts.size() - 2].IsExpression &&
- Line.First->isNot(tok::kw_template))
+ !Line.startsWith(tok::kw_template))
return false;
updateParameterCount(Left, CurrentToken);
if (!consumeToken())
@@ -255,7 +255,7 @@ private:
// A '[' could be an index subscript (after an identifier or after
// ')' or ']'), it could be the start of an Objective-C method
- // expression, or it could the the start of an Objective-C array literal.
+ // expression, or it could the start of an Objective-C array literal.
FormatToken *Left = CurrentToken->Previous;
Left->ParentBracket = Contexts.back().ContextKind;
FormatToken *Parent = Left->getPreviousNonComment();
@@ -457,7 +457,7 @@ private:
if (Contexts.back().ColonIsDictLiteral) {
Tok->Type = TT_DictLiteral;
} else if (Contexts.back().ColonIsObjCMethodExpr ||
- Line.First->is(TT_ObjCMethodSpecifier)) {
+ Line.startsWith(TT_ObjCMethodSpecifier)) {
Tok->Type = TT_ObjCMethodExpr;
Tok->Previous->Type = TT_SelectorName;
if (Tok->Previous->ColumnWidth >
@@ -503,7 +503,7 @@ private:
if (!parseParens())
return false;
if (Line.MustBeDeclaration && Contexts.size() == 1 &&
- !Contexts.back().IsExpression && Line.First->isNot(TT_ObjCProperty) &&
+ !Contexts.back().IsExpression && !Line.startsWith(TT_ObjCProperty) &&
(!Tok->Previous ||
!Tok->Previous->isOneOf(tok::kw_decltype, TT_LeadingJavaAnnotation)))
Line.MightBeFunctionDecl = true;
@@ -558,7 +558,7 @@ private:
break;
case tok::question:
if (Style.Language == FormatStyle::LK_JavaScript && Tok->Next &&
- Tok->Next->isOneOf(tok::semi, tok::colon, tok::r_paren,
+ Tok->Next->isOneOf(tok::semi, tok::comma, tok::colon, tok::r_paren,
tok::r_brace)) {
// Question marks before semicolons, colons, etc. indicate optional
// types (fields, parameters), e.g.
@@ -581,7 +581,7 @@ private:
if (Contexts.back().InCtorInitializer)
Tok->Type = TT_CtorInitializerComma;
else if (Contexts.back().FirstStartOfName &&
- (Contexts.size() == 1 || Line.First->is(tok::kw_for))) {
+ (Contexts.size() == 1 || Line.startsWith(tok::kw_for))) {
Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
Line.IsMultiVariableDeclStmt = true;
}
@@ -724,7 +724,7 @@ public:
if (ImportStatement)
return LT_ImportStatement;
- if (Line.First->is(TT_ObjCMethodSpecifier)) {
+ if (Line.startsWith(TT_ObjCMethodSpecifier)) {
if (Contexts.back().FirstObjCSelectorName)
Contexts.back().FirstObjCSelectorName->LongestObjCSelectorName =
Contexts.back().LongestObjCSelectorName;
@@ -820,7 +820,7 @@ private:
!Line.First->isOneOf(tok::kw_template, tok::kw_using) &&
(!Current.Previous || Current.Previous->isNot(tok::kw_operator))) {
Contexts.back().IsExpression = true;
- if (!Line.First->is(TT_UnaryOperator)) {
+ if (!Line.startsWith(TT_UnaryOperator)) {
for (FormatToken *Previous = Current.Previous;
Previous && !Previous->isOneOf(tok::comma, tok::semi);
Previous = Previous->Previous) {
@@ -870,7 +870,7 @@ private:
Contexts.back().InCtorInitializer = true;
} else if (Current.is(tok::kw_new)) {
Contexts.back().CanBeExpression = false;
- } else if (Current.is(tok::semi) || Current.is(tok::exclaim)) {
+ } else if (Current.isOneOf(tok::semi, tok::exclaim)) {
// This should be the condition or increment in a for-loop.
Contexts.back().IsExpression = true;
}
@@ -1081,7 +1081,7 @@ private:
// there is also an identifier before the ().
else if (LeftOfParens && Tok.Next &&
(LeftOfParens->Tok.getIdentifierInfo() == nullptr ||
- LeftOfParens->is(tok::kw_return)) &&
+ LeftOfParens->isOneOf(tok::kw_return, tok::kw_case)) &&
!LeftOfParens->isOneOf(TT_OverloadedOperator, tok::at,
TT_TemplateCloser)) {
if (Tok.Next->isOneOf(tok::identifier, tok::numeric_constant)) {
@@ -1441,11 +1441,11 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
ExpressionParser ExprParser(Style, Keywords, Line);
ExprParser.parse();
- if (Line.First->is(TT_ObjCMethodSpecifier))
+ if (Line.startsWith(TT_ObjCMethodSpecifier))
Line.Type = LT_ObjCMethodDecl;
- else if (Line.First->is(TT_ObjCDecl))
+ else if (Line.startsWith(TT_ObjCDecl))
Line.Type = LT_ObjCDecl;
- else if (Line.First->is(TT_ObjCProperty))
+ else if (Line.startsWith(TT_ObjCProperty))
Line.Type = LT_ObjCProperty;
Line.First->SpacesRequiredBefore = 1;
@@ -1638,7 +1638,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) ||
Right.is(tok::kw_operator)) {
- if (Line.First->is(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
+ if (Line.startsWith(tok::kw_for) && Right.PartOfMultiVariableDeclStmt)
return 3;
if (Left.is(TT_StartOfName))
return 110;
@@ -1674,8 +1674,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
(!Right.Next || Right.Next->isNot(tok::l_paren))) {
// Moving trailing annotations to the next line is fine for ObjC method
// declarations.
- if (Line.First->is(TT_ObjCMethodSpecifier))
-
+ if (Line.startsWith(TT_ObjCMethodSpecifier))
return 10;
// Generally, breaking before a trailing annotation is bad unless it is
// function-like. It seems to be especially preferable to keep standard
@@ -1687,7 +1686,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
}
// In for-loops, prefer breaking at ',' and ';'.
- if (Line.First->is(tok::kw_for) && Left.is(tok::equal))
+ if (Line.startsWith(tok::kw_for) && Left.is(tok::equal))
return 4;
// In Objective-C method expressions, prefer breaking before "param:" over
@@ -1800,6 +1799,7 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return true;
if (Left.is(TT_PointerOrReference))
return Right.Tok.isLiteral() || Right.is(TT_BlockComment) ||
+ (Right.is(tok::l_brace) && Right.BlockKind == BK_Block) ||
(!Right.isOneOf(TT_PointerOrReference, TT_ArraySubscriptLSquare,
tok::l_paren) &&
(Style.PointerAlignment != FormatStyle::PAS_Right &&
@@ -1844,7 +1844,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
tok::kw_new, tok::kw_delete) &&
(!Left.Previous || Left.Previous->isNot(tok::period))))) ||
(Style.SpaceBeforeParens == FormatStyle::SBPO_Always &&
- (Left.is(tok::identifier) || Left.isFunctionLikeKeyword() || Left.is(tok::r_paren)) &&
+ (Left.is(tok::identifier) || Left.isFunctionLikeKeyword() ||
+ Left.is(tok::r_paren)) &&
Line.Type != LT_PreprocessorDirective);
}
if (Left.is(tok::at) && Right.Tok.getObjCKeywordID() != tok::objc_not_keyword)
@@ -1989,7 +1990,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
return false;
if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
- Line.First->is(tok::hash))
+ Line.startsWith(tok::hash))
return true;
if (Right.is(TT_TrailingUnaryOperator))
return false;
@@ -2010,6 +2011,39 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.NewlinesBefore > 1)
return true;
+ if (Style.Language == FormatStyle::LK_JavaScript) {
+ // FIXME: This might apply to other languages and token kinds.
+ if (Right.is(tok::char_constant) && Left.is(tok::plus) && Left.Previous &&
+ Left.Previous->is(tok::char_constant))
+ return true;
+ if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 &&
+ Left.Previous && Left.Previous->is(tok::equal) &&
+ Line.First->isOneOf(tok::identifier, Keywords.kw_import, tok::kw_export,
+ tok::kw_const) &&
+ // kw_var is a pseudo-token that's a tok::identifier, so matches above.
+ !Line.startsWith(Keywords.kw_var))
+ // Object literals on the top level of a file are treated as "enum-style".
+ // Each key/value pair is put on a separate line, instead of bin-packing.
+ return true;
+ if (Left.is(tok::l_brace) && Line.Level == 0 &&
+ (Line.startsWith(tok::kw_enum) ||
+ Line.startsWith(tok::kw_export, tok::kw_enum)))
+ // JavaScript top-level enum key/value pairs are put on separate lines
+ // instead of bin-packing.
+ return true;
+ if (Right.is(tok::r_brace) && Left.is(tok::l_brace) &&
+ !Left.Children.empty())
+ // Support AllowShortFunctionsOnASingleLine for JavaScript.
+ return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
+ (Left.NestingLevel == 0 && Line.Level == 0 &&
+ Style.AllowShortFunctionsOnASingleLine ==
+ FormatStyle::SFS_Inline);
+ } else if (Style.Language == FormatStyle::LK_Java) {
+ if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
+ Right.Next->is(tok::string_literal))
+ return true;
+ }
+
// If the last token before a '}' is a comma or a trailing comment, the
// intention is to insert a line break after it in order to make shuffling
// around entries easier.
@@ -2030,7 +2064,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Left.isNot(TT_CtorInitializerColon) &&
(Right.NewlinesBefore > 0 && Right.HasUnescapedNewline);
if (Left.isTrailingComment())
- return true;
+ return true;
if (Left.isStringLiteral() &&
(Right.isStringLiteral() || Right.is(TT_ObjCStringLiteral)))
return true;
@@ -2060,12 +2094,6 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
return true;
if (Right.is(TT_InlineASMBrace))
return Right.HasUnescapedNewline;
- if (Style.Language == FormatStyle::LK_JavaScript && Right.is(tok::r_brace) &&
- Left.is(tok::l_brace) && !Left.Children.empty())
- // Support AllowShortFunctionsOnASingleLine for JavaScript.
- return Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_None ||
- (Left.NestingLevel == 0 && Line.Level == 0 &&
- Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline);
if (isAllmanBrace(Left) || isAllmanBrace(Right))
return Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
Style.BreakBeforeBraces == FormatStyle::BS_GNU;
@@ -2082,26 +2110,6 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Line.Last->is(tok::l_brace))
return true;
- if (Style.Language == FormatStyle::LK_JavaScript) {
- // FIXME: This might apply to other languages and token kinds.
- if (Right.is(tok::char_constant) && Left.is(tok::plus) && Left.Previous &&
- Left.Previous->is(tok::char_constant))
- return true;
- if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) &&
- Left.NestingLevel == 0 && Left.Previous &&
- Left.Previous->is(tok::equal) &&
- Line.First->isOneOf(tok::identifier, Keywords.kw_import,
- tok::kw_export) &&
- // kw_var is a pseudo-token that's a tok::identifier, so matches above.
- !Line.First->is(Keywords.kw_var))
- // Enum style object literal.
- return true;
- } else if (Style.Language == FormatStyle::LK_Java) {
- if (Right.is(tok::plus) && Left.is(tok::string_literal) && Right.Next &&
- Right.Next->is(tok::string_literal))
- return true;
- }
-
return false;
}
diff --git a/lib/Format/TokenAnnotator.h b/lib/Format/TokenAnnotator.h
index a948cdb..b8a6be0 100644
--- a/lib/Format/TokenAnnotator.h
+++ b/lib/Format/TokenAnnotator.h
@@ -59,7 +59,7 @@ public:
I->Tok->Previous = Current;
Current = Current->Next;
Current->Children.clear();
- for (const auto& Child : Node.Children) {
+ for (const auto &Child : Node.Children) {
Children.push_back(new AnnotatedLine(Child));
Current->Children.push_back(Children.back());
}
@@ -80,6 +80,12 @@ public:
}
}
+ /// \c true if this line starts with the given tokens in order, ignoring
+ /// comments.
+ template <typename... Ts> bool startsWith(Ts... Tokens) const {
+ return startsWith(First, Tokens...);
+ }
+
FormatToken *First;
FormatToken *Last;
@@ -107,6 +113,18 @@ private:
// Disallow copying.
AnnotatedLine(const AnnotatedLine &) = delete;
void operator=(const AnnotatedLine &) = delete;
+
+ template <typename A, typename... Ts>
+ bool startsWith(FormatToken *Tok, A K1) const {
+ while (Tok && Tok->is(tok::comment))
+ Tok = Tok->Next;
+ return Tok && Tok->is(K1);
+ }
+
+ template <typename A, typename... Ts>
+ bool startsWith(FormatToken *Tok, A K1, Ts... Tokens) const {
+ return startsWith(Tok, K1) && startsWith(Tok->Next, Tokens...);
+ }
};
/// \brief Determines extra information about the tokens comprising an
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index cbf8c6c..b6784b3 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -21,7 +21,7 @@ namespace {
bool startsExternCBlock(const AnnotatedLine &Line) {
const FormatToken *Next = Line.First->getNextNonComment();
const FormatToken *NextNext = Next ? Next->getNextNonComment() : nullptr;
- return Line.First->is(tok::kw_extern) && Next && Next->isStringLiteral() &&
+ return Line.startsWith(tok::kw_extern) && Next && Next->isStringLiteral() &&
NextNext && NextNext->is(tok::l_brace);
}
@@ -51,11 +51,13 @@ public:
/// next.
void nextLine(const AnnotatedLine &Line) {
Offset = getIndentOffset(*Line.First);
+ // Update the indent level cache size so that we can rely on it
+ // having the right size in adjustToUnmodifiedline.
+ while (IndentForLevel.size() <= Line.Level)
+ IndentForLevel.push_back(-1);
if (Line.InPPDirective) {
Indent = Line.Level * Style.IndentWidth + AdditionalIndent;
} else {
- while (IndentForLevel.size() <= Line.Level)
- IndentForLevel.push_back(-1);
IndentForLevel.resize(Line.Level + 1);
Indent = getIndent(IndentForLevel, Line.Level);
}
@@ -72,7 +74,7 @@ public:
unsigned LevelIndent = Line.First->OriginalColumn;
if (static_cast<int>(LevelIndent) - Offset >= 0)
LevelIndent -= Offset;
- if ((Line.First->isNot(tok::comment) || IndentForLevel[Line.Level] == -1) &&
+ if ((!Line.First->is(tok::comment) || IndentForLevel[Line.Level] == -1) &&
!Line.InPPDirective)
IndentForLevel[Line.Level] = LevelIndent;
}
@@ -187,7 +189,7 @@ private:
// If necessary, change to something smarter.
bool MergeShortFunctions =
Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
- (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Empty &&
+ (Style.AllowShortFunctionsOnASingleLine >= FormatStyle::SFS_Empty &&
I[1]->First->is(tok::r_brace)) ||
(Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
TheLine->Level != 0);
@@ -278,7 +280,7 @@ private:
TT_LineComment))
return 0;
// Only inline simple if's (no nested if or else).
- if (I + 2 != E && Line.First->is(tok::kw_if) &&
+ if (I + 2 != E && Line.startsWith(tok::kw_if) &&
I[2]->First->is(tok::kw_else))
return 0;
return 1;
@@ -332,12 +334,11 @@ private:
return 0;
if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
tok::kw___try, tok::kw_catch, tok::kw___finally,
- tok::kw_for, tok::r_brace) ||
- Line.First->is(Keywords.kw___except)) {
+ tok::kw_for, tok::r_brace, Keywords.kw___except)) {
if (!Style.AllowShortBlocksOnASingleLine)
return 0;
if (!Style.AllowShortIfStatementsOnASingleLine &&
- Line.First->is(tok::kw_if))
+ Line.startsWith(tok::kw_if))
return 0;
if (!Style.AllowShortLoopsOnASingleLine &&
Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for))
@@ -360,7 +361,7 @@ private:
Tok->SpacesRequiredBefore = 0;
Tok->CanBreakBefore = true;
return 1;
- } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace) &&
+ } else if (Limit != 0 && !Line.startsWith(tok::kw_namespace) &&
!startsExternCBlock(Line)) {
// We don't merge short records.
if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct,
@@ -444,9 +445,9 @@ private:
const FormatStyle &Style;
const AdditionalKeywords &Keywords;
- const SmallVectorImpl<AnnotatedLine*>::const_iterator End;
+ const SmallVectorImpl<AnnotatedLine *>::const_iterator End;
- SmallVectorImpl<AnnotatedLine*>::const_iterator Next;
+ SmallVectorImpl<AnnotatedLine *>::const_iterator Next;
};
static void markFinalized(FormatToken *Tok) {
diff --git a/lib/Format/UnwrappedLineFormatter.h b/lib/Format/UnwrappedLineFormatter.h
index da9aa1c..478617d 100644
--- a/lib/Format/UnwrappedLineFormatter.h
+++ b/lib/Format/UnwrappedLineFormatter.h
@@ -52,7 +52,8 @@ private:
/// \brief Returns the column limit for a line, taking into account whether we
/// need an escaped newline due to a continued preprocessor directive.
- unsigned getColumnLimit(bool InPPDirective, const AnnotatedLine *NextLine) const;
+ unsigned getColumnLimit(bool InPPDirective,
+ const AnnotatedLine *NextLine) const;
// Cache to store the penalty of formatting a vector of AnnotatedLines
// starting from a specific additional offset. Improves performance if there
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index 6ad4329..ea1ca39 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -251,7 +251,6 @@ void UnwrappedLineParser::parse() {
assert(PPLevelBranchIndex.back() <= PPLevelBranchCount.back());
}
} while (!PPLevelBranchIndex.empty());
-
}
void UnwrappedLineParser::parseFile() {
@@ -774,7 +773,15 @@ void UnwrappedLineParser::parseStructuralElement() {
parseBracedList();
break;
case tok::kw_enum:
+ // parseEnum falls through and does not yet add an unwrapped line as an
+ // enum definition can start a structural element.
parseEnum();
+ // This does not apply for Java and JavaScript.
+ if (Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) {
+ addUnwrappedLine();
+ return;
+ }
break;
case tok::kw_typedef:
nextToken();
@@ -785,9 +792,15 @@ void UnwrappedLineParser::parseStructuralElement() {
case tok::kw_struct:
case tok::kw_union:
case tok::kw_class:
+ // parseRecord falls through and does not yet add an unwrapped line as a
+ // record declaration or definition can start a structural element.
parseRecord();
- // A record declaration or definition is always the start of a structural
- // element.
+ // This does not apply for Java and JavaScript.
+ if (Style.Language == FormatStyle::LK_Java ||
+ Style.Language == FormatStyle::LK_JavaScript) {
+ addUnwrappedLine();
+ return;
+ }
break;
case tok::period:
nextToken();
@@ -848,6 +861,7 @@ void UnwrappedLineParser::parseStructuralElement() {
Style.Language == FormatStyle::LK_Java) &&
FormatTok->is(Keywords.kw_interface)) {
parseRecord();
+ addUnwrappedLine();
break;
}
@@ -872,8 +886,7 @@ void UnwrappedLineParser::parseStructuralElement() {
? FormatTok->NewlinesBefore > 0
: CommentsBeforeNextToken.front()->NewlinesBefore > 0;
- if (FollowedByNewline &&
- (Text.size() >= 5 || FunctionLike) &&
+ if (FollowedByNewline && (Text.size() >= 5 || FunctionLike) &&
tokenCanStartNewLine(FormatTok->Tok) && Text == Text.upper()) {
addUnwrappedLine();
return;
@@ -1033,7 +1046,7 @@ void UnwrappedLineParser::tryToParseJSFunction() {
if (FormatTok->is(tok::l_brace))
tryToParseBracedList();
else
- while(FormatTok->isNot(tok::l_brace) && !eof())
+ while (FormatTok->isNot(tok::l_brace) && !eof())
nextToken();
}
@@ -1066,7 +1079,7 @@ bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) {
nextToken();
// Fat arrows can be followed by simple expressions or by child blocks
// in curly braces.
- if (FormatTok->is(tok::l_brace)){
+ if (FormatTok->is(tok::l_brace)) {
parseChildBlock();
continue;
}
@@ -1475,6 +1488,7 @@ void UnwrappedLineParser::parseEnum() {
// Eat up enum class ...
if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct))
nextToken();
+
while (FormatTok->Tok.getIdentifierInfo() ||
FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
tok::greater, tok::comma, tok::question)) {
@@ -1482,8 +1496,14 @@ void UnwrappedLineParser::parseEnum() {
// We can have macros or attributes in between 'enum' and the enum name.
if (FormatTok->is(tok::l_paren))
parseParens();
- if (FormatTok->is(tok::identifier))
+ if (FormatTok->is(tok::identifier)) {
nextToken();
+ // If there are two identifiers in a row, this is likely an elaborate
+ // return type. In Java, this can be "implements", etc.
+ if (Style.Language == FormatStyle::LK_Cpp &&
+ FormatTok->is(tok::identifier))
+ return;
+ }
}
// Just a declaration or something is wrong.
@@ -1505,8 +1525,8 @@ void UnwrappedLineParser::parseEnum() {
addUnwrappedLine();
}
- // We fall through to parsing a structural element afterwards, so that in
- // enum A {} n, m;
+ // There is no addUnwrappedLine() here so that we fall through to parsing a
+ // structural element afterwards. Thus, in "enum A {} n, m;",
// "} n, m;" will end up in one unwrapped line.
}
@@ -1576,7 +1596,6 @@ void UnwrappedLineParser::parseRecord() {
const FormatToken &InitialToken = *FormatTok;
nextToken();
-
// The actual identifier can be a nested name specifier, and in macros
// it is often token-pasted.
while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash,
@@ -1623,13 +1642,9 @@ void UnwrappedLineParser::parseRecord() {
parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true,
/*MunchSemi=*/false);
}
- // We fall through to parsing a structural element afterwards, so
- // class A {} n, m;
- // will end up in one unwrapped line.
- // This does not apply for Java and JavaScript.
- if (Style.Language == FormatStyle::LK_Java ||
- Style.Language == FormatStyle::LK_JavaScript)
- addUnwrappedLine();
+ // There is no addUnwrappedLine() here so that we fall through to parsing a
+ // structural element afterwards. Thus, in "class A {} n, m;",
+ // "} n, m;" will end up in one unwrapped line.
}
void UnwrappedLineParser::parseObjCProtocolList() {
@@ -1722,7 +1737,8 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {
return;
}
- if (FormatTok->isOneOf(tok::kw_const, tok::kw_class, Keywords.kw_var))
+ if (FormatTok->isOneOf(tok::kw_const, tok::kw_class, tok::kw_enum,
+ Keywords.kw_var))
return; // Fall through to parsing the corresponding structure.
if (FormatTok->is(tok::l_brace)) {
diff --git a/lib/Format/WhitespaceManager.h b/lib/Format/WhitespaceManager.h
index 4bfc813..d973838 100644
--- a/lib/Format/WhitespaceManager.h
+++ b/lib/Format/WhitespaceManager.h
@@ -167,9 +167,11 @@ private:
/// \brief Align consecutive assignments over all \c Changes.
void alignConsecutiveAssignments();
- /// \brief Align consecutive assignments from change \p Start to change \p End at
+ /// \brief Align consecutive assignments from change \p Start to change \p End
+ /// at
/// the specified \p Column.
- void alignConsecutiveAssignments(unsigned Start, unsigned End, unsigned Column);
+ void alignConsecutiveAssignments(unsigned Start, unsigned End,
+ unsigned Column);
/// \brief Align trailing comments over all \c Changes.
void alignTrailingComments();
OpenPOWER on IntegriCloud