# Copyright (C) 2010 Chris Jerdonek (cjerdonek@webkit.org)
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Supports the parsing of command-line options for check-webkit-style."""

import logging
from optparse import OptionParser
import os.path
import sys

from webkitpy.style.filter import validate_filter_rules
# This module should not import anything from checker.py.

_log = logging.getLogger(__name__)

_USAGE = """usage: %prog [--help] [options] [path1] [path2] ...

Overview:
  Check coding style according to WebKit style guidelines:

      http://webkit.org/coding/coding-style.html

  Path arguments can be files and directories.  If neither a git commit nor
  paths are passed, then all changes in your source control working directory
  are checked.

Style errors:
  This script assigns to every style error a confidence score from 1-5 and
  a category name.  A confidence score of 5 means the error is certainly
  a problem, and 1 means it could be fine.

  Category names appear in error messages in brackets, for example
  [whitespace/indent].  See the options section below for an option that
  displays all available categories and which are reported by default.

Filters:
  Use filters to configure what errors to report.  Filters are specified using
  a comma-separated list of boolean filter rules.  The script reports errors
  in a category if the category passes the filter, as described below.

  All categories start out passing.  Boolean filter rules are then evaluated
  from left to right, with later rules taking precedence.  For example, the
  rule "+foo" passes any category that starts with "foo", and "-foo" fails
  any such category.  The filter input "-whitespace,+whitespace/braces" fails
  the category "whitespace/tab" and passes "whitespace/braces".

  Examples: --filter=-whitespace,+whitespace/braces
            --filter=-whitespace,-runtime/printf,+runtime/printf_format
            --filter=-,+build/include_what_you_use

Paths:
  Certain style-checking behavior depends on the paths relative to
  the WebKit source root of the files being checked.  For example,
  certain types of errors may be handled differently for files in
  WebKit/gtk/webkit/ (e.g. by suppressing "readability/naming" errors
  for files in this directory).

  Consequently, if the path relative to the source root cannot be
  determined for a file being checked, then style checking may not
  work correctly for that file.  This can occur, for example, if no
  WebKit checkout can be found, or if the source root can be detected,
  but one of the files being checked lies outside the source tree.

  If a WebKit checkout can be detected and all files being checked
  are in the source tree, then all paths will automatically be
  converted to paths relative to the source root prior to checking.
  This is also useful for display purposes.

  Currently, this command can detect the source root only if the
  command is run from within a WebKit checkout (i.e. if the current
  working directory is below the root of a checkout).  In particular,
  it is not recommended to run this script from a directory outside
  a checkout.

  Running this script from a top-level WebKit source directory and
  checking only files in the source tree will ensure that all style
  checking behaves correctly -- whether or not a checkout can be
  detected.  This is because all file paths will already be relative
  to the source root and so will not need to be converted."""

_EPILOG = ("This script can miss errors and does not substitute for "
           "code review.")


# This class should not have knowledge of the flag key names.
class DefaultCommandOptionValues(object):

    """Stores the default check-webkit-style command-line options.

    Attributes:
      output_format: A string that is the default output format.
      min_confidence: An integer that is the default minimum confidence level.

    """

    def __init__(self, min_confidence, output_format):
        self.min_confidence = min_confidence
        self.output_format = output_format


# This class should not have knowledge of the flag key names.
class CommandOptionValues(object):

    """Stores the option values passed by the user via the command line.

    Attributes:
      is_verbose: A boolean value of whether verbose logging is enabled.

      filter_rules: The list of filter rules provided by the user.
                    These rules are appended to the base rules and
                    path-specific rules and so take precedence over
                    the base filter rules, etc.

      git_commit: A string representing the git commit to check.
                  The default is None.

      min_confidence: An integer between 1 and 5 inclusive that is the
                      minimum confidence level of style errors to report.
                      The default is 1, which reports all errors.

      output_format: A string that is the output format.  The supported
                     output formats are "emacs" which emacs can parse
                     and "vs7" which Microsoft Visual Studio 7 can parse.

    """
    def __init__(self,
                 filter_rules=None,
                 git_commit=None,
                 diff_files=None,
                 is_verbose=False,
                 min_confidence=1,
                 output_format="emacs",
                 commit_queue=False,
                 git_index=False):
        if filter_rules is None:
            filter_rules = []

        if (min_confidence < 1) or (min_confidence > 5):
            raise ValueError('Invalid "min_confidence" parameter: value '
                             "must be an integer between 1 and 5 inclusive. "
                             'Value given: "%s".' % min_confidence)

        if output_format not in ("emacs", "vs7"):
            raise ValueError('Invalid "output_format" parameter: '
                             'value must be "emacs" or "vs7". '
                             'Value given: "%s".' % output_format)

        self.filter_rules = filter_rules
        self.git_commit = git_commit
        self.diff_files = diff_files
        self.is_verbose = is_verbose
        self.min_confidence = min_confidence
        self.output_format = output_format
        self.commit_queue = commit_queue
        self.git_index = git_index

    # Useful for unit testing.
    def __eq__(self, other):
        """Return whether this instance is equal to another."""
        if self.filter_rules != other.filter_rules:
            return False
        if self.git_commit != other.git_commit:
            return False
        if self.diff_files != other.diff_files:
            return False
        if self.is_verbose != other.is_verbose:
            return False
        if self.min_confidence != other.min_confidence:
            return False
        if self.output_format != other.output_format:
            return False
        if self.git_index != other.git_index:
            return False

        return True

    # Useful for unit testing.
    def __ne__(self, other):
        # Python does not automatically deduce this from __eq__().
        return not self.__eq__(other)


class ArgumentPrinter(object):

    """Supports the printing of check-webkit-style command arguments."""

    def _flag_pair_to_string(self, flag_key, flag_value):
        return '--%(key)s=%(val)s' % {'key': flag_key, 'val': flag_value}

    def to_flag_string(self, options):
        """Return a flag string of the given CommandOptionValues instance.

        This method orders the flag values alphabetically by the flag key.

        Args:
          options: A CommandOptionValues instance.

        """
        flags = {}
        flags['min-confidence'] = options.min_confidence
        flags['output'] = options.output_format
        # Only include the filter flag if user-provided rules are present.
        filter_rules = options.filter_rules
        if filter_rules:
            flags['filter'] = ",".join(filter_rules)
        if options.git_commit:
            flags['git-commit'] = options.git_commit
        if options.diff_files:
            flags['diff_files'] = options.diff_files

        flag_string = ''
        # Alphabetizing lets us unit test this method.
        for key in sorted(flags.keys()):
            flag_string += self._flag_pair_to_string(key, flags[key]) + ' '

        return flag_string.strip()


class ArgumentParser(object):

    # FIXME: Move the documentation of the attributes to the __init__
    #        docstring after making the attributes internal.
    """Supports the parsing of check-webkit-style command arguments.

    Attributes:
      create_usage: A function that accepts a DefaultCommandOptionValues
                    instance and returns a string of usage instructions.
                    Defaults to the function that generates the usage
                    string for check-webkit-style.
      default_options: A DefaultCommandOptionValues instance that provides
                       the default values for options not explicitly
                       provided by the user.
      stderr_write: A function that takes a string as a parameter and
                    serves as stderr.write.  Defaults to sys.stderr.write.
                    This parameter should be specified only for unit tests.

    """

    def __init__(self,
                 all_categories,
                 default_options,
                 base_filter_rules=None,
                 mock_stderr=None,
                 usage=None):
        """Create an ArgumentParser instance.

        Args:
          all_categories: The set of all available style categories.
          default_options: See the corresponding attribute in the class
                           docstring.
        Keyword Args:
          base_filter_rules: The list of filter rules at the beginning of
                             the list of rules used to check style.  This
                             list has the least precedence when checking
                             style and precedes any user-provided rules.
                             The class uses this parameter only for display
                             purposes to the user.  Defaults to the empty list.
          create_usage: See the documentation of the corresponding
                        attribute in the class docstring.
          stderr_write: See the documentation of the corresponding
                        attribute in the class docstring.

        """
        if base_filter_rules is None:
            base_filter_rules = []
        stderr = sys.stderr if mock_stderr is None else mock_stderr
        if usage is None:
            usage = _USAGE

        self._all_categories = all_categories
        self._base_filter_rules = base_filter_rules

        # FIXME: Rename these to reflect that they are internal.
        self.default_options = default_options
        self.stderr_write = stderr.write

        self._parser = self._create_option_parser(stderr=stderr,
            usage=usage,
            default_min_confidence=self.default_options.min_confidence,
            default_output_format=self.default_options.output_format)

    def _create_option_parser(self, stderr, usage,
                              default_min_confidence, default_output_format):
        # Since the epilog string is short, it is not necessary to replace
        # the epilog string with a mock epilog string when testing.
        # For this reason, we use _EPILOG directly rather than passing it
        # as an argument like we do for the usage string.
        parser = OptionParser(usage=usage, epilog=_EPILOG)

        filter_help = ('set a filter to control what categories of style '
                       'errors to report.  Specify a filter using a comma-'
                       'delimited list of boolean filter rules, for example '
                       '"--filter -whitespace,+whitespace/braces".  To display '
                       'all categories and which are enabled by default, pass '
                       """no value (e.g. '-f ""' or '--filter=').""")
        parser.add_option("-f", "--filter-rules", metavar="RULES",
                          dest="filter_value", help=filter_help)

        git_commit_help = ("check all changes in the given commit. "
                           "Use 'commit_id..' to check all changes after commmit_id")
        parser.add_option("-g", "--git-diff", "--git-commit",
                          metavar="COMMIT", dest="git_commit", help=git_commit_help,)

        diff_files_help = "diff the files passed on the command line rather than checking the style of every line"
        parser.add_option("--diff-files", action="store_true", dest="diff_files", default=False, help=diff_files_help)

        min_confidence_help = ("set the minimum confidence of style errors "
                               "to report.  Can be an integer 1-5, with 1 "
                               "displaying all errors.  Defaults to %default.")
        parser.add_option("-m", "--min-confidence", metavar="INT",
                          type="int", dest="min_confidence",
                          default=default_min_confidence,
                          help=min_confidence_help)

        output_format_help = ('set the output format, which can be "emacs" '
                              'or "vs7" (for Visual Studio).  '
                              'Defaults to "%default".')
        parser.add_option("-o", "--output-format", metavar="FORMAT",
                          choices=["emacs", "vs7"],
                          dest="output_format", default=default_output_format,
                          help=output_format_help)

        verbose_help = "enable verbose logging."
        parser.add_option("-v", "--verbose", dest="is_verbose", default=False,
                          action="store_true", help=verbose_help)

        commit_queue_help = "force commit queue to check contributors.json change"
        parser.add_option("--commit-queue", action="store_true", dest="commit_queue", default=False, help=commit_queue_help)
        parser.add_option("--git-index", action="store_true", dest="git_index", default=False, help="Scan staged files only")

        # Override OptionParser's error() method so that option help will
        # also display when an error occurs.  Normally, just the usage
        # string displays and not option help.
        parser.error = self._parse_error

        # Override OptionParser's print_help() method so that help output
        # does not render to the screen while running unit tests.
        print_help = parser.print_help
        parser.print_help = lambda file=stderr: print_help(file=file)

        return parser

    def _parse_error(self, error_message):
        """Print the help string and an error message, and exit."""
        # The method format_help() includes both the usage string and
        # the flag options.
        help = self._parser.format_help()
        # Separate help from the error message with a single blank line.
        self.stderr_write(help + "\n")
        if error_message:
            _log.error(error_message)

        # Since we are using this method to replace/override the Python
        # module optparse's OptionParser.error() method, we match its
        # behavior and exit with status code 2.
        #
        # As additional background, Python documentation says--
        #
        # "Unix programs generally use 2 for command line syntax errors
        #  and 1 for all other kind of errors."
        #
        # (from http://docs.python.org/library/sys.html#sys.exit )
        sys.exit(2)

    def _exit_with_categories(self):
        """Exit and print the style categories and default filter rules."""
        self.stderr_write('\nAll categories:\n')
        for category in sorted(self._all_categories):
            self.stderr_write('    ' + category + '\n')

        self.stderr_write('\nDefault filter rules**:\n')
        for filter_rule in sorted(self._base_filter_rules):
            self.stderr_write('    ' + filter_rule + '\n')
        self.stderr_write('\n**The command always evaluates the above rules, '
                          'and before any --filter flag.\n\n')

        sys.exit(0)

    def _parse_filter_flag(self, flag_value):
        """Parse the --filter flag, and return a list of filter rules.

        Args:
          flag_value: A string of comma-separated filter rules, for
                      example "-whitespace,+whitespace/indent".

        """
        filters = []
        for uncleaned_filter in flag_value.split(','):
            filter = uncleaned_filter.strip()
            if not filter:
                continue
            filters.append(filter)
        return filters

    def parse(self, args):
        """Parse the command line arguments to check-webkit-style.

        Args:
          args: A list of command-line arguments as returned by sys.argv[1:].

        Returns:
          A tuple of (paths, options)

          paths: The list of paths to check.
          options: A CommandOptionValues instance.

        """
        (options, paths) = self._parser.parse_args(args=args)

        filter_value = options.filter_value
        git_commit = options.git_commit
        diff_files = options.diff_files
        is_verbose = options.is_verbose
        min_confidence = options.min_confidence
        output_format = options.output_format
        commit_queue = options.commit_queue
        git_index = options.git_index

        if filter_value is not None and not filter_value:
            # Then the user explicitly passed no filter, for
            # example "-f ''" or "--filter=".
            self._exit_with_categories()

        # Validate user-provided values.

        min_confidence = int(min_confidence)
        if (min_confidence < 1) or (min_confidence > 5):
            self._parse_error('option --min-confidence: invalid integer: '
                              '%s: value must be between 1 and 5'
                              % min_confidence)

        if filter_value:
            filter_rules = self._parse_filter_flag(filter_value)
        else:
            filter_rules = []

        try:
            validate_filter_rules(filter_rules, self._all_categories)
        except ValueError as err:
            self._parse_error(err)

        options = CommandOptionValues(filter_rules=filter_rules,
                                      git_commit=git_commit,
                                      diff_files=diff_files,
                                      is_verbose=is_verbose,
                                      min_confidence=min_confidence,
                                      output_format=output_format,
                                      commit_queue=commit_queue,
                                      git_index=git_index)

        return (paths, options)
