State.ParenLevel = 0;
State.StartOfStringLiteral = 0;
State.StartOfLineLevel = State.ParenLevel;
+ State.IgnoreStackForComparison = false;
// The first token has already been indented and thus consumed.
moveStateToNextToken(State, /*DryRun=*/ false);
/// levels.
std::vector<ParenState> Stack;
+ /// \brief Ignore the stack of \c ParenStates for state comparison.
+ ///
+ /// In long and deeply nested unwrapped lines, the current algorithm can
+ /// be insufficient for finding the best formatting with a reasonable amount
+ /// of time and memory. Setting this flag will effectively lead to the
+ /// algorithm not analyzing some combinations. However, these combinations
+ /// rarely contain the optimal solution: In short, accepting a higher
+ /// penalty early would need to lead to different values in the \c
+ /// ParenState stack (in an otherwise identical state) and these different
+ /// values would need to lead to a significant amount of avoided penalty
+ /// later.
+ ///
+ /// FIXME: Come up with a better algorithm instead.
+ bool IgnoreStackForComparison;
+
/// \brief Comparison operator to be able to used \c LineState in \c map.
bool operator<(const LineState &Other) const {
if (NextToken != Other.NextToken)
return StartOfLineLevel < Other.StartOfLineLevel;
if (StartOfStringLiteral != Other.StartOfStringLiteral)
return StartOfStringLiteral < Other.StartOfStringLiteral;
+ if (IgnoreStackForComparison || Other.IgnoreStackForComparison)
+ return false;
return Stack < Other.Stack;
}
};
AvoidBinPacking = !Style.BinPackParameters;
}
- if (Current.NoMoreTokensOnLevel && Current.FakeLParens.empty()) {
- // This parenthesis was the last token possibly making use of Indent and
- // LastSpace of the next higher ParenLevel. Thus, erase them to achieve
- // better memoization results.
- for (unsigned i = State.Stack.size() - 1; i > 0; --i) {
- State.Stack[i].Indent = 0;
- State.Stack[i].LastSpace = 0;
- if (!State.Stack[i].ForFakeParenthesis)
- break;
- }
- }
-
State.Stack.push_back(ParenState(NewIndent, LastSpace, AvoidBinPacking,
State.Stack.back().NoLineBreak));
++State.ParenLevel;
}
Queue.pop();
+ // Cut off the analysis of certain solutions if the analysis gets too
+ // complex. See description of IgnoreStackForComparison.
+ if (Count > 10000)
+ Node->State.IgnoreStackForComparison = true;
+
if (!Seen.insert(Node->State).second)
// State already examined with lower penalty.
continue;
ParameterCount(0), TotalLength(FormatTok.TokenLength),
BindingStrength(0), SplitPenalty(0), LongestObjCSelectorName(0),
DefinesFunctionType(false), Parent(NULL), FakeRParens(0),
- LastInChainOfCalls(false), PartOfMultiVariableDeclStmt(false),
- NoMoreTokensOnLevel(false) {}
+ LastInChainOfCalls(false), PartOfMultiVariableDeclStmt(false) {}
bool is(tok::TokenKind Kind) const { return FormatTok.Tok.is(Kind); }
/// Only set if \c Type == \c TT_StartOfName.
bool PartOfMultiVariableDeclStmt;
- /// \brief Set to \c true for "("-tokens if this is the last token other than
- /// ")" in the next higher parenthesis level.
- ///
- /// If this is \c true, no more formatting decisions have to be made on the
- /// next higher parenthesis level, enabling optimizations.
- ///
- /// Example:
- /// \code
- /// aaaaaa(aaaaaa());
- /// ^ // Set to true for this parenthesis.
- /// \endcode
- bool NoMoreTokensOnLevel;
-
/// \brief Returns the previous token ignoring comments.
AnnotatedToken *getPreviousNoneComment() const;