sstwcw created this revision.
sstwcw added a reviewer: clang-format.
Herald added a project: All.
sstwcw requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

After all these years, having the two functions now serves to confuse
people.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D121755

Files:
  clang/lib/Format/TokenAnnotator.cpp
  clang/lib/Format/TokenAnnotator.h

Index: clang/lib/Format/TokenAnnotator.h
===================================================================
--- clang/lib/Format/TokenAnnotator.h
+++ clang/lib/Format/TokenAnnotator.h
@@ -169,9 +169,6 @@
 
   bool spaceRequiredBeforeParens(const FormatToken &Right) const;
 
-  bool spaceRequiredBetween(const AnnotatedLine &Line, const FormatToken &Left,
-                            const FormatToken &Right);
-
   bool spaceRequiredBefore(const AnnotatedLine &Line, const FormatToken &Right);
 
   bool mustBreakBefore(const AnnotatedLine &Line, const FormatToken &Right);
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3066,9 +3066,411 @@
   return false;
 }
 
-bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
-                                          const FormatToken &Left,
-                                          const FormatToken &Right) {
+bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
+                                         const FormatToken &Right) {
+  assert(Right.Previous);
+  const FormatToken &Left = *Right.Previous;
+
+  // If the token is finalized don't touch it (as it could be in a
+  // clang-format-off section).
+  if (Left.Finalized)
+    return Right.hasWhitespaceBefore();
+
+  if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
+    return true; // Never ever merge two identifiers.
+
+  // Leave a space between * and /* to avoid C4138 `comment end` found outside
+  // of comment.
+  if (Left.is(tok::star) && Right.is(tok::comment))
+    return true;
+
+  if (Style.isCpp()) {
+    // Space between import <iostream>.
+    // or import .....;
+    if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))
+      return true;
+    // Space between `module :` and `import :`.
+    if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&
+        Right.is(TT_ModulePartitionColon))
+      return true;
+    // No space between import foo:bar but keep a space between import :bar;
+    if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))
+      return false;
+    // No space between :bar;
+    if (Left.is(TT_ModulePartitionColon) &&
+        Right.isOneOf(tok::identifier, tok::kw_private))
+      return false;
+    if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&
+        Line.First->is(Keywords.kw_import))
+      return false;
+    // Space in __attribute__((attr)) ::type.
+    if (Left.is(TT_AttributeParen) && Right.is(tok::coloncolon))
+      return true;
+
+    if (Left.is(tok::kw_operator))
+      return Right.is(tok::coloncolon);
+    if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&
+        !Left.opensScope() && Style.SpaceBeforeCpp11BracedList)
+      return true;
+    if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) &&
+        Right.is(TT_TemplateOpener))
+      return true;
+  } else if (Style.Language == FormatStyle::LK_Proto ||
+             Style.Language == FormatStyle::LK_TextProto) {
+    if (Right.is(tok::period) &&
+        Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
+                     Keywords.kw_repeated, Keywords.kw_extend))
+      return true;
+    if (Right.is(tok::l_paren) &&
+        Left.isOneOf(Keywords.kw_returns, Keywords.kw_option))
+      return true;
+    if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))
+      return true;
+    // Slashes occur in text protocol extension syntax: [type/type] { ... }.
+    if (Left.is(tok::slash) || Right.is(tok::slash))
+      return false;
+    if (Left.MatchingParen &&
+        Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&
+        Right.isOneOf(tok::l_brace, tok::less))
+      return !Style.Cpp11BracedListStyle;
+    // A percent is probably part of a formatting specification, such as %lld.
+    if (Left.is(tok::percent))
+      return false;
+    // Preserve the existence of a space before a percent for cases like 0x%04x
+    // and "%d %d"
+    if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
+      return Right.hasWhitespaceBefore();
+  } else if (Style.isJson()) {
+    if (Right.is(tok::colon))
+      return false;
+  } else if (Style.isCSharp()) {
+    // Require spaces around '{' and  before '}' unless they appear in
+    // interpolated strings. Interpolated strings are merged into a single token
+    // so cannot have spaces inserted by this function.
+
+    // No space between 'this' and '['
+    if (Left.is(tok::kw_this) && Right.is(tok::l_square))
+      return false;
+
+    // No space between 'new' and '('
+    if (Left.is(tok::kw_new) && Right.is(tok::l_paren))
+      return false;
+
+    // Space before { (including space within '{ {').
+    if (Right.is(tok::l_brace))
+      return true;
+
+    // Spaces inside braces.
+    if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace))
+      return true;
+
+    if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace))
+      return true;
+
+    // Spaces around '=>'.
+    if (Left.is(TT_FatArrow) || Right.is(TT_FatArrow))
+      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;
+
+    // spaces inside square brackets.
+    if (Left.is(tok::l_square) || Right.is(tok::r_square))
+      return Style.SpacesInSquareBrackets;
+
+    // No space before ? in nullable types.
+    if (Right.is(TT_CSharpNullable))
+      return false;
+
+    // No space before null forgiving '!'.
+    if (Right.is(TT_NonNullAssertion))
+      return false;
+
+    // No space between consecutive commas '[,,]'.
+    if (Left.is(tok::comma) && Right.is(tok::comma))
+      return false;
+
+    // space after var in `var (key, value)`
+    if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren))
+      return true;
+
+    // space between keywords and paren e.g. "using ("
+    if (Right.is(tok::l_paren))
+      if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when,
+                       Keywords.kw_lock))
+        return Style.SpaceBeforeParensOptions.AfterControlStatements ||
+               spaceRequiredBeforeParens(Right);
+
+    // space between method modifier and opening parenthesis of a tuple return
+    // type
+    if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
+                     tok::kw_virtual, tok::kw_extern, tok::kw_static,
+                     Keywords.kw_internal, Keywords.kw_abstract,
+                     Keywords.kw_sealed, Keywords.kw_override,
+                     Keywords.kw_async, Keywords.kw_unsafe) &&
+        Right.is(tok::l_paren))
+      return true;
+  } else if (Style.isJavaScript()) {
+    if (Left.is(TT_FatArrow))
+      return true;
+    // for await ( ...
+    if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
+        Left.Previous->is(tok::kw_for))
+      return true;
+    if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
+        Right.MatchingParen) {
+      const FormatToken *Next = Right.MatchingParen->getNextNonComment();
+      // An async arrow function, for example: `x = async () => foo();`,
+      // as opposed to calling a function called async: `x = async();`
+      if (Next && Next->is(TT_FatArrow))
+        return true;
+    }
+    if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
+        (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
+      return false;
+    // In tagged template literals ("html`bar baz`"), there is no space between
+    // the tag identifier and the template string.
+    if (Keywords.IsJavaScriptIdentifier(Left,
+                                        /* AcceptIdentifierName= */ false) &&
+        Right.is(TT_TemplateString))
+      return false;
+    if (Right.is(tok::star) &&
+        Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
+      return false;
+    if (Right.isOneOf(tok::l_brace, tok::l_square) &&
+        Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,
+                     Keywords.kw_extends, Keywords.kw_implements))
+      return true;
+    if (Right.is(tok::l_paren)) {
+      // JS methods can use some keywords as names (e.g. `delete()`).
+      if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())
+        return false;
+      // Valid JS method names can include keywords, e.g. `foo.delete()` or
+      // `bar.instanceof()`. Recognize call positions by preceding period.
+      if (Left.Previous && Left.Previous->is(tok::period) &&
+          Left.Tok.getIdentifierInfo())
+        return false;
+      // Additional unary JavaScript operators that need a space after.
+      if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,
+                       tok::kw_void))
+        return true;
+    }
+    // `foo as const;` casts into a const type.
+    if (Left.endsSequence(tok::kw_const, Keywords.kw_as))
+      return false;
+    if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
+                      tok::kw_const) ||
+         // "of" is only a keyword if it appears after another identifier
+         // (e.g. as "const x of y" in a for loop), or after a destructuring
+         // operation (const [x, y] of z, const {a, b} of c).
+         (Left.is(Keywords.kw_of) && Left.Previous &&
+          (Left.Previous->is(tok::identifier) ||
+           Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
+        (!Left.Previous || !Left.Previous->is(tok::period)))
+      return true;
+    if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
+        Left.Previous->is(tok::period) && Right.is(tok::l_paren))
+      return false;
+    if (Left.is(Keywords.kw_as) &&
+        Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
+      return true;
+    if (Left.is(tok::kw_default) && Left.Previous &&
+        Left.Previous->is(tok::kw_export))
+      return true;
+    if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))
+      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;
+    if (Left.is(tok::ellipsis))
+      return false;
+    if (Left.is(TT_TemplateCloser) &&
+        !Right.isOneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square,
+                       Keywords.kw_implements, Keywords.kw_extends))
+      // Type assertions ('<type>expr') are not followed by whitespace. Other
+      // locations that should have whitespace following are identified by the
+      // above set of follower tokens.
+      return false;
+    if (Right.is(TT_NonNullAssertion))
+      return false;
+    if (Left.is(TT_NonNullAssertion) &&
+        Right.isOneOf(Keywords.kw_as, Keywords.kw_in))
+      return true; // "x! as string", "x! in y"
+  } else if (Style.Language == FormatStyle::LK_Java) {
+    if (Left.is(tok::r_square) && Right.is(tok::l_brace))
+      return true;
+    if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren))
+      return Style.SpaceBeforeParensOptions.AfterControlStatements ||
+             spaceRequiredBeforeParens(Right);
+    if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
+                      tok::kw_protected) ||
+         Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract,
+                      Keywords.kw_native)) &&
+        Right.is(TT_TemplateOpener))
+      return true;
+  }
+  if (Left.is(TT_ImplicitStringLiteral))
+    return Right.hasWhitespaceBefore();
+  if (Line.Type == LT_ObjCMethodDecl) {
+    if (Left.is(TT_ObjCMethodSpecifier))
+      return true;
+    if (Left.is(tok::r_paren) && canBeObjCSelectorComponent(Right))
+      // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a
+      // keyword in Objective-C, and '+ (instancetype)new;' is a standard class
+      // method declaration.
+      return false;
+  }
+  if (Line.Type == LT_ObjCProperty &&
+      (Right.is(tok::equal) || Left.is(tok::equal)))
+    return false;
+
+  if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
+      Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
+    return true;
+  if (Left.is(tok::comma) && !Right.is(TT_OverloadedOperatorLParen))
+    return true;
+  if (Right.is(tok::comma))
+    return false;
+  if (Right.is(TT_ObjCBlockLParen))
+    return true;
+  if (Right.is(TT_CtorInitializerColon))
+    return Style.SpaceBeforeCtorInitializerColon;
+  if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon)
+    return false;
+  if (Right.is(TT_RangeBasedForLoopColon) &&
+      !Style.SpaceBeforeRangeBasedForLoopColon)
+    return false;
+  if (Left.is(TT_BitFieldColon))
+    return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
+           Style.BitFieldColonSpacing == FormatStyle::BFCS_After;
+  if (Right.is(tok::colon)) {
+    if (Line.First->isOneOf(tok::kw_default, tok::kw_case))
+      return Style.SpaceBeforeCaseColon;
+    const FormatToken *Next = Right.getNextNonComment();
+    if (!Next || Next->is(tok::semi))
+      return false;
+    if (Right.is(TT_ObjCMethodExpr))
+      return false;
+    if (Left.is(tok::question))
+      return false;
+    if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon))
+      return false;
+    if (Right.is(TT_DictLiteral))
+      return Style.SpacesInContainerLiterals;
+    if (Right.is(TT_AttributeColon))
+      return false;
+    if (Right.is(TT_CSharpNamedArgumentColon))
+      return false;
+    if (Right.is(TT_BitFieldColon))
+      return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
+             Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
+    return true;
+  }
+  // Do not merge "- -" into "--".
+  if ((Left.isOneOf(tok::minus, tok::minusminus) &&
+       Right.isOneOf(tok::minus, tok::minusminus)) ||
+      (Left.isOneOf(tok::plus, tok::plusplus) &&
+       Right.isOneOf(tok::plus, tok::plusplus)))
+    return true;
+  if (Left.is(TT_UnaryOperator)) {
+    if (!Right.is(tok::l_paren)) {
+      // The alternative operators for ~ and ! are "compl" and "not".
+      // If they are used instead, we do not want to combine them with
+      // the token to the right, unless that is a left paren.
+      if (Left.is(tok::exclaim) && Left.TokenText == "not")
+        return true;
+      if (Left.is(tok::tilde) && Left.TokenText == "compl")
+        return true;
+      // Lambda captures allow for a lone &, so "&]" needs to be properly
+      // handled.
+      if (Left.is(tok::amp) && Right.is(tok::r_square))
+        return Style.SpacesInSquareBrackets;
+    }
+    return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
+           Right.is(TT_BinaryOperator);
+  }
+
+  // If the next token is a binary operator or a selector name, we have
+  // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
+  if (Left.is(TT_CastRParen))
+    return Style.SpaceAfterCStyleCast ||
+           Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
+
+  auto ShouldAddSpacesInAngles = [this, &Right]() {
+    if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always)
+      return true;
+    if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave)
+      return Right.hasWhitespaceBefore();
+    return false;
+  };
+
+  if (Left.is(tok::greater) && Right.is(tok::greater)) {
+    if (Style.Language == FormatStyle::LK_TextProto ||
+        (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
+      return !Style.Cpp11BracedListStyle;
+    return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
+           ((Style.Standard < FormatStyle::LS_Cpp11) ||
+            ShouldAddSpacesInAngles());
+  }
+  if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
+      Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
+      (Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
+    return false;
+  if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&
+      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
+    // this turns out to be too lenient, add analysis of the identifier itself.
+    return Right.hasWhitespaceBefore();
+  if (Right.is(tok::coloncolon) &&
+      !Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren))
+    // Put a space between < and :: in vector< ::std::string >
+    return (Left.is(TT_TemplateOpener) &&
+            ((Style.Standard < FormatStyle::LS_Cpp11) ||
+             ShouldAddSpacesInAngles())) ||
+           !(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
+                          tok::kw___super, TT_TemplateOpener,
+                          TT_TemplateCloser)) ||
+           (Left.is(tok::l_paren) && Style.SpacesInParentheses);
+  if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
+    return ShouldAddSpacesInAngles();
+  // Space before TT_StructuredBindingLSquare.
+  if (Right.is(TT_StructuredBindingLSquare))
+    return !Left.isOneOf(tok::amp, tok::ampamp) ||
+           getTokenReferenceAlignment(Left) != FormatStyle::PAS_Right;
+  // Space before & or && following a TT_StructuredBindingLSquare.
+  if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&
+      Right.isOneOf(tok::amp, tok::ampamp))
+    return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
+  if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
+      (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
+       !Right.is(tok::r_paren)))
+    return true;
+  if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
+      Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
+    return false;
+  if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
+      Line.startsWith(tok::hash))
+    return true;
+  if (Right.is(TT_TrailingUnaryOperator))
+    return false;
+  if (Left.is(TT_RegexLiteral))
+    return false;
+
   if (Left.is(tok::kw_return) &&
       !Right.isOneOf(tok::semi, tok::r_paren, tok::hashhash))
     return true;
@@ -3446,412 +3848,6 @@
   return true;
 }
 
-bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
-                                         const FormatToken &Right) {
-  const FormatToken &Left = *Right.Previous;
-
-  // If the token is finalized don't touch it (as it could be in a
-  // clang-format-off section).
-  if (Left.Finalized)
-    return Right.hasWhitespaceBefore();
-
-  if (Right.Tok.getIdentifierInfo() && Left.Tok.getIdentifierInfo())
-    return true; // Never ever merge two identifiers.
-
-  // Leave a space between * and /* to avoid C4138 `comment end` found outside
-  // of comment.
-  if (Left.is(tok::star) && Right.is(tok::comment))
-    return true;
-
-  if (Style.isCpp()) {
-    // Space between import <iostream>.
-    // or import .....;
-    if (Left.is(Keywords.kw_import) && Right.isOneOf(tok::less, tok::ellipsis))
-      return true;
-    // Space between `module :` and `import :`.
-    if (Left.isOneOf(Keywords.kw_module, Keywords.kw_import) &&
-        Right.is(TT_ModulePartitionColon))
-      return true;
-    // No space between import foo:bar but keep a space between import :bar;
-    if (Left.is(tok::identifier) && Right.is(TT_ModulePartitionColon))
-      return false;
-    // No space between :bar;
-    if (Left.is(TT_ModulePartitionColon) &&
-        Right.isOneOf(tok::identifier, tok::kw_private))
-      return false;
-    if (Left.is(tok::ellipsis) && Right.is(tok::identifier) &&
-        Line.First->is(Keywords.kw_import))
-      return false;
-    // Space in __attribute__((attr)) ::type.
-    if (Left.is(TT_AttributeParen) && Right.is(tok::coloncolon))
-      return true;
-
-    if (Left.is(tok::kw_operator))
-      return Right.is(tok::coloncolon);
-    if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) &&
-        !Left.opensScope() && Style.SpaceBeforeCpp11BracedList)
-      return true;
-    if (Left.is(tok::less) && Left.is(TT_OverloadedOperator) &&
-        Right.is(TT_TemplateOpener))
-      return true;
-  } else if (Style.Language == FormatStyle::LK_Proto ||
-             Style.Language == FormatStyle::LK_TextProto) {
-    if (Right.is(tok::period) &&
-        Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
-                     Keywords.kw_repeated, Keywords.kw_extend))
-      return true;
-    if (Right.is(tok::l_paren) &&
-        Left.isOneOf(Keywords.kw_returns, Keywords.kw_option))
-      return true;
-    if (Right.isOneOf(tok::l_brace, tok::less) && Left.is(TT_SelectorName))
-      return true;
-    // Slashes occur in text protocol extension syntax: [type/type] { ... }.
-    if (Left.is(tok::slash) || Right.is(tok::slash))
-      return false;
-    if (Left.MatchingParen &&
-        Left.MatchingParen->is(TT_ProtoExtensionLSquare) &&
-        Right.isOneOf(tok::l_brace, tok::less))
-      return !Style.Cpp11BracedListStyle;
-    // A percent is probably part of a formatting specification, such as %lld.
-    if (Left.is(tok::percent))
-      return false;
-    // Preserve the existence of a space before a percent for cases like 0x%04x
-    // and "%d %d"
-    if (Left.is(tok::numeric_constant) && Right.is(tok::percent))
-      return Right.hasWhitespaceBefore();
-  } else if (Style.isJson()) {
-    if (Right.is(tok::colon))
-      return false;
-  } else if (Style.isCSharp()) {
-    // Require spaces around '{' and  before '}' unless they appear in
-    // interpolated strings. Interpolated strings are merged into a single token
-    // so cannot have spaces inserted by this function.
-
-    // No space between 'this' and '['
-    if (Left.is(tok::kw_this) && Right.is(tok::l_square))
-      return false;
-
-    // No space between 'new' and '('
-    if (Left.is(tok::kw_new) && Right.is(tok::l_paren))
-      return false;
-
-    // Space before { (including space within '{ {').
-    if (Right.is(tok::l_brace))
-      return true;
-
-    // Spaces inside braces.
-    if (Left.is(tok::l_brace) && Right.isNot(tok::r_brace))
-      return true;
-
-    if (Left.isNot(tok::l_brace) && Right.is(tok::r_brace))
-      return true;
-
-    // Spaces around '=>'.
-    if (Left.is(TT_FatArrow) || Right.is(TT_FatArrow))
-      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;
-
-    // spaces inside square brackets.
-    if (Left.is(tok::l_square) || Right.is(tok::r_square))
-      return Style.SpacesInSquareBrackets;
-
-    // No space before ? in nullable types.
-    if (Right.is(TT_CSharpNullable))
-      return false;
-
-    // No space before null forgiving '!'.
-    if (Right.is(TT_NonNullAssertion))
-      return false;
-
-    // No space between consecutive commas '[,,]'.
-    if (Left.is(tok::comma) && Right.is(tok::comma))
-      return false;
-
-    // space after var in `var (key, value)`
-    if (Left.is(Keywords.kw_var) && Right.is(tok::l_paren))
-      return true;
-
-    // space between keywords and paren e.g. "using ("
-    if (Right.is(tok::l_paren))
-      if (Left.isOneOf(tok::kw_using, Keywords.kw_async, Keywords.kw_when,
-                       Keywords.kw_lock))
-        return Style.SpaceBeforeParensOptions.AfterControlStatements ||
-               spaceRequiredBeforeParens(Right);
-
-    // space between method modifier and opening parenthesis of a tuple return
-    // type
-    if (Left.isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected,
-                     tok::kw_virtual, tok::kw_extern, tok::kw_static,
-                     Keywords.kw_internal, Keywords.kw_abstract,
-                     Keywords.kw_sealed, Keywords.kw_override,
-                     Keywords.kw_async, Keywords.kw_unsafe) &&
-        Right.is(tok::l_paren))
-      return true;
-  } else if (Style.isJavaScript()) {
-    if (Left.is(TT_FatArrow))
-      return true;
-    // for await ( ...
-    if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
-        Left.Previous->is(tok::kw_for))
-      return true;
-    if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
-        Right.MatchingParen) {
-      const FormatToken *Next = Right.MatchingParen->getNextNonComment();
-      // An async arrow function, for example: `x = async () => foo();`,
-      // as opposed to calling a function called async: `x = async();`
-      if (Next && Next->is(TT_FatArrow))
-        return true;
-    }
-    if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
-        (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
-      return false;
-    // In tagged template literals ("html`bar baz`"), there is no space between
-    // the tag identifier and the template string.
-    if (Keywords.IsJavaScriptIdentifier(Left,
-                                        /* AcceptIdentifierName= */ false) &&
-        Right.is(TT_TemplateString))
-      return false;
-    if (Right.is(tok::star) &&
-        Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
-      return false;
-    if (Right.isOneOf(tok::l_brace, tok::l_square) &&
-        Left.isOneOf(Keywords.kw_function, Keywords.kw_yield,
-                     Keywords.kw_extends, Keywords.kw_implements))
-      return true;
-    if (Right.is(tok::l_paren)) {
-      // JS methods can use some keywords as names (e.g. `delete()`).
-      if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo())
-        return false;
-      // Valid JS method names can include keywords, e.g. `foo.delete()` or
-      // `bar.instanceof()`. Recognize call positions by preceding period.
-      if (Left.Previous && Left.Previous->is(tok::period) &&
-          Left.Tok.getIdentifierInfo())
-        return false;
-      // Additional unary JavaScript operators that need a space after.
-      if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof,
-                       tok::kw_void))
-        return true;
-    }
-    // `foo as const;` casts into a const type.
-    if (Left.endsSequence(tok::kw_const, Keywords.kw_as))
-      return false;
-    if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in,
-                      tok::kw_const) ||
-         // "of" is only a keyword if it appears after another identifier
-         // (e.g. as "const x of y" in a for loop), or after a destructuring
-         // operation (const [x, y] of z, const {a, b} of c).
-         (Left.is(Keywords.kw_of) && Left.Previous &&
-          (Left.Previous->is(tok::identifier) ||
-           Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
-        (!Left.Previous || !Left.Previous->is(tok::period)))
-      return true;
-    if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
-        Left.Previous->is(tok::period) && Right.is(tok::l_paren))
-      return false;
-    if (Left.is(Keywords.kw_as) &&
-        Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren))
-      return true;
-    if (Left.is(tok::kw_default) && Left.Previous &&
-        Left.Previous->is(tok::kw_export))
-      return true;
-    if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))
-      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;
-    if (Left.is(tok::ellipsis))
-      return false;
-    if (Left.is(TT_TemplateCloser) &&
-        !Right.isOneOf(tok::equal, tok::l_brace, tok::comma, tok::l_square,
-                       Keywords.kw_implements, Keywords.kw_extends))
-      // Type assertions ('<type>expr') are not followed by whitespace. Other
-      // locations that should have whitespace following are identified by the
-      // above set of follower tokens.
-      return false;
-    if (Right.is(TT_NonNullAssertion))
-      return false;
-    if (Left.is(TT_NonNullAssertion) &&
-        Right.isOneOf(Keywords.kw_as, Keywords.kw_in))
-      return true; // "x! as string", "x! in y"
-  } else if (Style.Language == FormatStyle::LK_Java) {
-    if (Left.is(tok::r_square) && Right.is(tok::l_brace))
-      return true;
-    if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren))
-      return Style.SpaceBeforeParensOptions.AfterControlStatements ||
-             spaceRequiredBeforeParens(Right);
-    if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private,
-                      tok::kw_protected) ||
-         Left.isOneOf(Keywords.kw_final, Keywords.kw_abstract,
-                      Keywords.kw_native)) &&
-        Right.is(TT_TemplateOpener))
-      return true;
-  }
-  if (Left.is(TT_ImplicitStringLiteral))
-    return Right.hasWhitespaceBefore();
-  if (Line.Type == LT_ObjCMethodDecl) {
-    if (Left.is(TT_ObjCMethodSpecifier))
-      return true;
-    if (Left.is(tok::r_paren) && canBeObjCSelectorComponent(Right))
-      // Don't space between ')' and <id> or ')' and 'new'. 'new' is not a
-      // keyword in Objective-C, and '+ (instancetype)new;' is a standard class
-      // method declaration.
-      return false;
-  }
-  if (Line.Type == LT_ObjCProperty &&
-      (Right.is(tok::equal) || Left.is(tok::equal)))
-    return false;
-
-  if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
-      Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
-    return true;
-  if (Left.is(tok::comma) && !Right.is(TT_OverloadedOperatorLParen))
-    return true;
-  if (Right.is(tok::comma))
-    return false;
-  if (Right.is(TT_ObjCBlockLParen))
-    return true;
-  if (Right.is(TT_CtorInitializerColon))
-    return Style.SpaceBeforeCtorInitializerColon;
-  if (Right.is(TT_InheritanceColon) && !Style.SpaceBeforeInheritanceColon)
-    return false;
-  if (Right.is(TT_RangeBasedForLoopColon) &&
-      !Style.SpaceBeforeRangeBasedForLoopColon)
-    return false;
-  if (Left.is(TT_BitFieldColon))
-    return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
-           Style.BitFieldColonSpacing == FormatStyle::BFCS_After;
-  if (Right.is(tok::colon)) {
-    if (Line.First->isOneOf(tok::kw_default, tok::kw_case))
-      return Style.SpaceBeforeCaseColon;
-    const FormatToken *Next = Right.getNextNonComment();
-    if (!Next || Next->is(tok::semi))
-      return false;
-    if (Right.is(TT_ObjCMethodExpr))
-      return false;
-    if (Left.is(tok::question))
-      return false;
-    if (Right.is(TT_InlineASMColon) && Left.is(tok::coloncolon))
-      return false;
-    if (Right.is(TT_DictLiteral))
-      return Style.SpacesInContainerLiterals;
-    if (Right.is(TT_AttributeColon))
-      return false;
-    if (Right.is(TT_CSharpNamedArgumentColon))
-      return false;
-    if (Right.is(TT_BitFieldColon))
-      return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both ||
-             Style.BitFieldColonSpacing == FormatStyle::BFCS_Before;
-    return true;
-  }
-  // Do not merge "- -" into "--".
-  if ((Left.isOneOf(tok::minus, tok::minusminus) &&
-       Right.isOneOf(tok::minus, tok::minusminus)) ||
-      (Left.isOneOf(tok::plus, tok::plusplus) &&
-       Right.isOneOf(tok::plus, tok::plusplus)))
-    return true;
-  if (Left.is(TT_UnaryOperator)) {
-    if (!Right.is(tok::l_paren)) {
-      // The alternative operators for ~ and ! are "compl" and "not".
-      // If they are used instead, we do not want to combine them with
-      // the token to the right, unless that is a left paren.
-      if (Left.is(tok::exclaim) && Left.TokenText == "not")
-        return true;
-      if (Left.is(tok::tilde) && Left.TokenText == "compl")
-        return true;
-      // Lambda captures allow for a lone &, so "&]" needs to be properly
-      // handled.
-      if (Left.is(tok::amp) && Right.is(tok::r_square))
-        return Style.SpacesInSquareBrackets;
-    }
-    return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) ||
-           Right.is(TT_BinaryOperator);
-  }
-
-  // If the next token is a binary operator or a selector name, we have
-  // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly.
-  if (Left.is(TT_CastRParen))
-    return Style.SpaceAfterCStyleCast ||
-           Right.isOneOf(TT_BinaryOperator, TT_SelectorName);
-
-  auto ShouldAddSpacesInAngles = [this, &Right]() {
-    if (this->Style.SpacesInAngles == FormatStyle::SIAS_Always)
-      return true;
-    if (this->Style.SpacesInAngles == FormatStyle::SIAS_Leave)
-      return Right.hasWhitespaceBefore();
-    return false;
-  };
-
-  if (Left.is(tok::greater) && Right.is(tok::greater)) {
-    if (Style.Language == FormatStyle::LK_TextProto ||
-        (Style.Language == FormatStyle::LK_Proto && Left.is(TT_DictLiteral)))
-      return !Style.Cpp11BracedListStyle;
-    return Right.is(TT_TemplateCloser) && Left.is(TT_TemplateCloser) &&
-           ((Style.Standard < FormatStyle::LS_Cpp11) ||
-            ShouldAddSpacesInAngles());
-  }
-  if (Right.isOneOf(tok::arrow, tok::arrowstar, tok::periodstar) ||
-      Left.isOneOf(tok::arrow, tok::period, tok::arrowstar, tok::periodstar) ||
-      (Right.is(tok::period) && Right.isNot(TT_DesignatedInitializerPeriod)))
-    return false;
-  if (!Style.SpaceBeforeAssignmentOperators && Left.isNot(TT_TemplateCloser) &&
-      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
-    // this turns out to be too lenient, add analysis of the identifier itself.
-    return Right.hasWhitespaceBefore();
-  if (Right.is(tok::coloncolon) &&
-      !Left.isOneOf(tok::l_brace, tok::comment, tok::l_paren))
-    // Put a space between < and :: in vector< ::std::string >
-    return (Left.is(TT_TemplateOpener) &&
-            ((Style.Standard < FormatStyle::LS_Cpp11) ||
-             ShouldAddSpacesInAngles())) ||
-           !(Left.isOneOf(tok::l_paren, tok::r_paren, tok::l_square,
-                          tok::kw___super, TT_TemplateOpener,
-                          TT_TemplateCloser)) ||
-           (Left.is(tok::l_paren) && Style.SpacesInParentheses);
-  if ((Left.is(TT_TemplateOpener)) != (Right.is(TT_TemplateCloser)))
-    return ShouldAddSpacesInAngles();
-  // Space before TT_StructuredBindingLSquare.
-  if (Right.is(TT_StructuredBindingLSquare))
-    return !Left.isOneOf(tok::amp, tok::ampamp) ||
-           getTokenReferenceAlignment(Left) != FormatStyle::PAS_Right;
-  // Space before & or && following a TT_StructuredBindingLSquare.
-  if (Right.Next && Right.Next->is(TT_StructuredBindingLSquare) &&
-      Right.isOneOf(tok::amp, tok::ampamp))
-    return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
-  if ((Right.is(TT_BinaryOperator) && !Left.is(tok::l_paren)) ||
-      (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
-       !Right.is(tok::r_paren)))
-    return true;
-  if (Right.is(TT_TemplateOpener) && Left.is(tok::r_paren) &&
-      Left.MatchingParen && Left.MatchingParen->is(TT_OverloadedOperatorLParen))
-    return false;
-  if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
-      Line.startsWith(tok::hash))
-    return true;
-  if (Right.is(TT_TrailingUnaryOperator))
-    return false;
-  if (Left.is(TT_RegexLiteral))
-    return false;
-  return spaceRequiredBetween(Line, Left, Right);
-}
-
 // Returns 'true' if 'Tok' is a brace we'd want to break before in Allman style.
 static bool isAllmanBrace(const FormatToken &Tok) {
   return Tok.is(tok::l_brace) && Tok.is(BK_Block) &&
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to