#!/usr/bin/env python3
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Example usage:
$ fx set ...
$ scripts/gn/suppress_errors.py\
--error=-Wconversion
--config="//build/config:Wno-conversion"
"""

import argparse
import fileinput
import multiprocessing
import os
import re
import subprocess
import sys


def run_command(command):
    return subprocess.check_output(
        command, stderr=subprocess.STDOUT, encoding="utf8")


def get_common_gn_args():
    """Retrieve common GN args shared by several commands in this script.
    Returns:
      A list of GN command-line arguments (to be used after "gn <command>").
    """
    return ["out/default"]


def can_have_config(params):
    """Returns whether the given target can have a config.
    If not sure, returns True.
    
    This function is module-level for reasons to do with how Python
    multiprocessing works.
    
    Args:
      params: tuple of target to examine, config to add, is target in Zircon.
              Packed in a single tuple for reasons to do with how Python
              multiprocessing works.
    """

    target, config, _ = params

    desc_command = ["fx", "gn", "desc"]
    desc_command += get_common_gn_args()

    try:
        desc_out = run_command(desc_command + [target, "configs"])
        # Target has configs and they include the given config.
        # Can't add a duplicate config!
        return config not in desc_out
    except subprocess.CalledProcessError as e:
        if 'Don\'t know how to display "configs" for ' in e.output:
            # Target type cannot have configs,
            # or the actual target is in another toolchain.
            # Assume the latter.
            return True
        elif " matches no targets, configs or files" in e.output:
            # The target probably exists in a non-default toolchain.
            # Assume that it can have the config.
            return True
        else:
            raise e


def main():
    parser = argparse.ArgumentParser(
        description="Adds a given config to all compile targets with "
        "a given compiler error")
    parser.add_argument("--error", required=True, help="Compiler error marker")
    parser.add_argument("--config", required=True, help="Config to add")
    parser.add_argument("--comment", help="Comment to add before config")
    args = parser.parse_args()
    error = args.error
    config = args.config
    comment = args.comment

    # Harvest all compilation errors
    print("Building...")
    try:
        # On error continue building to discover all failures
        run_command(["fx", "build", "-k0"])
        print("Build successful!")
        return 0
    except subprocess.CalledProcessError as e:
        build_out = e.output
    error_regex = re.compile(
        "(?:../)*([^:]*):\d*:\d*: error: .*" + re.escape(error))
    error_files = set()
    for line in build_out.splitlines():
        match = error_regex.match(line)
        if match:
            path = os.path.normpath(match.group(1))
            error_files.add(path)
    print("Sources with compilation errors:")
    print("\n".join(sorted(error_files)))
    print()
    if not error_files:
        return 0

    # Collect all BUILD.gn files with targets referencing failing sources
    print("Resolving references...")
    outdir = "out/default"
    refs_command = ["fx", "gn", "refs"]
    refs_command += get_common_gn_args(False)
    refs_command += sorted(error_files)
    try:
        refs_out = run_command(refs_command)
    except subprocess.CalledProcessError as e:
        print("Failed to resolve references!")
        print(e.output)
        return 1
    target_no_toolchain = re.compile("(\/\/[^:]*:[^(]*)(?:\(.*\))?")
    error_targets = {
        target_no_toolchain.match(ref).group(1)
        for ref in refs_out.splitlines()
    }

    # Remove targets that already have the given config
    # or can't have a config in the first place
    print("Removing irrelevant targets...")
    # `gn desc` is slow so parallelize
    with multiprocessing.Pool(multiprocessing.cpu_count()) as p:
        target_can_have = zip(
            error_targets,
            p.map(
                can_have_config,
                ((target, config, False) for target in error_targets)),
        )
        error_targets = {
            target for target, can_have in target_can_have if can_have
        }

    print("Failing targets:")
    print("\n".join(sorted(error_targets)))
    print()

    # Fix failing targets
    ref_regex = re.compile("//([^:]*):([^.(]*).*")
    for target in sorted(error_targets):
        match = ref_regex.match(target)
        build_dir, target_name = match.groups()
        target_regex = re.compile(
            '^\s*\w*\("' + re.escape(target_name) + '"\) {')
        build_file = os.path.join(build_dir, "BUILD.gn")
        # Format file before processing
        run_command(["fx", "format-code", "--files=" + build_file])
        print("Fixing", target)
        in_target = False
        config_printed = False
        in_configs = False
        curly_brace_depth = 0
        secondary_build_file = os.path.join("build", "secondary", build_file)
        if os.path.exists(secondary_build_file):
            # Sometimes we put third_party BUILD.gn files in a shadow directory
            # to avoid conflicting with original BUILD.gn files.
            build_file = secondary_build_file
        start_configs_inline = re.compile('configs \+?= \[ "')
        start_configs = re.compile("configs \+?= \[")

        for line in fileinput.FileInput(build_file, inplace=True):
            curly_brace_depth += line.count("{") - line.count("}")
            assert curly_brace_depth >= 0
            if config_printed:
                # We already printed the config, keep running until we exit the target
                if curly_brace_depth == target_end_depth:
                    in_target = False
            elif not in_target:
                # Try to enter target
                in_target = bool(target_regex.match(line))
                if in_target:
                    target_end_depth = curly_brace_depth - 1
            elif curly_brace_depth > target_end_depth + 1:
                # Ignore inner blocks such as inner definitions and conditionals
                pass
            elif curly_brace_depth == target_end_depth:
                # Last chance to print config before exiting
                if comment:
                    print("#", comment)
                print('configs += [ "' + config + '"]')
                config_printed = True
                in_target = False
            elif start_configs_inline.match(line) and config in line:
                config_printed = True
            elif start_configs_inline.match(line):
                line = line[:-3] + ', "' + config + '" ]\n'
                config_printed = True
            elif start_configs.match(line):
                in_configs = True
            elif in_configs and line.strip() == '"' + config + '",':
                in_configs = False
                config_printed = True
            elif in_configs and line.strip() == "]":
                if comment:
                    print("#", comment)
                print('"' + config + '",')
                in_configs = False
                config_printed = True
            print(line, end="")
            if config_printed and not in_target:
                # Reset for a possible redefinition of the same target
                # (e.g. within another conditional block)
                config_printed = False
        run_command(["fx", "format-code", "--files=" + build_file])

    print("Fixed all of:")
    for error_target in sorted(error_targets):
        print('  "' + error_target + '",')

    return 0


if __name__ == "__main__":
    sys.exit(main())
