diff options
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Format/TokenAnnotator.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Format/TokenAnnotator.cpp | 231 |
1 files changed, 170 insertions, 61 deletions
diff --git a/gnu/llvm/tools/clang/lib/Format/TokenAnnotator.cpp b/gnu/llvm/tools/clang/lib/Format/TokenAnnotator.cpp index 8fbb43b7996..4a90522e6e3 100644 --- a/gnu/llvm/tools/clang/lib/Format/TokenAnnotator.cpp +++ b/gnu/llvm/tools/clang/lib/Format/TokenAnnotator.cpp @@ -42,11 +42,24 @@ public: private: bool parseAngle() { - if (!CurrentToken) + if (!CurrentToken || !CurrentToken->Previous) + return false; + if (NonTemplateLess.count(CurrentToken->Previous)) return false; + + const FormatToken& Previous = *CurrentToken->Previous; + if (Previous.Previous) { + if (Previous.Previous->Tok.isLiteral()) + return false; + if (Previous.Previous->is(tok::r_paren) && Contexts.size() > 1 && + (!Previous.Previous->MatchingParen || + !Previous.Previous->MatchingParen->is(TT_OverloadedOperatorLParen))) + return false; + } + FormatToken *Left = CurrentToken->Previous; Left->ParentBracket = Contexts.back().ContextKind; - ScopedContextCreator ContextCreator(*this, tok::less, 10); + ScopedContextCreator ContextCreator(*this, tok::less, 12); // If this angle is in the context of an expression, we need to be more // hesitant to detect it as opening template parameters. @@ -121,6 +134,10 @@ private: if (Left->is(TT_OverloadedOperatorLParen)) { Contexts.back().IsExpression = false; + } else if (Style.Language == FormatStyle::LK_JavaScript && + Line.startsWith(Keywords.kw_type, tok::identifier)) { + // type X = (...); + Contexts.back().IsExpression = false; } else if (Left->Previous && (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_decltype, tok::kw_if, tok::kw_while, tok::l_paren, @@ -128,6 +145,16 @@ private: Left->Previous->is(TT_BinaryOperator))) { // static_assert, if and while usually contain expressions. Contexts.back().IsExpression = true; + } else if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous && + (Left->Previous->is(Keywords.kw_function) || + (Left->Previous->endsSequence(tok::identifier, + Keywords.kw_function)))) { + // function(...) or function f(...) + Contexts.back().IsExpression = false; + } else if (Style.Language == FormatStyle::LK_JavaScript && Left->Previous && + Left->Previous->is(TT_JsTypeColon)) { + // let x: (SomeType); + Contexts.back().IsExpression = false; } else if (Left->Previous && Left->Previous->is(tok::r_square) && Left->Previous->MatchingParen && Left->Previous->MatchingParen->is(TT_LambdaLSquare)) { @@ -159,8 +186,8 @@ private: Left->Type = TT_ObjCMethodExpr; } - bool MightBeFunctionType = CurrentToken->isOneOf(tok::star, tok::amp) && - !Contexts[Contexts.size() - 2].IsExpression; + bool MightBeFunctionType = !Contexts[Contexts.size() - 2].IsExpression; + bool ProbablyFunctionType = CurrentToken->isOneOf(tok::star, tok::amp); bool HasMultipleLines = false; bool HasMultipleParametersOnALine = false; bool MightBeObjCForRangeLoop = @@ -187,14 +214,15 @@ private: if (CurrentToken->Previous->is(TT_PointerOrReference) && CurrentToken->Previous->Previous->isOneOf(tok::l_paren, tok::coloncolon)) - MightBeFunctionType = true; + ProbablyFunctionType = true; + if (CurrentToken->is(tok::comma)) + MightBeFunctionType = false; if (CurrentToken->Previous->is(TT_BinaryOperator)) Contexts.back().IsExpression = true; if (CurrentToken->is(tok::r_paren)) { - if (MightBeFunctionType && CurrentToken->Next && + if (MightBeFunctionType && ProbablyFunctionType && CurrentToken->Next && (CurrentToken->Next->is(tok::l_paren) || - (CurrentToken->Next->is(tok::l_square) && - Line.MustBeDeclaration))) + (CurrentToken->Next->is(tok::l_square) && Line.MustBeDeclaration))) Left->Type = TT_FunctionTypeLParen; Left->MatchingParen = CurrentToken; CurrentToken->MatchingParen = Left; @@ -299,9 +327,9 @@ private: Left->Type = TT_JsComputedPropertyName; } else if (Style.Language == FormatStyle::LK_Proto || (Parent && - Parent->isOneOf(TT_BinaryOperator, tok::at, tok::comma, - tok::l_paren, tok::l_square, tok::question, - tok::colon, tok::kw_return, + Parent->isOneOf(TT_BinaryOperator, TT_TemplateCloser, tok::at, + tok::comma, tok::l_paren, tok::l_square, + tok::question, tok::colon, tok::kw_return, // Should only be relevant to JavaScript: tok::kw_default))) { Left->Type = TT_ArrayInitializerLSquare; @@ -396,7 +424,8 @@ private: (!Contexts.back().ColonIsDictLiteral || Style.Language != FormatStyle::LK_Cpp)) || Style.Language == FormatStyle::LK_Proto) && - Previous->Tok.getIdentifierInfo()) + (Previous->Tok.getIdentifierInfo() || + Previous->is(tok::string_literal))) Previous->Type = TT_SelectorName; if (CurrentToken->is(tok::colon) || Style.Language == FormatStyle::LK_JavaScript) @@ -410,7 +439,7 @@ private: } void updateParameterCount(FormatToken *Left, FormatToken *Current) { - if (Current->is(tok::l_brace) && !Current->is(TT_DictLiteral)) + if (Current->is(tok::l_brace) && Current->BlockKind == BK_Block) ++Left->BlockParameterCount; if (Current->is(tok::comma)) { ++Left->ParameterCount; @@ -491,7 +520,7 @@ private: Tok->Type = TT_BitFieldColon; } else if (Contexts.size() == 1 && !Line.First->isOneOf(tok::kw_enum, tok::kw_case)) { - if (Tok->Previous->is(tok::r_paren)) + if (Tok->Previous->isOneOf(tok::r_paren, tok::kw_noexcept)) Tok->Type = TT_CtorInitializerColon; else Tok->Type = TT_InheritanceColon; @@ -504,6 +533,14 @@ private: Tok->Type = TT_InlineASMColon; } break; + case tok::pipe: + case tok::amp: + // | and & in declarations/type expressions represent union and + // intersection types, respectively. + if (Style.Language == FormatStyle::LK_JavaScript && + !Contexts.back().IsExpression) + Tok->Type = TT_JsTypeOperator; + break; case tok::kw_if: case tok::kw_while: if (CurrentToken && CurrentToken->is(tok::l_paren)) { @@ -513,6 +550,9 @@ private: } break; case tok::kw_for: + if (Style.Language == FormatStyle::LK_JavaScript && Tok->Previous && + Tok->Previous->is(tok::period)) + break; Contexts.back().ColonIsForRangeExpr = true; next(); if (!parseParens()) @@ -550,11 +590,7 @@ private: return false; break; case tok::less: - if (!NonTemplateLess.count(Tok) && - (!Tok->Previous || - (!Tok->Previous->Tok.isLiteral() && - !(Tok->Previous->is(tok::r_paren) && Contexts.size() > 1))) && - parseAngle()) { + if (parseAngle()) { Tok->Type = TT_TemplateOpener; } else { Tok->Type = TT_BinaryOperator; @@ -603,7 +639,7 @@ private: } // Declarations cannot be conditional expressions, this can only be part // of a type declaration. - if (Line.MustBeDeclaration && + if (Line.MustBeDeclaration && !Contexts.back().IsExpression && Style.Language == FormatStyle::LK_JavaScript) break; parseConditional(); @@ -666,10 +702,24 @@ private: } LineType parsePreprocessorDirective() { + bool IsFirstToken = CurrentToken->IsFirst; LineType Type = LT_PreprocessorDirective; next(); if (!CurrentToken) return Type; + + if (Style.Language == FormatStyle::LK_JavaScript && IsFirstToken) { + // JavaScript files can contain shebang lines of the form: + // #!/usr/bin/env node + // Treat these like C++ #include directives. + while (CurrentToken) { + // Tokens cannot be comments here. + CurrentToken->Type = TT_ImplicitStringLiteral; + next(); + } + return LT_ImportStatement; + } + if (CurrentToken->Tok.is(tok::numeric_constant)) { CurrentToken->SpacesRequiredBefore = 1; return Type; @@ -745,11 +795,29 @@ public: bool KeywordVirtualFound = false; bool ImportStatement = false; + + // import {...} from '...'; + if (Style.Language == FormatStyle::LK_JavaScript && + CurrentToken->is(Keywords.kw_import)) + ImportStatement = true; + while (CurrentToken) { if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; - if (isImportStatement(*CurrentToken)) - ImportStatement = true; + if (Style.Language == FormatStyle::LK_JavaScript) { + // export {...} from '...'; + // An export followed by "from 'some string';" is a re-export from + // another module identified by a URI and is treated as a + // LT_ImportStatement (i.e. prevent wraps on it for long URIs). + // Just "export {...};" or "export class ..." should not be treated as + // an import in this sense. + if (Line.First->is(tok::kw_export) && + CurrentToken->is(Keywords.kw_from) && CurrentToken->Next && + CurrentToken->Next->isStringLiteral()) + ImportStatement = true; + if (isClosureImportStatement(*CurrentToken)) + ImportStatement = true; + } if (!consumeToken()) return LT_Invalid; } @@ -769,15 +837,15 @@ public: } private: - bool isImportStatement(const FormatToken &Tok) { + bool isClosureImportStatement(const FormatToken &Tok) { // FIXME: Closure-library specific stuff should not be hard-coded but be // configurable. - return Style.Language == FormatStyle::LK_JavaScript && - Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) && + return Tok.TokenText == "goog" && Tok.Next && Tok.Next->is(tok::period) && Tok.Next->Next && (Tok.Next->Next->TokenText == "module" || Tok.Next->Next->TokenText == "provide" || Tok.Next->Next->TokenText == "require" || - Tok.Next->Next->TokenText == "setTestOnly") && + Tok.Next->Next->TokenText == "setTestOnly" || + Tok.Next->Next->TokenText == "forwardDeclare") && Tok.Next->Next->Next && Tok.Next->Next->Next->is(tok::l_paren); } @@ -853,6 +921,9 @@ private: void modifyContext(const FormatToken &Current) { if (Current.getPrecedence() == prec::Assignment && !Line.First->isOneOf(tok::kw_template, tok::kw_using, tok::kw_return) && + // Type aliases use `type X = ...;` in TypeScript. + !(Style.Language == FormatStyle::LK_JavaScript && + Line.startsWith(Keywords.kw_type, tok::identifier)) && (!Current.Previous || Current.Previous->isNot(tok::kw_operator))) { Contexts.back().IsExpression = true; if (!Line.startsWith(TT_UnaryOperator)) { @@ -882,17 +953,17 @@ private: Contexts.back().IsExpression = false; } else if (Current.is(TT_LambdaArrow) || Current.is(Keywords.kw_assert)) { Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java; + } else if (Current.Previous && + Current.Previous->is(TT_CtorInitializerColon)) { + Contexts.back().IsExpression = true; + Contexts.back().InCtorInitializer = true; } else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) { for (FormatToken *Previous = Current.Previous; Previous && Previous->isOneOf(tok::star, tok::amp); Previous = Previous->Previous) Previous->Type = TT_PointerOrReference; - if (Line.MustBeDeclaration) - Contexts.back().IsExpression = Contexts.front().InCtorInitializer; - } else if (Current.Previous && - Current.Previous->is(TT_CtorInitializerColon)) { - Contexts.back().IsExpression = true; - Contexts.back().InCtorInitializer = true; + if (Line.MustBeDeclaration && !Contexts.front().InCtorInitializer) + Contexts.back().IsExpression = false; } else if (Current.is(tok::kw_new)) { Contexts.back().CanBeExpression = false; } else if (Current.isOneOf(tok::semi, tok::exclaim)) { @@ -938,7 +1009,7 @@ private: Current.Type = TT_UnaryOperator; } else if (Current.is(tok::question)) { if (Style.Language == FormatStyle::LK_JavaScript && - Line.MustBeDeclaration) { + Line.MustBeDeclaration && !Contexts.back().IsExpression) { // In JavaScript, `interface X { foo?(): bar; }` is an optional method // on the interface, not a ternary expression. Current.Type = TT_JsTypeOptionalQuestion; @@ -964,7 +1035,8 @@ private: Current.Type = TT_CastRParen; if (Current.MatchingParen && Current.Next && !Current.Next->isBinaryOperator() && - !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace)) + !Current.Next->isOneOf(tok::semi, tok::colon, tok::l_brace, + tok::period, tok::arrow, tok::coloncolon)) if (FormatToken *BeforeParen = Current.MatchingParen->Previous) if (BeforeParen->is(tok::identifier) && BeforeParen->TokenText == BeforeParen->TokenText.upper() && @@ -1035,6 +1107,9 @@ private: if (Tok.Previous->isOneOf(TT_LeadingJavaAnnotation, Keywords.kw_instanceof)) return false; + if (Style.Language == FormatStyle::LK_JavaScript && + Tok.Previous->is(Keywords.kw_in)) + return false; // Skip "const" as it does not have an influence on whether this is a name. FormatToken *PreviousNotConst = Tok.Previous; @@ -1078,7 +1153,7 @@ private: FormatToken *LeftOfParens = Tok.MatchingParen->getPreviousNonComment(); if (LeftOfParens) { - // If there is an opening parenthesis left of the current parentheses, + // If there is a closing parenthesis left of the current parentheses, // look past it as these might be chained casts. if (LeftOfParens->is(tok::r_paren)) { if (!LeftOfParens->MatchingParen || @@ -1097,7 +1172,7 @@ private: // Certain other tokens right before the parentheses are also signals that // this cannot be a cast. if (LeftOfParens->isOneOf(tok::at, tok::r_square, TT_OverloadedOperator, - TT_TemplateCloser)) + TT_TemplateCloser, tok::ellipsis)) return false; } @@ -1131,9 +1206,9 @@ private: if (!LeftOfParens) return false; - // If the following token is an identifier, this is a cast. All cases where - // this can be something else are handled above. - if (Tok.Next->is(tok::identifier)) + // If the following token is an identifier or 'this', this is a cast. All + // cases where this can be something else are handled above. + if (Tok.Next->isOneOf(tok::identifier, tok::kw_this)) return true; if (!Tok.Next->Next) @@ -1390,11 +1465,15 @@ private: Style.Language == FormatStyle::LK_JavaScript) && Current->is(Keywords.kw_instanceof)) return prec::Relational; + if (Style.Language == FormatStyle::LK_JavaScript && + Current->is(Keywords.kw_in)) + return prec::Relational; if (Current->is(TT_BinaryOperator) || Current->is(tok::comma)) return Current->getPrecedence(); if (Current->isOneOf(tok::period, tok::arrow)) return PrecedenceArrowAndPeriod; - if (Style.Language == FormatStyle::LK_Java && + if ((Style.Language == FormatStyle::LK_Java || + Style.Language == FormatStyle::LK_JavaScript) && Current->isOneOf(Keywords.kw_extends, Keywords.kw_implements, Keywords.kw_throws)) return 0; @@ -1508,7 +1587,8 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) { // This function heuristically determines whether 'Current' starts the name of a // function declaration. -static bool isFunctionDeclarationName(const FormatToken &Current) { +static bool isFunctionDeclarationName(const FormatToken &Current, + const AnnotatedLine &Line) { auto skipOperatorName = [](const FormatToken* Next) -> const FormatToken* { for (; Next; Next = Next->Next) { if (Next->is(TT_OverloadedOperatorLParen)) @@ -1528,6 +1608,7 @@ static bool isFunctionDeclarationName(const FormatToken &Current) { return nullptr; }; + // Find parentheses of parameter list. const FormatToken *Next = Current.Next; if (Current.is(tok::kw_operator)) { if (Current.Previous && Current.Previous->is(tok::coloncolon)) @@ -1557,14 +1638,22 @@ static bool isFunctionDeclarationName(const FormatToken &Current) { } } - if (!Next || !Next->is(tok::l_paren)) + // Check whether parameter list can be long to a function declaration. + if (!Next || !Next->is(tok::l_paren) || !Next->MatchingParen) return false; + // If the lines ends with "{", this is likely an function definition. + if (Line.Last->is(tok::l_brace)) + return true; if (Next->Next == Next->MatchingParen) + return true; // Empty parentheses. + // If there is an &/&& after the r_paren, this is likely a function. + if (Next->MatchingParen->Next && + Next->MatchingParen->Next->is(TT_PointerOrReference)) return true; for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen; Tok = Tok->Next) { if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() || - Tok->isOneOf(TT_PointerOrReference, TT_StartOfName)) + Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) return true; if (Tok->isOneOf(tok::l_brace, tok::string_literal, TT_ObjCMethodExpr) || Tok->Tok.isLiteral()) @@ -1610,7 +1699,7 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) { FormatToken *Current = Line.First->Next; bool InFunctionDecl = Line.MightBeFunctionDecl; while (Current) { - if (isFunctionDeclarationName(*Current)) + if (isFunctionDeclarationName(*Current, Line)) Current->Type = TT_FunctionDeclarationName; if (Current->is(TT_LineComment)) { if (Current->Previous->BlockKind == BK_BracedInit && @@ -1736,7 +1825,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, if (Style.Language == FormatStyle::LK_Proto) return 1; if (Left.is(tok::r_square)) - return 25; + return 200; // Slightly prefer formatting local lambda definitions like functions. if (Right.is(TT_LambdaLSquare) && Left.is(tok::equal)) return 35; @@ -1768,6 +1857,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, return 500; if (Left.isOneOf(tok::kw_class, tok::kw_struct)) return 5000; + if (Left.is(tok::comment)) + return 1000; if (Left.isOneOf(TT_RangeBasedForLoopColon, TT_InheritanceColon)) return 2; @@ -1910,15 +2001,14 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, if (Left.is(tok::less) || Right.isOneOf(tok::greater, tok::less)) return false; if (Right.is(tok::ellipsis)) - return Left.Tok.isLiteral(); + return Left.Tok.isLiteral() || (Left.is(tok::identifier) && Left.Previous && + Left.Previous->is(tok::kw_case)); if (Left.is(tok::l_square) && Right.is(tok::amp)) return false; if (Right.is(TT_PointerOrReference)) - return (Left.is(tok::r_paren) && Left.MatchingParen && - (Left.MatchingParen->is(TT_OverloadedOperatorLParen) || - (Left.MatchingParen->Previous && - Left.MatchingParen->Previous->is(TT_FunctionDeclarationName)))) || - (Left.Tok.isLiteral() || + return (Left.is(tok::r_paren) && Line.MightBeFunctionDecl) || + (Left.Tok.isLiteral() || (Left.is(tok::kw_const) && Left.Previous && + Left.Previous->is(tok::r_paren)) || (!Left.isOneOf(TT_PointerOrReference, tok::l_paren) && (Style.PointerAlignment != FormatStyle::PAS_Left || Line.IsMultiVariableDeclStmt))); @@ -2021,8 +2111,14 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, Left.isOneOf(Keywords.kw_returns, Keywords.kw_option)) return true; } else if (Style.Language == FormatStyle::LK_JavaScript) { - if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, TT_JsFatArrow, - Keywords.kw_in)) + if (Left.is(TT_JsFatArrow)) + return true; + if (Right.is(tok::star) && + Left.isOneOf(Keywords.kw_function, Keywords.kw_yield)) + return false; + if (Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in, + Keywords.kw_of, tok::kw_const) && + (!Left.Previous || !Left.Previous->is(tok::period))) return true; if (Left.is(tok::kw_default) && Left.Previous && Left.Previous->is(tok::kw_export)) @@ -2031,6 +2127,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, return true; if (Right.isOneOf(TT_JsTypeColon, TT_JsTypeOptionalQuestion)) return false; + if (Left.is(TT_JsTypeOperator) || Right.is(TT_JsTypeOperator)) + return false; if ((Left.is(tok::l_brace) || Right.is(tok::r_brace)) && Line.First->isOneOf(Keywords.kw_import, tok::kw_export)) return false; @@ -2043,6 +2141,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, // locations that should have whitespace following are identified by the // above set of follower tokens. return false; + // Postfix non-null assertion operator, as in `foo!.bar()`. + if (Right.is(tok::exclaim) && (Left.isOneOf(tok::identifier, tok::r_paren, + tok::r_square, tok::r_brace) || + Left.Tok.isLiteral())) + return false; } else if (Style.Language == FormatStyle::LK_Java) { if (Left.is(tok::r_square) && Right.is(tok::l_brace)) return true; @@ -2111,10 +2214,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (!Style.SpaceBeforeAssignmentOperators && Right.getPrecedence() == prec::Assignment) return false; - if (Right.is(tok::coloncolon) && Left.isNot(tok::l_brace)) + if (Right.is(tok::coloncolon) && !Left.isOneOf(tok::l_brace, tok::comment)) return (Left.is(TT_TemplateOpener) && Style.Standard == FormatStyle::LS_Cpp03) || - !(Left.isOneOf(tok::identifier, tok::l_paren, tok::r_paren) || + !(Left.isOneOf(tok::identifier, tok::l_paren, tok::r_paren, + tok::l_square) || Left.isOneOf(TT_TemplateCloser, TT_TemplateOpener)); if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser))) return Style.SpacesInAngles; @@ -2152,8 +2256,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, 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)) + if (Right.is(tok::string_literal) && Left.is(tok::plus) && Left.Previous && + Left.Previous->is(tok::string_literal)) return true; if (Left.is(TT_DictLiteral) && Left.is(tok::l_brace) && Line.Level == 0 && Left.Previous && Left.Previous->is(tok::equal) && @@ -2239,9 +2343,6 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line, return (Line.startsWith(tok::kw_enum) && Style.BraceWrapping.AfterEnum) || (Line.startsWith(tok::kw_class) && Style.BraceWrapping.AfterClass) || (Line.startsWith(tok::kw_struct) && Style.BraceWrapping.AfterStruct); - if (Style.Language == FormatStyle::LK_Proto && Left.isNot(tok::l_brace) && - Right.is(TT_SelectorName)) - return true; if (Left.is(TT_ObjCBlockLBrace) && !Style.AllowShortBlocksOnASingleLine) return true; @@ -2268,12 +2369,20 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, Keywords.kw_implements)) return true; } else if (Style.Language == FormatStyle::LK_JavaScript) { + if (Left.is(tok::kw_return)) + return false; // Otherwise a semicolon is inserted. if (Left.is(TT_JsFatArrow) && Right.is(tok::l_brace)) return false; if (Left.is(TT_JsTypeColon)) return true; if (Right.NestingLevel == 0 && Right.is(Keywords.kw_is)) 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 (Left.is(tok::at)) @@ -2390,7 +2499,7 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, Left.getPrecedence() == prec::Assignment)) return true; return Left.isOneOf(tok::comma, tok::coloncolon, tok::semi, tok::l_brace, - tok::kw_class, tok::kw_struct) || + tok::kw_class, tok::kw_struct, tok::comment) || Right.isMemberAccess() || Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow, tok::lessless, tok::colon, tok::l_square, tok::at) || |
