#!/usr/bin/env vpython3

# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.

import argparse
import collections
import os
import re
import sys

# TARGET_RE matches a GN target, and extracts the target name and the contents.
TARGET_RE = re.compile(
    r'(?P<indent>\s*)\w+\("(?P<target_name>\w+)"\) {'
    r'(?P<target_contents>.*?)'
    r'(?P=indent)}', re.MULTILINE | re.DOTALL)

# SOURCES_RE matches a block of sources inside a GN target.
SOURCES_RE = re.compile(r'sources \+?= \[(?P<sources>.*?)\]',
                        re.MULTILINE | re.DOTALL)

ERROR_MESSAGE = ("{build_file_path} in target '{target_name}':\n"
                 "  Source file '{source_file}'\n"
                 "  crosses boundary of package '{subpackage}'.")


class PackageBoundaryViolation(
        collections.namedtuple(
            'PackageBoundaryViolation',
            'build_file_path target_name source_file subpackage')):
  def __str__(self):
    return ERROR_MESSAGE.format(**self._asdict())


def _BuildSubpackagesPattern(packages, query):
  """Returns a regular expression that matches source files inside subpackages
  of the given query."""
  query += os.path.sep
  length = len(query)
  pattern = r'\s*"(?P<source_file>(?P<subpackage>'
  pattern += '|'.join(
      re.escape(package[length:].replace(os.path.sep, '/'))
      for package in packages if package.startswith(query))
  pattern += r')/[\w\./]*)"'
  return re.compile(pattern)


def _ReadFileAndPrependLines(file_path):
  """Reads the contents of a file."""
  with open(file_path) as f:
    return "".join(f.readlines())


def _CheckBuildFile(build_file_path, packages):
  """Iterates over all the targets of the given BUILD.gn file, and verifies that
  the source files referenced by it don't belong to any of it's subpackages.
  Returns an iterator over PackageBoundaryViolations for this package.
  """
  package = os.path.dirname(build_file_path)
  subpackages_re = _BuildSubpackagesPattern(packages, package)

  build_file_contents = _ReadFileAndPrependLines(build_file_path)
  for target_match in TARGET_RE.finditer(build_file_contents):
    target_name = target_match.group('target_name')
    target_contents = target_match.group('target_contents')
    for sources_match in SOURCES_RE.finditer(target_contents):
      sources = sources_match.group('sources')
      for subpackages_match in subpackages_re.finditer(sources):
        subpackage = subpackages_match.group('subpackage')
        source_file = subpackages_match.group('source_file')
        if subpackage:
          yield PackageBoundaryViolation(build_file_path, target_name,
                                         source_file, subpackage)


def CheckPackageBoundaries(root_dir, build_files=None):
  packages = [
      root for root, _, files in os.walk(root_dir) if 'BUILD.gn' in files
  ]

  if build_files is not None:
    for build_file_path in build_files:
      assert build_file_path.startswith(root_dir)
  else:
    build_files = [os.path.join(package, 'BUILD.gn') for package in packages]

  messages = []
  for build_file_path in build_files:
    messages.extend(_CheckBuildFile(build_file_path, packages))
  return messages


def main(argv):
  parser = argparse.ArgumentParser(
      description='Script that checks package boundary violations in GN '
      'build files.')

  parser.add_argument('root_dir',
                      metavar='ROOT_DIR',
                      help='The root directory that contains all BUILD.gn '
                      'files to be processed.')
  parser.add_argument('build_files',
                      metavar='BUILD_FILE',
                      nargs='*',
                      help='A list of BUILD.gn files to be processed. If no '
                      'files are given, all BUILD.gn files under ROOT_DIR '
                      'will be processed.')
  parser.add_argument('--max_messages',
                      type=int,
                      default=None,
                      help='If set, the maximum number of violations to be '
                      'displayed.')

  args = parser.parse_args(argv)

  messages = CheckPackageBoundaries(args.root_dir, args.build_files)
  messages = messages[:args.max_messages]

  for i, message in enumerate(messages):
    if i > 0:
      print()
    print(message)

  return bool(messages)


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
