# Copyright 2014 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.

class StrictEnumValueChecker(object):
  """Verify that changes to enums are valid.

  This class is used to check enums where reordering or deletion is not allowed,
  and additions must be at the end of the enum, just prior to some "boundary"
  entry. See comments at the top of the "extension_function_histogram_value.h"
  file in chrome/browser/extensions for an example what are considered valid
  changes. There are situations where this class gives false positive warnings,
  i.e. it warns even though the edit is legitimate. Since the class warns using
  prompt warnings, the user can always choose to continue. The main point is to
  attract the attention to all (potentially or not) invalid edits.

  """
  def __init__(self, input_api, output_api, start_marker, end_marker, path):
    self.input_api = input_api
    self.output_api = output_api
    self.start_marker = start_marker
    self.end_marker = end_marker
    self.path = path
    self.results = []

  class EnumRange(object):
    """Represents a range of line numbers (1-based)"""
    def __init__(self, first_line, last_line):
      self.first_line = first_line
      self.last_line = last_line

    def Count(self):
      return self.last_line - self.first_line + 1

    def Contains(self, line_num):
      return self.first_line <= line_num and line_num <= self.last_line

  def LogInfo(self, message):
    self.input_api.logging.info(message)
    return

  def LogDebug(self, message):
    self.input_api.logging.debug(message)
    return

  def ComputeEnumRangeInContents(self, contents):
    """Returns an |EnumRange| object representing the line extent of the
    enum members in |contents|. The line numbers are 1-based,
    compatible with line numbers returned by AffectedFile.ChangeContents().
    |contents| is a list of strings reprenting the lines of a text file.

    If either start_marker or end_marker cannot be found in
    |contents|, returns None and emits detailed warnings about the problem.

    """
    first_enum_line = 0
    last_enum_line = 0
    line_num = 1  # Line numbers are 1-based
    for line in contents:
      if line.startswith(self.start_marker):
        first_enum_line = line_num + 1
      elif line.startswith(self.end_marker):
        last_enum_line = line_num
      line_num += 1

    if first_enum_line == 0:
      self.EmitWarning("The presubmit script could not find the start of the "
                       "enum definition (\"%s\"). Did the enum definition "
                       "change?" % self.start_marker)
      return None

    if last_enum_line == 0:
      self.EmitWarning("The presubmit script could not find the end of the "
                       "enum definition (\"%s\"). Did the enum definition "
                       "change?" % self.end_marker)
      return None

    if first_enum_line >= last_enum_line:
      self.EmitWarning("The presubmit script located the start of the enum "
                       "definition (\"%s\" at line %d) *after* its end "
                       "(\"%s\" at line %d). Something is not quite right."
                       % (self.start_marker, first_enum_line,
                          self.end_marker, last_enum_line))
      return None

    self.LogInfo("Line extent of (\"%s\") enum definition: "
                 "first_line=%d, last_line=%d."
                 % (self.start_marker, first_enum_line, last_enum_line))
    return self.EnumRange(first_enum_line, last_enum_line)

  def ComputeEnumRangeInNewFile(self, affected_file):
    return self.ComputeEnumRangeInContents(affected_file.NewContents())

  def GetLongMessage(self, local_path):
    return str("The file \"%s\" contains the definition of the "
               "(\"%s\") enum which should be edited in specific ways "
               "only - *** read the comments at the top of the header file ***"
               ". There are changes to the file that may be incorrect and "
               "warrant manual confirmation after review. Note that this "
               "presubmit script can not reliably report the nature of all "
               "types of invalid changes, especially when the diffs are "
               "complex. For example, an invalid deletion may be reported "
               "whereas the change contains a valid rename."
               % (local_path, self.start_marker))

  def EmitWarning(self, message, line_number=None, line_text=None):
    """Emits a presubmit prompt warning containing the short message
    |message|. |item| is |LOCAL_PATH| with optional |line_number| and
    |line_text|.

    """
    if line_number is not None and line_text is not None:
      item = "%s(%d): %s" % (self.path, line_number, line_text)
    elif line_number is not None:
      item = "%s(%d)" % (self.path, line_number)
    else:
      item = self.path
    long_message = self.GetLongMessage(self.path)
    self.LogInfo(message)
    self.results.append(
      self.output_api.PresubmitPromptWarning(message, [item], long_message))

  def CollectRangesInsideEnumDefinition(self, affected_file,
                                        first_line, last_line):
    """Returns a list of triplet (line_start, line_end, line_text) of ranges of
    edits changes. The |line_text| part is the text at line |line_start|.
    Since it used only for reporting purposes, we do not need all the text
    lines in the range.

    """
    results = []
    previous_line_number = 0
    previous_range_start_line_number = 0
    previous_range_start_text = ""

    def addRange():
      tuple = (previous_range_start_line_number,
               previous_line_number,
               previous_range_start_text)
      results.append(tuple)

    for line_number, line_text in affected_file.ChangedContents():
      if first_line <= line_number and line_number <= last_line:
        self.LogDebug("Line change at line number " + str(line_number) + ": " +
                      line_text)
        # Start a new interval if none started
        if previous_range_start_line_number == 0:
          previous_range_start_line_number = line_number
          previous_range_start_text = line_text
        # Add new interval if we reached past the previous one
        elif line_number != previous_line_number + 1:
          addRange()
          previous_range_start_line_number = line_number
          previous_range_start_text = line_text
        previous_line_number = line_number

    # Add a last interval if needed
    if previous_range_start_line_number != 0:
        addRange()
    return results

  def CheckForFileDeletion(self, affected_file):
    """Emits a warning notification if file has been deleted """
    if not affected_file.NewContents():
      self.EmitWarning("The file seems to be deleted in the changelist. If "
                       "your intent is to really delete the file, the code in "
                       "PRESUBMIT.py should be updated to remove the "
                       "|StrictEnumValueChecker| class.");
      return False
    return True

  def GetDeletedLinesFromScmDiff(self, affected_file):
    """Return a list of of line numbers (1-based) corresponding to lines
    deleted from the new source file (if they had been present in it). Note
    that if multiple contiguous lines have been deleted, the returned list will
    contain contiguous line number entries. To prevent false positives, we
    return deleted line numbers *only* from diff chunks which decrease the size
    of the new file.

    Note: We need this method because we have access to neither the old file
    content nor the list of "delete" changes from the current presubmit script
    API.

    """
    results = []
    line_num = 0
    deleting_lines = False
    for line in affected_file.GenerateScmDiff().splitlines():
      # Parse the unified diff chunk optional section heading, which looks like
      # @@ -l,s +l,s @@ optional section heading
      m = self.input_api.re.match(
        r"^@@ \-([0-9]+)\,([0-9]+) \+([0-9]+)\,([0-9]+) @@", line)
      if m:
        old_line_num = int(m.group(1))
        old_size = int(m.group(2))
        new_line_num = int(m.group(3))
        new_size = int(m.group(4))
        line_num = new_line_num
        # Return line numbers only from diff chunks decreasing the size of the
        # new file
        deleting_lines = old_size > new_size
        continue
      if not line.startswith("-"):
        line_num += 1
      if deleting_lines and line.startswith("-") and not line.startswith("--"):
        results.append(line_num)
    return results

  def CheckForEnumEntryDeletions(self, affected_file):
    """Look for deletions inside the enum definition. We currently use a
    simple heuristics (not 100% accurate): if there are deleted lines inside
    the enum definition, this might be a deletion.

    """
    range_new = self.ComputeEnumRangeInNewFile(affected_file)
    if not range_new:
      return False

    is_ok = True
    for line_num in self.GetDeletedLinesFromScmDiff(affected_file):
      if range_new.Contains(line_num):
        self.EmitWarning("It looks like you are deleting line(s) from the "
                         "enum definition. This should never happen.",
                         line_num)
        is_ok = False
    return is_ok

  def CheckForEnumEntryInsertions(self, affected_file):
    range = self.ComputeEnumRangeInNewFile(affected_file)
    if not range:
      return False

    first_line = range.first_line
    last_line = range.last_line

    # Collect the range of changes inside the enum definition range.
    is_ok = True
    for line_start, line_end, line_text in \
          self.CollectRangesInsideEnumDefinition(affected_file,
                                                 first_line,
                                                 last_line):
      # The only edit we consider valid is adding 1 or more entries *exactly*
      # at the end of the enum definition. Every other edit inside the enum
      # definition will result in a "warning confirmation" message.
      #
      # TODO(rpaquay): We currently cannot detect "renames" of existing entries
      # vs invalid insertions, so we sometimes will warn for valid edits.
      is_valid_edit = (line_end == last_line - 1)

      self.LogDebug("Edit range in new file at starting at line number %d and "
                    "ending at line number %d: valid=%s"
                    % (line_start, line_end, is_valid_edit))

      if not is_valid_edit:
        self.EmitWarning("The change starting at line %d and ending at line "
                         "%d is *not* located *exactly* at the end of the "
                         "enum definition. Unless you are renaming an "
                         "existing entry, this is not a valid change, as new "
                         "entries should *always* be added at the end of the "
                         "enum definition, right before the \"%s\" "
                         "entry." % (line_start, line_end, self.end_marker),
                         line_start,
                         line_text)
        is_ok = False
    return is_ok

  def PerformChecks(self, affected_file):
    if not self.CheckForFileDeletion(affected_file):
      return
    if not self.CheckForEnumEntryDeletions(affected_file):
      return
    if not self.CheckForEnumEntryInsertions(affected_file):
      return

  def ProcessHistogramValueFile(self, affected_file):
    self.LogInfo("Start processing file \"%s\"" % affected_file.LocalPath())
    self.PerformChecks(affected_file)
    self.LogInfo("Done processing file \"%s\"" % affected_file.LocalPath())

  def Run(self):
    for file in self.input_api.AffectedFiles(include_deletes=True):
      if file.LocalPath() == self.path:
        self.ProcessHistogramValueFile(file)
    return self.results
