Code Duplication    Length = 137-137 lines in 2 locations

sdk/build-support/cpplint.py 1 location

@@ 5168-5304 (lines=137) @@
5165
  return False
5166
5167
5168
def CheckForNonConstReference(filename, clean_lines, linenum,
5169
                              nesting_state, error):
5170
  """Check for non-const references.
5171
5172
  Separate from CheckLanguage since it scans backwards from current
5173
  line, instead of scanning forward.
5174
5175
  Args:
5176
    filename: The name of the current file.
5177
    clean_lines: A CleansedLines instance containing the file.
5178
    linenum: The number of the line to check.
5179
    nesting_state: A NestingState instance which maintains information about
5180
                   the current stack of nested blocks being parsed.
5181
    error: The function to call with any errors found.
5182
  """
5183
  # Do nothing if there is no '&' on current line.
5184
  line = clean_lines.elided[linenum]
5185
  if '&' not in line:
5186
    return
5187
5188
  # If a function is inherited, current function doesn't have much of
5189
  # a choice, so any non-const references should not be blamed on
5190
  # derived function.
5191
  if IsDerivedFunction(clean_lines, linenum):
5192
    return
5193
5194
  # Don't warn on out-of-line method definitions, as we would warn on the
5195
  # in-line declaration, if it isn't marked with 'override'.
5196
  if IsOutOfLineMethodDefinition(clean_lines, linenum):
5197
    return
5198
5199
  # Long type names may be broken across multiple lines, usually in one
5200
  # of these forms:
5201
  #   LongType
5202
  #       ::LongTypeContinued &identifier
5203
  #   LongType::
5204
  #       LongTypeContinued &identifier
5205
  #   LongType<
5206
  #       ...>::LongTypeContinued &identifier
5207
  #
5208
  # If we detected a type split across two lines, join the previous
5209
  # line to current line so that we can match const references
5210
  # accordingly.
5211
  #
5212
  # Note that this only scans back one line, since scanning back
5213
  # arbitrary number of lines would be expensive.  If you have a type
5214
  # that spans more than 2 lines, please use a typedef.
5215
  if linenum > 1:
5216
    previous = None
5217
    if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
5218
      # previous_line\n + ::current_line
5219
      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
5220
                        clean_lines.elided[linenum - 1])
5221
    elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
5222
      # previous_line::\n + current_line
5223
      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
5224
                        clean_lines.elided[linenum - 1])
5225
    if previous:
5226
      line = previous.group(1) + line.lstrip()
5227
    else:
5228
      # Check for templated parameter that is split across multiple lines
5229
      endpos = line.rfind('>')
5230
      if endpos > -1:
5231
        (_, startline, startpos) = ReverseCloseExpression(
5232
            clean_lines, linenum, endpos)
5233
        if startpos > -1 and startline < linenum:
5234
          # Found the matching < on an earlier line, collect all
5235
          # pieces up to current line.
5236
          line = ''
5237
          for i in xrange(startline, linenum + 1):
5238
            line += clean_lines.elided[i].strip()
5239
5240
  # Check for non-const references in function parameters.  A single '&' may
5241
  # found in the following places:
5242
  #   inside expression: binary & for bitwise AND
5243
  #   inside expression: unary & for taking the address of something
5244
  #   inside declarators: reference parameter
5245
  # We will exclude the first two cases by checking that we are not inside a
5246
  # function body, including one that was just introduced by a trailing '{'.
5247
  # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
5248
  if (nesting_state.previous_stack_top and
5249
      not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
5250
           isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
5251
    # Not at toplevel, not within a class, and not within a namespace
5252
    return
5253
5254
  # Avoid initializer lists.  We only need to scan back from the
5255
  # current line for something that starts with ':'.
5256
  #
5257
  # We don't need to check the current line, since the '&' would
5258
  # appear inside the second set of parentheses on the current line as
5259
  # opposed to the first set.
5260
  if linenum > 0:
5261
    for i in xrange(linenum - 1, max(0, linenum - 10), -1):
5262
      previous_line = clean_lines.elided[i]
5263
      if not Search(r'[),]\s*$', previous_line):
5264
        break
5265
      if Match(r'^\s*:\s+\S', previous_line):
5266
        return
5267
5268
  # Avoid preprocessors
5269
  if Search(r'\\\s*$', line):
5270
    return
5271
5272
  # Avoid constructor initializer lists
5273
  if IsInitializerList(clean_lines, linenum):
5274
    return
5275
5276
  # We allow non-const references in a few standard places, like functions
5277
  # called "swap()" or iostream operators like "<<" or ">>".  Do not check
5278
  # those function parameters.
5279
  #
5280
  # We also accept & in static_assert, which looks like a function but
5281
  # it's actually a declaration expression.
5282
  whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
5283
                           r'operator\s*[<>][<>]|'
5284
                           r'static_assert|COMPILE_ASSERT'
5285
                           r')\s*\(')
5286
  if Search(whitelisted_functions, line):
5287
    return
5288
  elif not Search(r'\S+\([^)]*$', line):
5289
    # Don't see a whitelisted function on this line.  Actually we
5290
    # didn't see any function name on this line, so this is likely a
5291
    # multi-line parameter list.  Try a bit harder to catch this case.
5292
    for i in xrange(2):
5293
      if (linenum > i and
5294
          Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
5295
        return
5296
5297
  decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
5298
  for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
5299
    if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
5300
        not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
5301
      error(filename, linenum, 'runtime/references', 2,
5302
            'Is this a non-const reference? '
5303
            'If so, make const or use a pointer: ' +
5304
            ReplaceAll(' *<', '<', parameter))
5305
5306
5307
def CheckCasts(filename, clean_lines, linenum, error):

core/build-support/cpplint.py 1 location

@@ 5168-5304 (lines=137) @@
5165
  return False
5166
5167
5168
def CheckForNonConstReference(filename, clean_lines, linenum,
5169
                              nesting_state, error):
5170
  """Check for non-const references.
5171
5172
  Separate from CheckLanguage since it scans backwards from current
5173
  line, instead of scanning forward.
5174
5175
  Args:
5176
    filename: The name of the current file.
5177
    clean_lines: A CleansedLines instance containing the file.
5178
    linenum: The number of the line to check.
5179
    nesting_state: A NestingState instance which maintains information about
5180
                   the current stack of nested blocks being parsed.
5181
    error: The function to call with any errors found.
5182
  """
5183
  # Do nothing if there is no '&' on current line.
5184
  line = clean_lines.elided[linenum]
5185
  if '&' not in line:
5186
    return
5187
5188
  # If a function is inherited, current function doesn't have much of
5189
  # a choice, so any non-const references should not be blamed on
5190
  # derived function.
5191
  if IsDerivedFunction(clean_lines, linenum):
5192
    return
5193
5194
  # Don't warn on out-of-line method definitions, as we would warn on the
5195
  # in-line declaration, if it isn't marked with 'override'.
5196
  if IsOutOfLineMethodDefinition(clean_lines, linenum):
5197
    return
5198
5199
  # Long type names may be broken across multiple lines, usually in one
5200
  # of these forms:
5201
  #   LongType
5202
  #       ::LongTypeContinued &identifier
5203
  #   LongType::
5204
  #       LongTypeContinued &identifier
5205
  #   LongType<
5206
  #       ...>::LongTypeContinued &identifier
5207
  #
5208
  # If we detected a type split across two lines, join the previous
5209
  # line to current line so that we can match const references
5210
  # accordingly.
5211
  #
5212
  # Note that this only scans back one line, since scanning back
5213
  # arbitrary number of lines would be expensive.  If you have a type
5214
  # that spans more than 2 lines, please use a typedef.
5215
  if linenum > 1:
5216
    previous = None
5217
    if Match(r'\s*::(?:[\w<>]|::)+\s*&\s*\S', line):
5218
      # previous_line\n + ::current_line
5219
      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+[\w<>])\s*$',
5220
                        clean_lines.elided[linenum - 1])
5221
    elif Match(r'\s*[a-zA-Z_]([\w<>]|::)+\s*&\s*\S', line):
5222
      # previous_line::\n + current_line
5223
      previous = Search(r'\b((?:const\s*)?(?:[\w<>]|::)+::)\s*$',
5224
                        clean_lines.elided[linenum - 1])
5225
    if previous:
5226
      line = previous.group(1) + line.lstrip()
5227
    else:
5228
      # Check for templated parameter that is split across multiple lines
5229
      endpos = line.rfind('>')
5230
      if endpos > -1:
5231
        (_, startline, startpos) = ReverseCloseExpression(
5232
            clean_lines, linenum, endpos)
5233
        if startpos > -1 and startline < linenum:
5234
          # Found the matching < on an earlier line, collect all
5235
          # pieces up to current line.
5236
          line = ''
5237
          for i in xrange(startline, linenum + 1):
5238
            line += clean_lines.elided[i].strip()
5239
5240
  # Check for non-const references in function parameters.  A single '&' may
5241
  # found in the following places:
5242
  #   inside expression: binary & for bitwise AND
5243
  #   inside expression: unary & for taking the address of something
5244
  #   inside declarators: reference parameter
5245
  # We will exclude the first two cases by checking that we are not inside a
5246
  # function body, including one that was just introduced by a trailing '{'.
5247
  # TODO(unknown): Doesn't account for 'catch(Exception& e)' [rare].
5248
  if (nesting_state.previous_stack_top and
5249
      not (isinstance(nesting_state.previous_stack_top, _ClassInfo) or
5250
           isinstance(nesting_state.previous_stack_top, _NamespaceInfo))):
5251
    # Not at toplevel, not within a class, and not within a namespace
5252
    return
5253
5254
  # Avoid initializer lists.  We only need to scan back from the
5255
  # current line for something that starts with ':'.
5256
  #
5257
  # We don't need to check the current line, since the '&' would
5258
  # appear inside the second set of parentheses on the current line as
5259
  # opposed to the first set.
5260
  if linenum > 0:
5261
    for i in xrange(linenum - 1, max(0, linenum - 10), -1):
5262
      previous_line = clean_lines.elided[i]
5263
      if not Search(r'[),]\s*$', previous_line):
5264
        break
5265
      if Match(r'^\s*:\s+\S', previous_line):
5266
        return
5267
5268
  # Avoid preprocessors
5269
  if Search(r'\\\s*$', line):
5270
    return
5271
5272
  # Avoid constructor initializer lists
5273
  if IsInitializerList(clean_lines, linenum):
5274
    return
5275
5276
  # We allow non-const references in a few standard places, like functions
5277
  # called "swap()" or iostream operators like "<<" or ">>".  Do not check
5278
  # those function parameters.
5279
  #
5280
  # We also accept & in static_assert, which looks like a function but
5281
  # it's actually a declaration expression.
5282
  whitelisted_functions = (r'(?:[sS]wap(?:<\w:+>)?|'
5283
                           r'operator\s*[<>][<>]|'
5284
                           r'static_assert|COMPILE_ASSERT'
5285
                           r')\s*\(')
5286
  if Search(whitelisted_functions, line):
5287
    return
5288
  elif not Search(r'\S+\([^)]*$', line):
5289
    # Don't see a whitelisted function on this line.  Actually we
5290
    # didn't see any function name on this line, so this is likely a
5291
    # multi-line parameter list.  Try a bit harder to catch this case.
5292
    for i in xrange(2):
5293
      if (linenum > i and
5294
          Search(whitelisted_functions, clean_lines.elided[linenum - i - 1])):
5295
        return
5296
5297
  decls = ReplaceAll(r'{[^}]*}', ' ', line)  # exclude function body
5298
  for parameter in re.findall(_RE_PATTERN_REF_PARAM, decls):
5299
    if (not Match(_RE_PATTERN_CONST_REF_PARAM, parameter) and
5300
        not Match(_RE_PATTERN_REF_STREAM_PARAM, parameter)):
5301
      error(filename, linenum, 'runtime/references', 2,
5302
            'Is this a non-const reference? '
5303
            'If so, make const or use a pointer: ' +
5304
            ReplaceAll(' *<', '<', parameter))
5305
5306
5307
def CheckCasts(filename, clean_lines, linenum, error):