def CheckOperatorSpacing()

in cpp/misc/cpplint.py [0:0]


def CheckOperatorSpacing(filename, clean_lines, linenum, error):
  """Checks for horizontal spacing around operators.

  Args:
    filename: The name of the current file.
    clean_lines: A CleansedLines instance containing the file.
    linenum: The number of the line to check.
    error: The function to call with any errors found.
  """
  line = clean_lines.elided[linenum]

  # Don't try to do spacing checks for operator methods.  Do this by
  # replacing the troublesome characters with something else,
  # preserving column position for all other characters.
  #
  # The replacement is done repeatedly to avoid false positives from
  # operators that call operators.
  while True:
    match = Match(r'^(.*\boperator\b)(\S+)(\s*\(.*)$', line)
    if match:
      line = match.group(1) + ('_' * len(match.group(2))) + match.group(3)
    else:
      break

  # We allow no-spaces around = within an if: "if ( (a=Foo()) == 0 )".
  # Otherwise not.  Note we only check for non-spaces on *both* sides;
  # sometimes people put non-spaces on one side when aligning ='s among
  # many lines (not that this is behavior that I approve of...)
  if ((Search(r'[\w.]=', line) or
       Search(r'=[\w.]', line))
      and not Search(r'\b(if|while|for) ', line)
      # Operators taken from [lex.operators] in C++11 standard.
      and not Search(r'(>=|<=|==|!=|&=|\^=|\|=|\+=|\*=|\/=|\%=)', line)
      and not Search(r'operator=', line)):
    error(filename, linenum, 'whitespace/operators', 4,
          'Missing spaces around =')

  # It's ok not to have spaces around binary operators like + - * /, but if
  # there's too little whitespace, we get concerned.  It's hard to tell,
  # though, so we punt on this one for now.  TODO.

  # You should always have whitespace around binary operators.
  #
  # Check <= and >= first to avoid false positives with < and >, then
  # check non-include lines for spacing around < and >.
  #
  # If the operator is followed by a comma, assume it's be used in a
  # macro context and don't do any checks.  This avoids false
  # positives.
  #
  # Note that && is not included here.  This is because there are too
  # many false positives due to RValue references.
  match = Search(r'[^<>=!\s](==|!=|<=|>=|\|\|)[^<>=!\s,;\)]', line)
  if match:
    error(filename, linenum, 'whitespace/operators', 3,
          'Missing spaces around %s' % match.group(1))
  elif not Match(r'#.*include', line):
    # Look for < that is not surrounded by spaces.  This is only
    # triggered if both sides are missing spaces, even though
    # technically should should flag if at least one side is missing a
    # space.  This is done to avoid some false positives with shifts.
    match = Match(r'^(.*[^\s<])<[^\s=<,]', line)
    if match:
      (_, _, end_pos) = CloseExpression(
          clean_lines, linenum, len(match.group(1)))
      if end_pos <= -1:
        error(filename, linenum, 'whitespace/operators', 3,
              'Missing spaces around <')

    # Look for > that is not surrounded by spaces.  Similar to the
    # above, we only trigger if both sides are missing spaces to avoid
    # false positives with shifts.
    match = Match(r'^(.*[^-\s>])>[^\s=>,]', line)
    if match:
      (_, _, start_pos) = ReverseCloseExpression(
          clean_lines, linenum, len(match.group(1)))
      if start_pos <= -1:
        error(filename, linenum, 'whitespace/operators', 3,
              'Missing spaces around >')

  # We allow no-spaces around << when used like this: 10<<20, but
  # not otherwise (particularly, not when used as streams)
  #
  # We also allow operators following an opening parenthesis, since
  # those tend to be macros that deal with operators.
  match = Search(r'(operator|[^\s(<])(?:L|UL|LL|ULL|l|ul|ll|ull)?<<([^\s,=<])', line)
  if (match and not (match.group(1).isdigit() and match.group(2).isdigit()) and
      not (match.group(1) == 'operator' and match.group(2) == ';')):
    error(filename, linenum, 'whitespace/operators', 3,
          'Missing spaces around <<')

  # We allow no-spaces around >> for almost anything.  This is because
  # C++11 allows ">>" to close nested templates, which accounts for
  # most cases when ">>" is not followed by a space.
  #
  # We still warn on ">>" followed by alpha character, because that is
  # likely due to ">>" being used for right shifts, e.g.:
  #   value >> alpha
  #
  # When ">>" is used to close templates, the alphanumeric letter that
  # follows would be part of an identifier, and there should still be
  # a space separating the template type and the identifier.
  #   type<type<type>> alpha
  match = Search(r'>>[a-zA-Z_]', line)
  if match:
    error(filename, linenum, 'whitespace/operators', 3,
          'Missing spaces around >>')

  # There shouldn't be space around unary operators
  match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
  if match:
    error(filename, linenum, 'whitespace/operators', 4,
          'Extra space for operator %s' % match.group(1))