# 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.

# Autocompletion config for YouCompleteMe in WebRTC. This is just copied from
# tools/vim in chromium with very minor modifications.
#
# USAGE:
#
#   1. Install YCM [https://github.com/Valloric/YouCompleteMe]
#          (Googlers should check out [go/ycm])
#
#   2. Create a symbolic link to this file called .ycm_extra_conf.py in the
#      directory above your WebRTC checkout (i.e. next to your .gclient file).
#
#          cd src
#          ln -rs tools_webrtc/vim/webrtc.ycm_extra_conf.py \
#          ../.ycm_extra_conf.py
#
#   3. (optional) Whitelist the .ycm_extra_conf.py from step #2 by adding the
#      following to your .vimrc:
#
#          let g:ycm_extra_conf_globlist=['<path to .ycm_extra_conf.py>']
#
#      You can also add other .ycm_extra_conf.py files you want to use to this
#      list to prevent excessive prompting each time you visit a directory
#      covered by a config file.
#
#   4. Profit
#
#
# Usage notes:
#
#   * You must use ninja & clang to build WebRTC.
#
#   * You must have run "gn gen" and built WebRTC recently.
#
#
# Hacking notes:
#
#   * The purpose of this script is to construct an accurate enough command line
#     for YCM to pass to clang so it can build and extract the symbols.
#
#   * Right now, we only pull the -I and -D flags. That seems to be sufficient
#     for everything I've used it for.
#
#   * That whole ninja & clang thing? We could support other configs if someone
#     were willing to write the correct commands and a parser.
#
#   * This has only been tested on gPrecise.


import os
import os.path
import shlex
import subprocess
import sys

# Flags from YCM's default config.
_DEFAULT_FLAGS = [
  '-DUSE_CLANG_COMPLETER',
  '-std=c++11',
  '-x',
  'c++',
]

_HEADER_ALTERNATES = ('.cc', '.cpp', '.c', '.mm', '.m')

_EXTENSION_FLAGS = {
  '.m': ['-x', 'objective-c'],
  '.mm': ['-x', 'objective-c++'],
}

def PathExists(*args):
  return os.path.exists(os.path.join(*args))


def FindWebrtcSrcFromFilename(filename):
  """Searches for the root of the WebRTC checkout.

  Simply checks parent directories until it finds .gclient and src/.

  Args:
    filename: (String) Path to source file being edited.

  Returns:
    (String) Path of 'src/', or None if unable to find.
  """
  curdir = os.path.normpath(os.path.dirname(filename))
  while not (os.path.basename(curdir) == 'src'
             and PathExists(curdir, 'DEPS')
             and (PathExists(curdir, '..', '.gclient')
                  or PathExists(curdir, '.git'))):
    nextdir = os.path.normpath(os.path.join(curdir, '..'))
    if nextdir == curdir:
      return None
    curdir = nextdir
  return curdir


def GetDefaultSourceFile(webrtc_root, filename):
  """Returns the default source file to use as an alternative to |filename|.

  Compile flags used to build the default source file is assumed to be a
  close-enough approximation for building |filename|.

  Args:
    webrtc_root: (String) Absolute path to the root of WebRTC checkout.
    filename: (String) Absolute path to the source file.

  Returns:
    (String) Absolute path to substitute source file.
  """
  if 'test.' in filename:
    return os.path.join(webrtc_root, 'base', 'logging_unittest.cc')
  return os.path.join(webrtc_root, 'base', 'logging.cc')


def GetNinjaBuildOutputsForSourceFile(out_dir, filename):
  """Returns a list of build outputs for filename.

  The list is generated by invoking 'ninja -t query' tool to retrieve a list of
  inputs and outputs of |filename|. This list is then filtered to only include
  .o and .obj outputs.

  Args:
    out_dir: (String) Absolute path to ninja build output directory.
    filename: (String) Absolute path to source file.

  Returns:
    (List of Strings) List of target names. Will return [] if |filename| doesn't
        yield any .o or .obj outputs.
  """
  # Ninja needs the path to the source file relative to the output build
  # directory.
  rel_filename = os.path.relpath(filename, out_dir)

  p = subprocess.Popen(['ninja', '-C', out_dir, '-t', 'query', rel_filename],
                       stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
                       universal_newlines=True)
  stdout, _ = p.communicate()
  if p.returncode != 0:
    return []

  # The output looks like:
  #   ../../relative/path/to/source.cc:
  #     outputs:
  #       obj/reative/path/to/target.source.o
  #       obj/some/other/target2.source.o
  #       another/target.txt
  #
  outputs_text = stdout.partition('\n  outputs:\n')[2]
  output_lines = [line.strip() for line in outputs_text.split('\n')]
  return [target for target in output_lines
          if target and (target.endswith('.o') or target.endswith('.obj'))]


def GetClangCommandLineForNinjaOutput(out_dir, build_target):
  """Returns the Clang command line for building |build_target|

  Asks ninja for the list of commands used to build |filename| and returns the
  final Clang invocation.

  Args:
    out_dir: (String) Absolute path to ninja build output directory.
    build_target: (String) A build target understood by ninja

  Returns:
    (String or None) Clang command line or None if a Clang command line couldn't
        be determined.
  """
  p = subprocess.Popen(['ninja', '-v', '-C', out_dir,
                        '-t', 'commands', build_target],
                       stdout=subprocess.PIPE, universal_newlines=True)
  stdout, _ = p.communicate()
  if p.returncode != 0:
    return None

  # Ninja will return multiple build steps for all dependencies up to
  # |build_target|. The build step we want is the last Clang invocation, which
  # is expected to be the one that outputs |build_target|.
  for line in reversed(stdout.split('\n')):
    if 'clang' in line:
      return line
  return None


def GetClangCommandLineFromNinjaForSource(out_dir, filename):
  """Returns a Clang command line used to build |filename|.

  The same source file could be built multiple times using different tool
  chains. In such cases, this command returns the first Clang invocation. We
  currently don't prefer one toolchain over another. Hopefully the tool chain
  corresponding to the Clang command line is compatible with the Clang build
  used by YCM.

  Args:
    out_dir: (String) Absolute path to WebRTC checkout.
    filename: (String) Absolute path to source file.

  Returns:
    (String or None): Command line for Clang invocation using |filename| as a
        source. Returns None if no such command line could be found.
  """
  build_targets = GetNinjaBuildOutputsForSourceFile(out_dir, filename)
  for build_target in build_targets:
    command_line = GetClangCommandLineForNinjaOutput(out_dir, build_target)
    if command_line:
      return command_line
  return None


def GetClangOptionsFromCommandLine(clang_commandline, out_dir,
                                   additional_flags):
  """Extracts relevant command line options from |clang_commandline|

  Args:
    clang_commandline: (String) Full Clang invocation.
    out_dir: (String) Absolute path to ninja build directory. Relative paths in
        the command line are relative to |out_dir|.
    additional_flags: (List of String) Additional flags to return.

  Returns:
    (List of Strings) The list of command line flags for this source file. Can
    be empty.
  """
  clang_flags = [] + additional_flags

  # Parse flags that are important for YCM's purposes.
  clang_tokens = shlex.split(clang_commandline)
  for flag_index, flag in enumerate(clang_tokens):
    if flag.startswith('-I'):
      # Relative paths need to be resolved, because they're relative to the
      # output dir, not the source.
      if flag[2] == '/':
        clang_flags.append(flag)
      else:
        abs_path = os.path.normpath(os.path.join(out_dir, flag[2:]))
        clang_flags.append('-I' + abs_path)
    elif flag.startswith('-std'):
      clang_flags.append(flag)
    elif flag.startswith('-') and flag[1] in 'DWFfmO':
      if flag == '-Wno-deprecated-register' or flag == '-Wno-header-guard':
        # These flags causes libclang (3.3) to crash. Remove it until things
        # are fixed.
        continue
      clang_flags.append(flag)
    elif flag == '-isysroot':
      # On Mac -isysroot <path> is used to find the system headers.
      # Copy over both flags.
      if flag_index + 1 < len(clang_tokens):
        clang_flags.append(flag)
        clang_flags.append(clang_tokens[flag_index + 1])
    elif flag.startswith('--sysroot='):
      # On Linux we use a sysroot image.
      sysroot_path = flag.lstrip('--sysroot=')
      if sysroot_path.startswith('/'):
        clang_flags.append(flag)
      else:
        abs_path = os.path.normpath(os.path.join(out_dir, sysroot_path))
        clang_flags.append('--sysroot=' + abs_path)
  return clang_flags


def GetClangOptionsFromNinjaForFilename(webrtc_root, filename):
  """Returns the Clang command line options needed for building |filename|.

  Command line options are based on the command used by ninja for building
  |filename|. If |filename| is a .h file, uses its companion .cc or .cpp file.
  If a suitable companion file can't be located or if ninja doesn't know about
  |filename|, then uses default source files in WebRTC for determining the
  commandline.

  Args:
    webrtc_root: (String) Path to src/.
    filename: (String) Absolute path to source file being edited.

  Returns:
    (List of Strings) The list of command line flags for this source file. Can
    be empty.
  """
  if not webrtc_root:
    return []

  # Generally, everyone benefits from including WebRTC's src/, because all of
  # WebRTC's includes are relative to that.
  additional_flags = ['-I' + os.path.join(webrtc_root)]

  # Version of Clang used to compile WebRTC can be newer then version of
  # libclang that YCM uses for completion. So it's possible that YCM's libclang
  # doesn't know about some used warning options, which causes compilation
  # warnings (and errors, because of '-Werror');
  additional_flags.append('-Wno-unknown-warning-option')

  sys.path.append(os.path.join(webrtc_root, 'tools', 'vim'))
  from ninja_output import GetNinjaOutputDirectory
  out_dir = GetNinjaOutputDirectory(webrtc_root)

  basename, extension = os.path.splitext(filename)
  if extension == '.h':
    candidates = [basename + ext for ext in _HEADER_ALTERNATES]
  else:
    candidates = [filename]

  clang_line = None
  buildable_extension = extension
  for candidate in candidates:
    clang_line = GetClangCommandLineFromNinjaForSource(out_dir, candidate)
    if clang_line:
      buildable_extension = os.path.splitext(candidate)[1]
      break

  additional_flags += _EXTENSION_FLAGS.get(buildable_extension, [])

  if not clang_line:
    # If ninja didn't know about filename or it's companion files, then try a
    # default build target. It is possible that the file is new, or build.ninja
    # is stale.
    clang_line = GetClangCommandLineFromNinjaForSource(
        out_dir, GetDefaultSourceFile(webrtc_root, filename))

  if not clang_line:
    return additional_flags

  return GetClangOptionsFromCommandLine(clang_line, out_dir, additional_flags)


def FlagsForFile(filename):
  """This is the main entry point for YCM. Its interface is fixed.

  Args:
    filename: (String) Path to source file being edited.

  Returns:
    (Dictionary)
      'flags': (List of Strings) Command line flags.
      'do_cache': (Boolean) True if the result should be cached.
  """
  abs_filename = os.path.abspath(filename)
  webrtc_root = FindWebrtcSrcFromFilename(abs_filename)
  clang_flags = GetClangOptionsFromNinjaForFilename(webrtc_root, abs_filename)

  # If clang_flags could not be determined, then assume that was due to a
  # transient failure. Preventing YCM from caching the flags allows us to try to
  # determine the flags again.
  should_cache_flags_for_file = bool(clang_flags)

  final_flags = _DEFAULT_FLAGS + clang_flags

  return {
    'flags': final_flags,
    'do_cache': should_cache_flags_for_file
  }
