diff options
Diffstat (limited to 'lib/Format/UnwrappedLineParser.cpp')
| -rw-r--r-- | lib/Format/UnwrappedLineParser.cpp | 123 | 
1 files changed, 97 insertions, 26 deletions
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index 3cd3c8f9cdf69..a35e98ae55039 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -1,9 +1,8 @@  //===--- UnwrappedLineParser.cpp - Format C++ code ------------------------===//  // -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception  //  //===----------------------------------------------------------------------===//  /// @@ -173,10 +172,16 @@ class CompoundStatementIndenter {  public:    CompoundStatementIndenter(UnwrappedLineParser *Parser,                              const FormatStyle &Style, unsigned &LineLevel) +      : CompoundStatementIndenter(Parser, LineLevel, +                                  Style.BraceWrapping.AfterControlStatement, +                                  Style.BraceWrapping.IndentBraces) { +  } +  CompoundStatementIndenter(UnwrappedLineParser *Parser, unsigned &LineLevel, +                            bool WrapBrace, bool IndentBrace)        : LineLevel(LineLevel), OldLineLevel(LineLevel) { -    if (Style.BraceWrapping.AfterControlStatement) +    if (WrapBrace)        Parser->addUnwrappedLine(); -    if (Style.BraceWrapping.IndentBraces) +    if (IndentBrace)        ++LineLevel;    }    ~CompoundStatementIndenter() { LineLevel = OldLineLevel; } @@ -482,7 +487,7 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {        break;      case tok::identifier:        if (!Tok->is(TT_StatementMacro)) -          break; +        break;        LLVM_FALLTHROUGH;      case tok::at:      case tok::semi: @@ -625,7 +630,7 @@ static bool isIIFE(const UnwrappedLine &Line,  static bool ShouldBreakBeforeBrace(const FormatStyle &Style,                                     const FormatToken &InitialToken) { -  if (InitialToken.is(tok::kw_namespace)) +  if (InitialToken.isOneOf(tok::kw_namespace, TT_NamespaceMacro))      return Style.BraceWrapping.AfterNamespace;    if (InitialToken.is(tok::kw_class))      return Style.BraceWrapping.AfterClass; @@ -656,6 +661,7 @@ void UnwrappedLineParser::parseChildBlock() {  void UnwrappedLineParser::parsePPDirective() {    assert(FormatTok->Tok.is(tok::hash) && "'#' expected");    ScopedMacroState MacroState(*Line, Tokens, FormatTok); +    nextToken();    if (!FormatTok->Tok.getIdentifierInfo()) { @@ -799,7 +805,7 @@ void UnwrappedLineParser::parsePPEndIf() {  void UnwrappedLineParser::parsePPDefine() {    nextToken(); -  if (FormatTok->Tok.getKind() != tok::identifier) { +  if (!FormatTok->Tok.getIdentifierInfo()) {      IncludeGuard = IG_Rejected;      IncludeGuardToken = nullptr;      parsePPUnknown(); @@ -824,7 +830,7 @@ void UnwrappedLineParser::parsePPDefine() {            FormatTok->WhitespaceRange.getEnd()) {      parseParens();    } -  if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash) +  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)      Line->Level += PPBranchLevel + 1;    addUnwrappedLine();    ++Line->Level; @@ -841,7 +847,7 @@ void UnwrappedLineParser::parsePPUnknown() {    do {      nextToken();    } while (!eof()); -  if (Style.IndentPPDirectives == FormatStyle::PPDIS_AfterHash) +  if (Style.IndentPPDirectives != FormatStyle::PPDIS_None)      Line->Level += PPBranchLevel + 1;    addUnwrappedLine();  } @@ -1000,7 +1006,7 @@ void UnwrappedLineParser::parseStructuralElement() {    case tok::kw_protected:    case tok::kw_private:      if (Style.Language == FormatStyle::LK_Java || -        Style.Language == FormatStyle::LK_JavaScript) +        Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp())        nextToken();      else        parseAccessSpecifier(); @@ -1116,6 +1122,10 @@ void UnwrappedLineParser::parseStructuralElement() {        parseStatementMacro();        return;      } +    if (Style.isCpp() && FormatTok->is(TT_NamespaceMacro)) { +      parseNamespace(); +      return; +    }      // In all other cases, parse the declaration.      break;    default: @@ -1167,8 +1177,8 @@ void UnwrappedLineParser::parseStructuralElement() {        case tok::objc_synchronized:          nextToken();          if (FormatTok->Tok.is(tok::l_paren)) -           // Skip synchronization object -           parseParens(); +          // Skip synchronization object +          parseParens();          if (FormatTok->Tok.is(tok::l_brace)) {            if (Style.BraceWrapping.AfterControlStatement)              addUnwrappedLine(); @@ -1214,9 +1224,9 @@ void UnwrappedLineParser::parseStructuralElement() {        // parseRecord falls through and does not yet add an unwrapped line as a        // record declaration or definition can start a structural element.        parseRecord(); -      // This does not apply for Java and JavaScript. +      // This does not apply for Java, JavaScript and C#.        if (Style.Language == FormatStyle::LK_Java || -          Style.Language == FormatStyle::LK_JavaScript) { +          Style.Language == FormatStyle::LK_JavaScript || Style.isCSharp()) {          if (FormatTok->is(tok::semi))            nextToken();          addUnwrappedLine(); @@ -1329,10 +1339,15 @@ void UnwrappedLineParser::parseStructuralElement() {        // See if the following token should start a new unwrapped line.        StringRef Text = FormatTok->TokenText;        nextToken(); -      if (Line->Tokens.size() == 1 && -          // JS doesn't have macros, and within classes colons indicate fields, -          // not labels. -          Style.Language != FormatStyle::LK_JavaScript) { + +      // JS doesn't have macros, and within classes colons indicate fields, not +      // labels. +      if (Style.Language == FormatStyle::LK_JavaScript) +        break; + +      TokenCount = Line->Tokens.size(); +      if (TokenCount == 1 || +          (TokenCount == 2 && Line->Tokens.front().Tok->is(tok::comment))) {          if (FormatTok->Tok.is(tok::colon) && !Line->MustBeDeclaration) {            Line->Tokens.begin()->Tok->MustBreakBefore = true;            parseLabel(); @@ -1402,6 +1417,8 @@ bool UnwrappedLineParser::tryToParseLambda() {    if (!tryToParseLambdaIntroducer())      return false; +  bool SeenArrow = false; +    while (FormatTok->isNot(tok::l_brace)) {      if (FormatTok->isSimpleTypeSpecifier()) {        nextToken(); @@ -1423,16 +1440,57 @@ bool UnwrappedLineParser::tryToParseLambda() {      case tok::numeric_constant:      case tok::coloncolon:      case tok::kw_mutable: +    case tok::kw_noexcept:        nextToken();        break; +    // Specialization of a template with an integer parameter can contain +    // arithmetic, logical, comparison and ternary operators. +    // +    // FIXME: This also accepts sequences of operators that are not in the scope +    // of a template argument list. +    // +    // In a C++ lambda a template type can only occur after an arrow. We use +    // this as an heuristic to distinguish between Objective-C expressions +    // followed by an `a->b` expression, such as: +    // ([obj func:arg] + a->b) +    // Otherwise the code below would parse as a lambda. +    case tok::plus: +    case tok::minus: +    case tok::exclaim: +    case tok::tilde: +    case tok::slash: +    case tok::percent: +    case tok::lessless: +    case tok::pipe: +    case tok::pipepipe: +    case tok::ampamp: +    case tok::caret: +    case tok::equalequal: +    case tok::exclaimequal: +    case tok::greaterequal: +    case tok::lessequal: +    case tok::question: +    case tok::colon: +    case tok::kw_true: +    case tok::kw_false: +      if (SeenArrow) { +        nextToken(); +        break; +      } +      return true;      case tok::arrow: +      // This might or might not actually be a lambda arrow (this could be an +      // ObjC method invocation followed by a dereferencing arrow). We might +      // reset this back to TT_Unknown in TokenAnnotator.        FormatTok->Type = TT_LambdaArrow; +      SeenArrow = true;        nextToken();        break;      default:        return true;      }    } +  FormatTok->Type = TT_LambdaLBrace;    LSquare.Type = TT_LambdaLSquare;    parseChildBlock();    return true; @@ -1806,12 +1864,17 @@ void UnwrappedLineParser::parseTryCatch() {  }  void UnwrappedLineParser::parseNamespace() { -  assert(FormatTok->Tok.is(tok::kw_namespace) && "'namespace' expected"); +  assert(FormatTok->isOneOf(tok::kw_namespace, TT_NamespaceMacro) && +         "'namespace' expected");    const FormatToken &InitialToken = *FormatTok;    nextToken(); -  while (FormatTok->isOneOf(tok::identifier, tok::coloncolon)) -    nextToken(); +  if (InitialToken.is(TT_NamespaceMacro)) { +    parseParens(); +  } else { +    while (FormatTok->isOneOf(tok::identifier, tok::coloncolon)) +      nextToken(); +  }    if (FormatTok->Tok.is(tok::l_brace)) {      if (ShouldBreakBeforeBrace(Style, InitialToken))        addUnwrappedLine(); @@ -1907,7 +1970,9 @@ void UnwrappedLineParser::parseLabel() {    if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))      --Line->Level;    if (CommentsBeforeNextToken.empty() && FormatTok->Tok.is(tok::l_brace)) { -    CompoundStatementIndenter Indenter(this, Style, Line->Level); +    CompoundStatementIndenter Indenter(this, Line->Level, +                                       Style.BraceWrapping.AfterCaseLabel, +                                       Style.BraceWrapping.IndentBraces);      parseBlock(/*MustBeDeclaration=*/false);      if (FormatTok->Tok.is(tok::kw_break)) {        if (Style.BraceWrapping.AfterControlStatement) @@ -1976,6 +2041,10 @@ bool UnwrappedLineParser::parseEnum() {        FormatTok->isOneOf(tok::colon, tok::question))      return false; +  // In protobuf, "enum" can be used as a field name. +  if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal)) +    return false; +    // Eat up enum class ...    if (FormatTok->Tok.is(tok::kw_class) || FormatTok->Tok.is(tok::kw_struct))      nextToken(); @@ -2347,8 +2416,7 @@ void UnwrappedLineParser::parseJavaScriptEs6ImportExport() {    }  } -void UnwrappedLineParser::parseStatementMacro() -{ +void UnwrappedLineParser::parseStatementMacro() {    nextToken();    if (FormatTok->is(tok::l_paren))      parseParens(); @@ -2631,6 +2699,9 @@ void UnwrappedLineParser::readToken(int LevelDifference) {        // Comments stored before the preprocessor directive need to be output        // before the preprocessor directive, at the same level as the        // preprocessor directive, as we consider them to apply to the directive. +      if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash && +          PPBranchLevel > 0) +        Line->Level += PPBranchLevel;        flushComments(isOnNewLine(*FormatTok));        parsePPDirective();      }  | 
