diff options
Diffstat (limited to 'clang/lib/Format/ContinuationIndenter.cpp')
-rw-r--r-- | clang/lib/Format/ContinuationIndenter.cpp | 95 |
1 files changed, 65 insertions, 30 deletions
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 651ec80d6196..412c57b850b5 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -21,6 +21,7 @@ #include "clang/Format/Format.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Debug.h" +#include <optional> #define DEBUG_TYPE "format-indenter" @@ -146,13 +147,13 @@ static bool opensProtoMessageField(const FormatToken &LessTok, (LessTok.Previous && LessTok.Previous->is(tok::equal)))); } -// Returns the delimiter of a raw string literal, or None if TokenText is not -// the text of a raw string literal. The delimiter could be the empty string. -// For example, the delimiter of R"deli(cont)deli" is deli. -static llvm::Optional<StringRef> getRawStringDelimiter(StringRef TokenText) { +// Returns the delimiter of a raw string literal, or std::nullopt if TokenText +// is not the text of a raw string literal. The delimiter could be the empty +// string. For example, the delimiter of R"deli(cont)deli" is deli. +static std::optional<StringRef> getRawStringDelimiter(StringRef TokenText) { if (TokenText.size() < 5 // The smallest raw string possible is 'R"()"'. || !TokenText.startswith("R\"") || !TokenText.endswith("\"")) { - return None; + return std::nullopt; } // A raw string starts with 'R"<delimiter>(' and delimiter is ascii and has @@ -160,15 +161,15 @@ static llvm::Optional<StringRef> getRawStringDelimiter(StringRef TokenText) { // 19 bytes. size_t LParenPos = TokenText.substr(0, 19).find_first_of('('); if (LParenPos == StringRef::npos) - return None; + return std::nullopt; StringRef Delimiter = TokenText.substr(2, LParenPos - 2); // Check that the string ends in ')Delimiter"'. size_t RParenPos = TokenText.size() - Delimiter.size() - 2; if (TokenText[RParenPos] != ')') - return None; + return std::nullopt; if (!TokenText.substr(RParenPos + 1).startswith(Delimiter)) - return None; + return std::nullopt; return Delimiter; } @@ -186,7 +187,7 @@ getCanonicalRawStringDelimiter(const FormatStyle &Style, RawStringFormatStyleManager::RawStringFormatStyleManager( const FormatStyle &CodeStyle) { for (const auto &RawStringFormat : CodeStyle.RawStringFormats) { - llvm::Optional<FormatStyle> LanguageStyle = + std::optional<FormatStyle> LanguageStyle = CodeStyle.GetLanguageStyle(RawStringFormat.Language); if (!LanguageStyle) { FormatStyle PredefinedStyle; @@ -205,20 +206,20 @@ RawStringFormatStyleManager::RawStringFormatStyleManager( } } -llvm::Optional<FormatStyle> +std::optional<FormatStyle> RawStringFormatStyleManager::getDelimiterStyle(StringRef Delimiter) const { auto It = DelimiterStyle.find(Delimiter); if (It == DelimiterStyle.end()) - return None; + return std::nullopt; return It->second; } -llvm::Optional<FormatStyle> +std::optional<FormatStyle> RawStringFormatStyleManager::getEnclosingFunctionStyle( StringRef EnclosingFunction) const { auto It = EnclosingFunctionStyle.find(EnclosingFunction); if (It == EnclosingFunctionStyle.end()) - return None; + return std::nullopt; return It->second; } @@ -331,6 +332,15 @@ bool ContinuationIndenter::canBreak(const LineState &State) { if (Previous.is(tok::l_square) && Previous.is(TT_ObjCMethodExpr)) return false; + if (Current.is(TT_ConditionalExpr) && Previous.is(tok::r_paren) && + Previous.MatchingParen && Previous.MatchingParen->Previous && + Previous.MatchingParen->Previous->MatchingParen && + Previous.MatchingParen->Previous->MatchingParen->is(TT_LambdaLBrace)) { + // We have a lambda within a conditional expression, allow breaking here. + assert(Previous.MatchingParen->Previous->is(tok::r_brace)); + return true; + } + return !CurrentState.NoLineBreak; } @@ -343,8 +353,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { auto LambdaBodyLength = getLengthToMatchingParen(Current, State.Stack); return LambdaBodyLength > getColumnLimit(State); } - if (Current.MustBreakBefore || Current.is(TT_InlineASMColon)) + if (Current.MustBreakBefore || + (Current.is(TT_InlineASMColon) && + (Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_Always || + Style.BreakBeforeInlineASMColon == FormatStyle::BBIAS_OnlyMultiline))) { return true; + } if (CurrentState.BreakBeforeClosingBrace && Current.closesBlockOrBlockTypeList(Style)) { return true; @@ -444,7 +458,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { } // If the template declaration spans multiple lines, force wrap before the - // function/class declaration + // function/class declaration. if (Previous.ClosesTemplateDeclaration && CurrentState.BreakBeforeParameter && Current.CanBreakBefore) { return true; @@ -552,7 +566,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { // If the return type spans multiple lines, wrap before the function name. if (((Current.is(TT_FunctionDeclarationName) && - // Don't break before a C# function when no break after return type + !State.Line->ReturnTypeWrapped && + // Don't break before a C# function when no break after return type. (!Style.isCSharp() || Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) && // Don't always break between a JavaScript `function` and the function @@ -707,8 +722,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, (Previous.is(tok::l_brace) && Previous.isNot(BK_Block) && Style.Cpp11BracedListStyle)) && State.Column > getNewLineColumn(State) && - (!Previous.Previous || !Previous.Previous->isOneOf( - tok::kw_for, tok::kw_while, tok::kw_switch)) && + (!Previous.Previous || + !Previous.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, + tok::kw_switch)) && // Don't do this for simple (no expressions) one-argument function calls // as that feels like needlessly wasting whitespace, e.g.: // @@ -1090,8 +1106,12 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { CurrentState.Indent + Style.ContinuationIndentWidth); } - if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths && - State.Line->First->is(tok::kw_enum)) { + // After a goto label. Usually labels are on separate lines. However + // for Verilog the labels may be only recognized by the annotator and + // thus are on the same line as the current token. + if ((Style.isVerilog() && Keywords.isVerilogEndOfLabel(Previous)) || + (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths && + State.Line->First->is(tok::kw_enum))) { return (Style.IndentWidth * State.Line->First->IndentLevel) + Style.IndentWidth; } @@ -1244,6 +1264,9 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) { return ContinuationIndent; } + if (State.Line->InPragmaDirective) + return CurrentState.Indent + Style.ContinuationIndentWidth; + // This ensure that we correctly format ObjC methods calls without inputs, // i.e. where the last element isn't selector like: [callee method]; if (NextNonComment->is(tok::identifier) && NextNonComment->FakeRParens == 0 && @@ -1301,7 +1324,7 @@ static bool hasNestedBlockInlined(const FormatToken *Previous, if (Previous->ParameterCount > 1) return true; - // Also a nested block if contains a lambda inside function with 1 parameter + // Also a nested block if contains a lambda inside function with 1 parameter. return Style.BraceWrapping.BeforeLambdaBody && Current.is(TT_LambdaLSquare); } @@ -1399,8 +1422,10 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, CurrentState.NestedBlockIndent = State.Column + Current.ColumnWidth + 1; if (Current.isOneOf(TT_LambdaLSquare, TT_LambdaArrow)) CurrentState.LastSpace = State.Column; - if (Current.is(TT_RequiresExpression)) + if (Current.is(TT_RequiresExpression) && + Style.RequiresExpressionIndentation == FormatStyle::REI_Keyword) { CurrentState.NestedBlockIndent = State.Column; + } // Insert scopes created by fake parenthesis. const FormatToken *Previous = Current.getPreviousNonComment(); @@ -1514,6 +1539,12 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace); } + // Special case for generic selection expressions, its comma-separated + // expressions are not aligned to the opening paren like regular calls, but + // rather continuation-indented relative to the _Generic keyword. + if (Previous && Previous->endsSequence(tok::l_paren, tok::kw__Generic)) + NewParenState.Indent = CurrentState.LastSpace; + if (Previous && (Previous->getPrecedence() == prec::Assignment || Previous->isOneOf(tok::kw_return, TT_RequiresClause) || @@ -1521,7 +1552,7 @@ void ContinuationIndenter::moveStatePastFakeLParens(LineState &State, Previous->is(TT_ConditionalExpr))) && !Newline) { // If BreakBeforeBinaryOperators is set, un-indent a bit to account for - // the operator and keep the operands aligned + // the operator and keep the operands aligned. if (Style.AlignOperands == FormatStyle::OAS_AlignAfterOperator) NewParenState.UnindentOperator = true; // Mark indentation as alignment if the expression is aligned. @@ -1660,8 +1691,12 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, (State.Line->Type != LT_ObjCDecl && Style.BinPackParameters) || (State.Line->Type == LT_ObjCDecl && ObjCBinPackProtocolList); + bool GenericSelection = + Current.getPreviousNonComment() && + Current.getPreviousNonComment()->is(tok::kw__Generic); + AvoidBinPacking = - (CurrentState.IsCSharpGenericTypeConstraint) || + (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection || (Style.isJavaScript() && EndsInComma) || (State.Line->MustBeDeclaration && !BinPackDeclaration) || (!State.Line->MustBeDeclaration && !Style.BinPackArguments) || @@ -1713,7 +1748,7 @@ void ContinuationIndenter::moveStatePastScopeOpener(LineState &State, if (Style.BraceWrapping.BeforeLambdaBody && Current.Next != nullptr && Current.is(tok::l_paren)) { - // Search for any parameter that is a lambda + // Search for any parameter that is a lambda. FormatToken const *next = Current.Next; while (next != nullptr) { if (next->is(TT_LambdaLSquare)) { @@ -2045,21 +2080,21 @@ static StringRef getEnclosingFunctionName(const FormatToken &Current) { return Tok->TokenText; } -llvm::Optional<FormatStyle> +std::optional<FormatStyle> ContinuationIndenter::getRawStringStyle(const FormatToken &Current, const LineState &State) { if (!Current.isStringLiteral()) - return None; + return std::nullopt; auto Delimiter = getRawStringDelimiter(Current.TokenText); if (!Delimiter) - return None; + return std::nullopt; auto RawStringStyle = RawStringFormats.getDelimiterStyle(*Delimiter); if (!RawStringStyle && Delimiter->empty()) { RawStringStyle = RawStringFormats.getEnclosingFunctionStyle( getEnclosingFunctionName(Current)); } if (!RawStringStyle) - return None; + return std::nullopt; RawStringStyle->ColumnLimit = getColumnLimit(State); return RawStringStyle; } @@ -2533,7 +2568,7 @@ ContinuationIndenter::breakProtrudingToken(const FormatToken &Current, } unsigned ContinuationIndenter::getColumnLimit(const LineState &State) const { - // In preprocessor directives reserve two chars for trailing " \" + // In preprocessor directives reserve two chars for trailing " \". return Style.ColumnLimit - (State.Line->InPPDirective ? 2 : 0); } |