Commit 900dee8c authored by Jonathan Coe's avatar Jonathan Coe
Browse files

[clang-format] Do not merge target-name and : for C# attributes

Summary:
Re-use token type `TT_AttributeColon` for C# attribute target colons.

Reviewers: krasimir

Reviewed By: krasimir

Subscribers: MyDeveloperDay, cfe-commits

Tags: #clang-format, #clang

Differential Revision: https://reviews.llvm.org/D75465
parent f9047ede
Loading
Loading
Loading
Loading
+0 −30
Original line number Diff line number Diff line
@@ -76,8 +76,6 @@ void FormatTokenLexer::tryMergePreviousTokens() {
    return;

  if (Style.isCSharp()) {
    if (tryMergeCSharpAttributeAndTarget())
      return;
    if (tryMergeCSharpKeywordVariables())
      return;
    if (tryMergeCSharpStringLiteral())
@@ -284,34 +282,6 @@ const llvm::StringSet<> FormatTokenLexer::CSharpAttributeTargets = {
    "param",    "property", "return", "type",
};

bool FormatTokenLexer::tryMergeCSharpAttributeAndTarget() {
  // Treat '[assembly:' and '[field:' as tokens in their own right.
  if (Tokens.size() < 3)
    return false;

  auto &SquareBracket = *(Tokens.end() - 3);
  auto &Target = *(Tokens.end() - 2);
  auto &Colon = *(Tokens.end() - 1);

  if (!SquareBracket->Tok.is(tok::l_square))
    return false;

  if (CSharpAttributeTargets.find(Target->TokenText) ==
      CSharpAttributeTargets.end())
    return false;

  if (!Colon->Tok.is(tok::colon))
    return false;

  SquareBracket->TokenText =
      StringRef(SquareBracket->TokenText.begin(),
                Colon->TokenText.end() - SquareBracket->TokenText.begin());
  SquareBracket->ColumnWidth += (Target->ColumnWidth + Colon->ColumnWidth);
  Tokens.erase(Tokens.end() - 2);
  Tokens.erase(Tokens.end() - 1);
  return true;
}

bool FormatTokenLexer::tryMergeCSharpDoubleQuestion() {
  if (Tokens.size() < 2)
    return false;
+0 −1
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ private:
  bool tryMergeCSharpDoubleQuestion();
  bool tryMergeCSharpNullConditional();
  bool tryTransformCSharpForEach();
  bool tryMergeCSharpAttributeAndTarget();

  bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);

+19 −10
Original line number Diff line number Diff line
@@ -385,10 +385,10 @@ private:
    if (!AttrTok)
      return false;
    
    // Move past the end of ']'.
    // Allow an attribute to be the only content of a file.
    AttrTok = AttrTok->Next;
    if (!AttrTok)
      return false;
      return true;

    // Limit this to being an access modifier that follows.
    if (AttrTok->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
@@ -460,7 +460,7 @@ private:
                                     Contexts.back().InCpp11AttributeSpecifier;

    // Treat C# Attributes [STAThread] much like C++ attributes [[...]].
    bool IsCSharp11AttributeSpecifier =
    bool IsCSharpAttributeSpecifier =
        isCSharpAttributeSpecifier(*Left) ||
        Contexts.back().InCSharpAttributeSpecifier;

@@ -469,7 +469,8 @@ private:
    bool StartsObjCMethodExpr =
        !IsCppStructuredBinding && !InsideInlineASM && !CppArrayTemplates &&
        Style.isCpp() && !IsCpp11AttributeSpecifier &&
        Contexts.back().CanBeExpression && Left->isNot(TT_LambdaLSquare) &&
        !IsCSharpAttributeSpecifier && 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,
@@ -496,7 +497,7 @@ private:
      } else if (Style.isCpp() && Contexts.back().ContextKind == tok::l_brace &&
                 Parent && Parent->isOneOf(tok::l_brace, tok::comma)) {
        Left->Type = TT_DesignatedInitializerLSquare;
      } else if (IsCSharp11AttributeSpecifier) {
      } else if (IsCSharpAttributeSpecifier) {
        Left->Type = TT_AttributeSquare;
      } else if (CurrentToken->is(tok::r_square) && Parent &&
                 Parent->is(TT_TemplateCloser)) {
@@ -559,13 +560,13 @@ private:

    Contexts.back().ColonIsObjCMethodExpr = StartsObjCMethodExpr;
    Contexts.back().InCpp11AttributeSpecifier = IsCpp11AttributeSpecifier;
    Contexts.back().InCSharpAttributeSpecifier = IsCSharp11AttributeSpecifier;
    Contexts.back().InCSharpAttributeSpecifier = IsCSharpAttributeSpecifier;

    while (CurrentToken) {
      if (CurrentToken->is(tok::r_square)) {
        if (IsCpp11AttributeSpecifier)
          CurrentToken->Type = TT_AttributeSquare;
        if (IsCSharp11AttributeSpecifier)
        if (IsCSharpAttributeSpecifier)
          CurrentToken->Type = TT_AttributeSquare;
        else if (((CurrentToken->Next &&
                   CurrentToken->Next->is(tok::l_paren)) ||
@@ -777,6 +778,10 @@ private:
          break;
        }
      } else if (Style.isCSharp()) {
        if (Contexts.back().InCSharpAttributeSpecifier) {
          Tok->Type = TT_AttributeColon;
          break;
        }
        if (Contexts.back().ContextKind == tok::l_paren) {
          Tok->Type = TT_CSharpNamedArgumentColon;
          break;
@@ -2922,6 +2927,10 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
    if (Left.is(TT_JsFatArrow) || Right.is(TT_JsFatArrow))
      return true;

    // No spaces around attribute target colons
    if (Left.is(TT_AttributeColon) || Right.is(TT_AttributeColon))
      return false;

    // space between type and variable e.g. Dictionary<string,string> foo;
    if (Left.is(TT_TemplateCloser) && Right.is(TT_StartOfName))
      return true;
@@ -3550,8 +3559,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
  const FormatToken &Left = *Right.Previous;
  // Language-specific stuff.
  if (Style.isCSharp()) {
    if (Left.is(TT_CSharpNamedArgumentColon) ||
        Right.is(TT_CSharpNamedArgumentColon))
    if (Left.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon) ||
        Right.isOneOf(TT_CSharpNamedArgumentColon, TT_AttributeColon))
      return false;
  } else if (Style.Language == FormatStyle::LK_Java) {
    if (Left.isOneOf(Keywords.kw_throws, Keywords.kw_extends,