def IsRValueType()

in build-support/cpplint.py [0:0]


def IsRValueType(typenames, clean_lines, nesting_state, linenum, column):
  """Check if the token ending on (linenum, column) is a type.

  Assumes that text to the right of the column is "&&" or a function
  name.

  Args:
    typenames: set of type names from template-argument-list.
    clean_lines: A CleansedLines instance containing the file.
    nesting_state: A NestingState instance which maintains information about
                   the current stack of nested blocks being parsed.
    linenum: the number of the line to check.
    column: end column of the token to check.
  Returns:
    True if this token is a type, False if we are not sure.
  """
  prefix = clean_lines.elided[linenum][0:column]

  # Get one word to the left.  If we failed to do so, this is most
  # likely not a type, since it's unlikely that the type name and "&&"
  # would be split across multiple lines.
  match = Match(r'^(.*)(\b\w+|[>*)&])\s*$', prefix)
  if not match:
    return False

  # Check text following the token.  If it's "&&>" or "&&," or "&&...", it's
  # most likely a rvalue reference used inside a template.
  suffix = clean_lines.elided[linenum][column:]
  if Match(r'&&\s*(?:[>,]|\.\.\.)', suffix):
    return True

  # Check for known types and end of templates:
  #   int&& variable
  #   vector<int>&& variable
  #
  # Because this function is called recursively, we also need to
  # recognize pointer and reference types:
  #   int* Function()
  #   int& Function()
  if (match.group(2) in typenames or
      match.group(2) in ['char', 'char16_t', 'char32_t', 'wchar_t', 'bool',
                         'short', 'int', 'long', 'signed', 'unsigned',
                         'float', 'double', 'void', 'auto', '>', '*', '&']):
    return True

  # If we see a close parenthesis, look for decltype on the other side.
  # decltype would unambiguously identify a type, anything else is
  # probably a parenthesized expression and not a type.
  if match.group(2) == ')':
    return IsDecltype(
        clean_lines, linenum, len(match.group(1)) + len(match.group(2)) - 1)

  # Check for casts and cv-qualifiers.
  #   match.group(1)  remainder
  #   --------------  ---------
  #   const_cast<     type&&
  #   const           type&&
  #   type            const&&
  if Search(r'\b(?:const_cast\s*<|static_cast\s*<|dynamic_cast\s*<|'
            r'reinterpret_cast\s*<|\w+\s)\s*$',
            match.group(1)):
    return True

  # Look for a preceding symbol that might help differentiate the context.
  # These are the cases that would be ambiguous:
  #   match.group(1)  remainder
  #   --------------  ---------
  #   Call         (   expression &&
  #   Declaration  (   type&&
  #   sizeof       (   type&&
  #   if           (   expression &&
  #   while        (   expression &&
  #   for          (   type&&
  #   for(         ;   expression &&
  #   statement    ;   type&&
  #   block        {   type&&
  #   constructor  {   expression &&
  start = linenum
  line = match.group(1)
  match_symbol = None
  while start >= 0:
    # We want to skip over identifiers and commas to get to a symbol.
    # Commas are skipped so that we can find the opening parenthesis
    # for function parameter lists.
    match_symbol = Match(r'^(.*)([^\w\s,])[\w\s,]*$', line)
    if match_symbol:
      break
    start -= 1
    line = clean_lines.elided[start]

  if not match_symbol:
    # Probably the first statement in the file is an rvalue reference
    return True

  if match_symbol.group(2) == '}':
    # Found closing brace, probably an indicate of this:
    #   block{} type&&
    return True

  if match_symbol.group(2) == ';':
    # Found semicolon, probably one of these:
    #   for(; expression &&
    #   statement; type&&

    # Look for the previous 'for(' in the previous lines.
    before_text = match_symbol.group(1)
    for i in xrange(start - 1, max(start - 6, 0), -1):
      before_text = clean_lines.elided[i] + before_text
    if Search(r'for\s*\([^{};]*$', before_text):
      # This is the condition inside a for-loop
      return False

    # Did not find a for-init-statement before this semicolon, so this
    # is probably a new statement and not a condition.
    return True

  if match_symbol.group(2) == '{':
    # Found opening brace, probably one of these:
    #   block{ type&& = ... ; }
    #   constructor{ expression && expression }

    # Look for a closing brace or a semicolon.  If we see a semicolon
    # first, this is probably a rvalue reference.
    line = clean_lines.elided[start][0:len(match_symbol.group(1)) + 1]
    end = start
    depth = 1
    while True:
      for ch in line:
        if ch == ';':
          return True
        elif ch == '{':
          depth += 1
        elif ch == '}':
          depth -= 1
          if depth == 0:
            return False
      end += 1
      if end >= clean_lines.NumLines():
        break
      line = clean_lines.elided[end]
    # Incomplete program?
    return False

  if match_symbol.group(2) == '(':
    # Opening parenthesis.  Need to check what's to the left of the
    # parenthesis.  Look back one extra line for additional context.
    before_text = match_symbol.group(1)
    if linenum > 1:
      before_text = clean_lines.elided[linenum - 1] + before_text
    before_text = match_symbol.group(1)

    # Patterns that are likely to be types:
    #   [](type&&
    #   for (type&&
    #   sizeof(type&&
    #   operator=(type&&
    #
    if Search(r'(?:\]|\bfor|\bsizeof|\boperator\s*\S+\s*)\s*$', before_text):
      return True

    # Patterns that are likely to be expressions:
    #   if (expression &&
    #   while (expression &&
    #   : initializer(expression &&
    #   , initializer(expression &&
    #   ( FunctionCall(expression &&
    #   + FunctionCall(expression &&
    #   + (expression &&
    #
    # The last '+' represents operators such as '+' and '-'.
    if Search(r'(?:\bif|\bwhile|[-+=%^(<!?:,&*]\s*)$', before_text):
      return False

    # Something else.  Check that tokens to the left look like
    #   return_type function_name
    match_func = Match(r'^(.*\S.*)\s+\w(?:\w|::)*(?:<[^<>]*>)?\s*$',
                       match_symbol.group(1))
    if match_func:
      # Check for constructors, which don't have return types.
      if Search(r'\b(?:explicit|inline)$', match_func.group(1)):
        return True
      implicit_constructor = Match(r'\s*(\w+)\((?:const\s+)?(\w+)', prefix)
      if (implicit_constructor and
          implicit_constructor.group(1) == implicit_constructor.group(2)):
        return True
      return IsRValueType(typenames, clean_lines, nesting_state, linenum,
                          len(match_func.group(1)))

    # Nothing before the function name.  If this is inside a block scope,
    # this is probably a function call.
    return not (nesting_state.previous_stack_top and
                nesting_state.previous_stack_top.IsBlockInfo())

  if match_symbol.group(2) == '>':
    # Possibly a closing bracket, check that what's on the other side
    # looks like the start of a template.
    return IsTemplateParameterList(
        clean_lines, start, len(match_symbol.group(1)))

  # Some other symbol, usually something like "a=b&&c".  This is most
  # likely not a type.
  return False