diff options
Diffstat (limited to 'lib/Format/TokenAnnotator.cpp')
-rw-r--r-- | lib/Format/TokenAnnotator.cpp | 70 |
1 files changed, 63 insertions, 7 deletions
diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index 3a19215e18037..24c2f998c388a 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -366,7 +366,8 @@ private: // specifier parameter, although this is technically valid: // [[foo(:)]] if (AttrTok->is(tok::colon) || - AttrTok->startsSequence(tok::identifier, tok::identifier)) + AttrTok->startsSequence(tok::identifier, tok::identifier) || + AttrTok->startsSequence(tok::r_paren, tok::identifier)) return false; if (AttrTok->is(tok::ellipsis)) return true; @@ -398,9 +399,11 @@ private: bool IsCpp11AttributeSpecifier = isCpp11AttributeSpecifier(*Left) || Contexts.back().InCpp11AttributeSpecifier; + bool InsideInlineASM = Line.startsWith(tok::kw_asm); bool StartsObjCMethodExpr = - !CppArrayTemplates && Style.isCpp() && !IsCpp11AttributeSpecifier && - Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) && + !InsideInlineASM && !CppArrayTemplates && Style.isCpp() && + !IsCpp11AttributeSpecifier && Contexts.back().CanBeExpression && + Left->isNot(TT_LambdaLSquare) && !CurrentToken->isOneOf(tok::l_brace, tok::r_square) && (!Parent || Parent->isOneOf(tok::colon, tok::l_square, tok::l_paren, @@ -1120,6 +1123,7 @@ private: (Tok.Next->Next->TokenText == "module" || Tok.Next->Next->TokenText == "provide" || Tok.Next->Next->TokenText == "require" || + Tok.Next->Next->TokenText == "requireType" || Tok.Next->Next->TokenText == "forwardDeclare") && Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren); } @@ -2517,7 +2521,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, Right.MatchingParen->BlockKind != BK_Block)) return !Style.Cpp11BracedListStyle; if (Left.is(TT_BlockComment)) - return !Left.TokenText.endswith("=*/"); + // No whitespace in x(/*foo=*/1), except for JavaScript. + return Style.Language == FormatStyle::LK_JavaScript || + !Left.TokenText.endswith("=*/"); if (Right.is(tok::l_paren)) { if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) || (Left.is(tok::r_square) && Left.is(TT_AttributeSquare))) @@ -2553,8 +2559,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return false; if (Left.is(TT_TemplateCloser) && Left.MatchingParen && Left.MatchingParen->Previous && - Left.MatchingParen->Previous->is(tok::period)) + (Left.MatchingParen->Previous->is(tok::period) || + Left.MatchingParen->Previous->is(tok::coloncolon))) + // Java call to generic function with explicit type: // A.<B<C<...>>>DoSomething(); + // A::<B<C<...>>>DoSomething(); // With a Java 8 method reference. return false; if (Left.is(TT_TemplateCloser) && Right.is(tok::l_square)) return false; @@ -2774,6 +2783,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (!Style.SpaceBeforeAssignmentOperators && Right.getPrecedence() == prec::Assignment) return false; + if (Style.Language == FormatStyle::LK_Java && Right.is(tok::coloncolon) && + (Left.is(tok::identifier) || Left.is(tok::kw_this))) + return false; if (Right.is(tok::coloncolon) && Left.is(tok::identifier)) // Generally don't remove existing spaces between an identifier and "::". // The identifier might actually be a macro name such as ALWAYS_INLINE. If @@ -2866,6 +2878,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, } else if (Style.Language == FormatStyle::LK_Cpp || Style.Language == FormatStyle::LK_ObjC || Style.Language == FormatStyle::LK_Proto || + Style.Language == FormatStyle::LK_TableGen || Style.Language == FormatStyle::LK_TextProto) { if (Left.isStringLiteral() && Right.isStringLiteral()) return true; @@ -3041,6 +3054,30 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return true; } + // Deal with lambda arguments in C++ - we want consistent line breaks whether + // they happen to be at arg0, arg1 or argN. The selection is a bit nuanced + // as aggressive line breaks are placed when the lambda is not the last arg. + if ((Style.Language == FormatStyle::LK_Cpp || + Style.Language == FormatStyle::LK_ObjC) && + Left.is(tok::l_paren) && Left.BlockParameterCount > 0 && + !Right.isOneOf(tok::l_paren, TT_LambdaLSquare)) { + // Multiple lambdas in the same function call force line breaks. + if (Left.BlockParameterCount > 1) + return true; + + // A lambda followed by another arg forces a line break. + if (!Left.Role) + return false; + auto Comma = Left.Role->lastComma(); + if (!Comma) + return false; + auto Next = Comma->getNextNonComment(); + if (!Next) + return false; + if (!Next->isOneOf(TT_LambdaLSquare, tok::l_brace, tok::caret)) + return true; + } + return false; } @@ -3078,14 +3115,33 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, // Don't wrap between ":" and "!" of a strict prop init ("field!: type;"). if (Left.is(tok::exclaim) && Right.is(tok::colon)) return false; - if (Right.is(Keywords.kw_is)) - return false; + // Look for is type annotations like: + // function f(): a is B { ... } + // Do not break before is in these cases. + if (Right.is(Keywords.kw_is)) { + const FormatToken* Next = Right.getNextNonComment(); + // If `is` is followed by a colon, it's likely that it's a dict key, so + // ignore it for this check. + // For example this is common in Polymer: + // Polymer({ + // is: 'name', + // ... + // }); + if (!Next || !Next->is(tok::colon)) + return false; + } if (Left.is(Keywords.kw_in)) return Style.BreakBeforeBinaryOperators == FormatStyle::BOS_None; if (Right.is(Keywords.kw_in)) return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None; if (Right.is(Keywords.kw_as)) return false; // must not break before as in 'x as type' casts + if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) { + // extends and infer can appear as keywords in conditional types: + // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types + // do not break before them, as the expressions are subject to ASI. + return false; + } if (Left.is(Keywords.kw_as)) return true; if (Left.is(TT_JsNonNullAssertion)) |