#!/usr/bin/env python

# This file has been imported into the Kudu source tree from
# the IWYU source tree as of version 0.8
#   https://github.com/include-what-you-use/include-what-you-use/blob/master/iwyu_tool.py
# and corresponding license has been added:
#   https://github.com/include-what-you-use/include-what-you-use/blob/master/LICENSE.TXT
#
# ------------------------------------------------------------------------------
# NOTE: some local Kudu modifications have been made. Before
# "upgrading" this to a new version from upstream, check the git log.
# ------------------------------------------------------------------------------
#
# ==============================================================================
# LLVM Release License
# ==============================================================================
# University of Illinois/NCSA
# Open Source License
#
# Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign.
# All rights reserved.
#
# Developed by:
#
#     LLVM Team
#
#     University of Illinois at Urbana-Champaign
#
#     http://llvm.org
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal with
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is furnished to do
# so, subject to the following conditions:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimers.
#
#     * Redistributions in binary form must reproduce the above copyright notice,
#       this list of conditions and the following disclaimers in the
#       documentation and/or other materials provided with the distribution.
#
#     * Neither the names of the LLVM Team, University of Illinois at
#       Urbana-Champaign, nor the names of its contributors may be used to
#       endorse or promote products derived from this Software without specific
#       prior written permission.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
# SOFTWARE.

""" Driver to consume a Clang compilation database and invoke IWYU.

Example usage with CMake:

  # Unix systems
  $ mkdir build && cd build
  $ CC="clang" CXX="clang++" cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ...
  $ iwyu_tool.py -p .

  # Windows systems
  $ mkdir build && cd build
  $ cmake -DCMAKE_CXX_COMPILER="%VCINSTALLDIR%/bin/cl.exe" \
    -DCMAKE_C_COMPILER="%VCINSTALLDIR%/VC/bin/cl.exe" \
    -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
    -G Ninja ...
  $ python iwyu_tool.py -p .

See iwyu_tool.py -h for more details on command-line arguments.
"""

import argparse
import glob
import json
import multiprocessing
from multiprocessing.pool import ThreadPool
import os
import re
import subprocess
import sys
import unittest
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from kudu_util import get_thirdparty_dir


def iwyu_formatter(output):
    """ Process iwyu's output, basically a no-op. """
    print('\n'.join(output))


CORRECT_RE = re.compile(r'^\((.*?) has correct #includes/fwd-decls\)$')
SHOULD_ADD_RE = re.compile(r'^(.*?) should add these lines:$')
SHOULD_REMOVE_RE = re.compile(r'^(.*?) should remove these lines:$')
FULL_LIST_RE = re.compile(r'The full include-list for (.*?):$')
END_RE = re.compile(r'^---$')
LINES_RE = re.compile(r'^- (.*?)  // lines ([0-9]+)-[0-9]+$')


GENERAL, ADD, REMOVE, LIST = range(4)


def clang_formatter(output):
    """ Process iwyu's output into something clang-like. """
    state = (GENERAL, None)
    for line in output:
        match = CORRECT_RE.match(line)
        if match:
            print('%s:1:1: note: #includes/fwd-decls are correct' % match.groups(1))
            continue
        match = SHOULD_ADD_RE.match(line)
        if match:
            state = (ADD, match.group(1))
            continue
        match = SHOULD_REMOVE_RE.match(line)
        if match:
            state = (REMOVE, match.group(1))
            continue
        match = FULL_LIST_RE.match(line)
        if match:
            state = (LIST, match.group(1))
        elif END_RE.match(line):
            state = (GENERAL, None)
        elif not line.strip():
            continue
        elif state[0] == GENERAL:
            print(line)
        elif state[0] == ADD:
            print('%s:1:1: error: add the following line' % state[1])
            print(line)
        elif state[0] == REMOVE:
            match = LINES_RE.match(line)
            line_no = match.group(2) if match else '1'
            print('%s:%s:1: error: remove the following line' % (state[1], line_no))
            print(match.group(1))


DEFAULT_FORMAT = 'iwyu'
FORMATTERS = {
    'iwyu': iwyu_formatter,
    'clang': clang_formatter
}

def get_output(cwd, args):
    """ Run the given command and return its output as a string. """
    process = subprocess.Popen(args=args,
                               cwd=cwd,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT)
    return process.communicate()[0].decode("utf-8").splitlines()


def run_iwyu(cwd, compile_command, iwyu_args, verbose):
    """ Rewrite compile_command to an IWYU command, and run it. """
    compiler, _, args = compile_command.partition(' ')
    if compiler.endswith('cl.exe'):
        # If the compiler name is cl.exe, let IWYU be cl-compatible
        clang_args = ['--driver-mode=cl']
    else:
        clang_args = []

    extra_args = []
    for a in iwyu_args:
        extra_args += ['-Xiwyu', a]

    cmd_args = ['include-what-you-use'] + clang_args + extra_args + args.split()

    if verbose:
        print('{0}'.format(cmd_args))

    return get_output(cwd, cmd_args)


def workaround_parent_dir_relative_includes(cwd, command):
    """
    Replace any relative include paths in the compilation command
    'command' with the appropriate absolute paths.

    This works around an apparent bug in IWYU in which passing relative
    paths like -I../../src/ result in IWYU not reporting issues that it
    otherwise would report when the corresponding absolute path is
    passed.

    Oddly enough, this is only relevant when using the Ninja generator
    for CMake, which results in relative paths in the -I directives. The
    Makefile generator always produces absolute paths to begin with.
    See https://gitlab.kitware.com/cmake/cmake/issues/17450
    """
    def subber(m):
        return m.group(1) + os.path.abspath(os.path.join(cwd, m.group(2)))
    return re.sub(r'(-isystem |-I\s*)([^/\s]\S+)', subber, command)


class RelativeIncludeTest(unittest.TestCase):
    def test(self):
        f = workaround_parent_dir_relative_includes
        self.assertEquals(f('/foo/bar', 'gcc -isystem relative/dir'),
                          'gcc -isystem /foo/bar/relative/dir')
        self.assertEquals(f('/foo/bar', 'gcc -I relative/dir'),
                          'gcc -I /foo/bar/relative/dir')
        self.assertEquals(f('/foo/bar', 'gcc -Irelative/dir'),
                          'gcc -I/foo/bar/relative/dir')

        self.assertEquals(f('/foo/bar', 'gcc -isystem /abs/dir'),
                          'gcc -isystem /abs/dir')
        self.assertEquals(f('/foo/bar', 'gcc -I /abs/dir'),
                          'gcc -I /abs/dir')
        self.assertEquals(f('/foo/bar', 'gcc -I/abs/dir'),
                          'gcc -I/abs/dir')

def workaround_add_libcpp(build_dir, command):
    """
    Modify 'command' to include C++ standard library headers from the libc++
    found in Kudu's thirdparty tree.

    By default, IWYU will use the system's libstdc++ for standard library
    headers. This is problematic as every system has a different version of
    libstdc++, leading to differing recommendations depending on the host system.

    If we standardize on libc++ from Kudu's thirdparty tree, we can ensure the
    same recommendations regardless of system, though those recommendations will
    change when libc++ is upgraded.
    """
    nostdinc = "-nostdinc++"
    if nostdinc not in command:
        command += " " + nostdinc

    # Check for and add any dynamic (path-based) flags.
    #
    # Some sanitizer builds (like TSAN) already include libc++; if the command
    # already has a flag including libc++, we don't want to add it again.
    path_to_libcpp_prefix = os.path.join(get_thirdparty_dir(), "installed")
    path_to_libcpp_suffix = os.path.join("include", "c++", "v1")
    tp_pattern = os.path.join(path_to_libcpp_prefix, "*", path_to_libcpp_suffix)
    found = False
    for path in glob.glob(tp_pattern):
        search_string = "-isystem " + path
        if search_string in command:
            found = True
            break
    if not found:
        path_to_libcpp = os.path.join(path_to_libcpp_prefix, "uninstrumented",
                                      path_to_libcpp_suffix)
        command += " -isystem " + os.path.abspath(path_to_libcpp)

    return command

def main(compilation_db_path, source_files, verbose, formatter, iwyu_args):
    """ Entry point. """
    # Canonicalize compilation database path
    if os.path.isdir(compilation_db_path):
        compilation_db_path = os.path.join(compilation_db_path,
                                           'compile_commands.json')

    compilation_db_path = os.path.realpath(compilation_db_path)
    if not os.path.isfile(compilation_db_path):
        print('ERROR: No such file or directory: \'%s\'' % compilation_db_path)
        return 1

    # Read compilation db from disk
    with open(compilation_db_path, 'r') as fileobj:
        compilation_db = json.load(fileobj)

    # expand symlinks
    for entry in compilation_db:
        entry['file'] = os.path.realpath(entry['file'])

    # Cross-reference source files with compilation database
    source_files = [os.path.realpath(s) for s in source_files]
    if not source_files:
        # No source files specified, analyze entire compilation database
        entries = compilation_db
    else:
        # Source files specified, analyze the ones appearing in compilation db,
        # warn for the rest.
        entries = []
        for source in source_files:
            matches = [e for e in compilation_db if e['file'] == source]
            if matches:
                entries.extend(matches)
            else:
                print('WARNING: \'%s\' not found in compilation database.' %
                      source)

    # Run analysis
    build_dir = os.path.dirname(compilation_db_path)
    def run_iwyu_task(entry):
        cwd, compile_command = entry['directory'], entry['command']
        compile_command = workaround_parent_dir_relative_includes(
            cwd, compile_command)
        compile_command = workaround_add_libcpp(build_dir, compile_command)
        return run_iwyu(cwd, compile_command, iwyu_args, verbose)
    pool = ThreadPool(multiprocessing.cpu_count())
    try:
        for iwyu_output in pool.imap_unordered(run_iwyu_task, entries):
            formatter(iwyu_output)
    except KeyboardInterrupt as ki:
        sys.exit(1)
    except OSError as why:
        print('ERROR: Failed to launch include-what-you-use: %s' % why)
        return 1
    finally:
        pool.terminate()
        pool.join()
    return 0


def _bootstrap():
    """ Parse arguments and dispatch to main(). """
    # This hackery is necessary to add the forwarded IWYU args to the
    # usage and help strings.
    def customize_usage(parser):
        """ Rewrite the parser's format_usage. """
        original_format_usage = parser.format_usage
        parser.format_usage = lambda: original_format_usage().rstrip() + \
                              ' -- [<IWYU args>]' + os.linesep

    def customize_help(parser):
        """ Rewrite the parser's format_help. """
        original_format_help = parser.format_help

        def custom_help():
            """ Customized help string, calls the adjusted format_usage. """
            helpmsg = original_format_help()
            helplines = helpmsg.splitlines()
            helplines[0] = parser.format_usage().rstrip()
            return os.linesep.join(helplines) + os.linesep

        parser.format_help = custom_help

    # Parse arguments
    parser = argparse.ArgumentParser(
        description='Include-what-you-use compilation database driver.',
        epilog='Assumes include-what-you-use is available on the PATH.')
    customize_usage(parser)
    customize_help(parser)

    parser.add_argument('-v', '--verbose', action='store_true',
                        help='Print IWYU commands')
    parser.add_argument('-o', '--output-format', type=str,
                        choices=FORMATTERS.keys(), default=DEFAULT_FORMAT,
                        help='Output format (default: %s)' % DEFAULT_FORMAT)
    parser.add_argument('-p', metavar='<build-path>', required=True,
                        help='Compilation database path', dest='dbpath')
    parser.add_argument('source', nargs='*',
                        help='Zero or more source files to run IWYU on. '
                        'Defaults to all in compilation database.')

    def partition_args(argv):
        """ Split around '--' into driver args and IWYU args. """
        try:
            double_dash = argv.index('--')
            return argv[:double_dash], argv[double_dash+1:]
        except ValueError:
            return argv, []
    argv, iwyu_args = partition_args(sys.argv[1:])
    args = parser.parse_args(argv)

    sys.exit(main(args.dbpath, args.source, args.verbose,
                  FORMATTERS[args.output_format], iwyu_args))


if __name__ == '__main__':
    _bootstrap()
