# Copyright 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Top-level presubmit script for Chromium media component.

See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into depot_tools.
"""

import re
import string

# Well-defined simple classes containing only <= 4 ints, or <= 2 floats.
BASE_TIME_TYPES = [
    'base::Time',
    'base::TimeDelta',
    'base::TimeTicks',
]

BASE_TIME_TYPES_RE = re.compile(r'\bconst (%s)&' %
                                string.join(BASE_TIME_TYPES, '|'))

def _FilterFile(affected_file):
  """Return true if the file could contain code requiring a presubmit check."""
  return affected_file.LocalPath().endswith(
      ('.h', '.cc', '.cpp', '.cxx', '.mm'))


def _CheckForUseOfWrongClock(input_api, output_api):
  """Make sure new lines of media code don't use a clock susceptible to skew."""

  # Regular expression that should detect any explicit references to the
  # base::Time type (or base::Clock/DefaultClock), whether in using decls,
  # typedefs, or to call static methods.
  base_time_type_pattern = r'(^|\W)base::(Time|Clock|DefaultClock)(\W|$)'

  # Regular expression that should detect references to the base::Time class
  # members, such as a call to base::Time::Now.
  base_time_member_pattern = r'(^|\W)(Time|Clock|DefaultClock)::'

  # Regular expression to detect "using base::Time" declarations.  We want to
  # prevent these from triggerring a warning.  For example, it's perfectly
  # reasonable for code to be written like this:
  #
  #   using base::Time;
  #   ...
  #   int64_t foo_us = foo_s * Time::kMicrosecondsPerSecond;
  using_base_time_decl_pattern = r'^\s*using\s+(::)?base::Time\s*;'

  # Regular expression to detect references to the kXXX constants in the
  # base::Time class.  We want to prevent these from triggerring a warning.
  base_time_konstant_pattern = r'(^|\W)Time::k\w+'

  problem_re = input_api.re.compile(
      r'(' + base_time_type_pattern + r')|(' + base_time_member_pattern + r')')
  exception_re = input_api.re.compile(
      r'(' + using_base_time_decl_pattern + r')|(' +
      base_time_konstant_pattern + r')')
  problems = []
  for f in input_api.AffectedSourceFiles(_FilterFile):
    for line_number, line in f.ChangedContents():
      if problem_re.search(line):
        if not exception_re.search(line):
          problems.append(
              '  %s:%d\n    %s' % (f.LocalPath(), line_number, line.strip()))

  if problems:
    return [output_api.PresubmitPromptOrNotify(
        'You added one or more references to the base::Time class and/or one\n'
        'of its member functions (or base::Clock/DefaultClock). In media\n'
        'code, it is rarely correct to use a clock susceptible to time skew!\n'
        'Instead, could you use base::TimeTicks to track the passage of\n'
        'real-world time?\n\n' +
        '\n'.join(problems))]
  else:
    return []


def _CheckForMessageLoopProxy(input_api, output_api):
  """Make sure media code only uses MessageLoopProxy for accessing the current
  loop."""

  message_loop_proxy_re = input_api.re.compile(
      r'\bMessageLoopProxy(?!::current\(\))')

  problems = []
  for f in input_api.AffectedSourceFiles(_FilterFile):
    for line_number, line in f.ChangedContents():
      if message_loop_proxy_re.search(line):
        problems.append('%s:%d' % (f.LocalPath(), line_number))

  if problems:
    return [output_api.PresubmitError(
      'MessageLoopProxy should only be used for accessing the current loop.\n'
      'Use the TaskRunner interfaces instead as they are more explicit about\n'
      'the run-time characteristics. In most cases, SingleThreadTaskRunner\n'
      'is a drop-in replacement for MessageLoopProxy.', problems)]

  return []


def _CheckForHistogramOffByOne(input_api, output_api):
  """Make sure histogram enum maxes are used properly"""

  # A general-purpose chunk of regex to match whitespace and/or comments
  # that may be interspersed with the code we're interested in:
  comment = r'/\*.*?\*/|//[^\n]*'
  whitespace = r'(?:[\n\t ]|(?:' + comment + r'))*'

  # The name is assumed to be a literal string.
  histogram_name = r'"[^"]*"'

  # This can be an arbitrary expression, so just ensure it isn't a ; to prevent
  # matching past the end of this statement.
  histogram_value = r'[^;]*'

  # In parens so we can retrieve it for further checks.
  histogram_max = r'([^;,]*)'

  # This should match a uma histogram enumeration macro expression.
  uma_macro_re = input_api.re.compile(
      r'\bUMA_HISTOGRAM_ENUMERATION\(' + whitespace + histogram_name + r',' +
      whitespace + histogram_value + r',' + whitespace + histogram_max +
      whitespace + r'\)' + whitespace + r';(?:' + whitespace +
      r'\/\/ (PRESUBMIT_IGNORE_UMA_MAX))?')

  uma_max_re = input_api.re.compile(r'.*(?:Max|MAX).* \+ 1')

  problems = []

  for f in input_api.AffectedSourceFiles(_FilterFile):
    contents = input_api.ReadFile(f)

    # We want to match across lines, but still report a line number, so we keep
    # track of the line we're on as we search through the file.
    line_number = 1

    # We search the entire file, then check if any violations are in the changed
    # areas, this is inefficient, but simple. A UMA_HISTOGRAM_ENUMERATION call
    # will often span multiple lines, so finding a match looking just at the
    # deltas line-by-line won't catch problems.
    match = uma_macro_re.search(contents)
    while match:
      line_number += contents.count('\n', 0, match.start())
      max_arg = match.group(1) # The third argument.

      if (not uma_max_re.match(max_arg) and match.group(2) !=
          'PRESUBMIT_IGNORE_UMA_MAX'):
        uma_range = range(match.start(), match.end() + 1)
        # Check if any part of the match is in the changed lines:
        for num, line in f.ChangedContents():
          if line_number <= num <= line_number + match.group().count('\n'):
            problems.append('%s:%d' % (f, line_number))
            break

      # Strip off the file contents up to the end of the match and update the
      # line number.
      contents = contents[match.end():]
      line_number += match.group().count('\n')
      match = uma_macro_re.search(contents)

  if problems:
    return [output_api.PresubmitError(
      'UMA_HISTOGRAM_ENUMERATION reports in src/media/ are expected to adhere\n'
      'to the following guidelines:\n'
      ' - The max value (3rd argument) should be an enum value equal to the\n'
      '   last valid value, e.g. FOO_MAX = LAST_VALID_FOO.\n'
      ' - 1 must be added to that max value.\n'
      'Contact rileya@chromium.org if you have questions.' , problems)]

  return []


def _CheckPassByValue(input_api, output_api):
  """Check that base::Time and derived classes are passed by value, and not by
  const reference """

  problems = []

  for f in input_api.AffectedSourceFiles(_FilterFile):
    for line_number, line in f.ChangedContents():
      if BASE_TIME_TYPES_RE.search(line):
        problems.append('%s:%d' % (f, line_number))

  if problems:
    return [output_api.PresubmitError(
      'base::Time and derived classes should be passed by value and not by\n'
      'const ref, see base/time/time.h for more information.', problems)]
  return []


def _CheckChange(input_api, output_api):
  results = []
  results.extend(_CheckForUseOfWrongClock(input_api, output_api))
  results.extend(_CheckForMessageLoopProxy(input_api, output_api))
  results.extend(_CheckPassByValue(input_api, output_api))
  results.extend(_CheckForHistogramOffByOne(input_api, output_api))
  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
  return results


def CheckChangeOnUpload(input_api, output_api):
  return _CheckChange(input_api, output_api)


def CheckChangeOnCommit(input_api, output_api):
  return _CheckChange(input_api, output_api)
