#!/usr/bin/env python

# 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:]))
