| #!/usr/bin/env python3 |
| # Copyright (C) 2013 Danilo Cesar Lemes de Paula <danilo.eu@gmail.com> |
| # Copyright (C) 2014 ChangSeok Oh <shivamidow@gmail.com> |
| # |
| # This library is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU Lesser General Public |
| # License as published by the Free Software Foundation; either |
| # version 2 of the License, or (at your option) any later version. |
| # |
| # This library is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| # Lesser General Public License for more details. |
| # |
| # You should have received a copy of the GNU Lesser General Public |
| # License along with this library; if not, write to the Free Software |
| # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| |
| import os |
| import sys |
| import ycm_core |
| |
| # It's very likely that this script is a symlink somewhere in the WebKit directory, |
| # so we try to find the actual script location so that we can locate the tools |
| # directory. |
| original_file = __file__[:-1] if __file__.endswith(".pyc") else __file__ |
| if os.path.islink(original_file): |
| parent_folder = os.path.abspath(os.path.dirname(original_file)) |
| link_file = os.path.join(parent_folder, os.readlink(original_file)) |
| __tools_directory = os.path.dirname(link_file) |
| else: |
| __tools_directory = os.path.dirname(original_file) |
| |
| top_level_directory = os.path.normpath(os.path.join(os.path.abspath(__tools_directory), '..', '..')) |
| sys.path.insert(0, os.path.join(top_level_directory, 'Tools', 'glib')) |
| import common |
| |
| |
| FLAGS_PRECEDING_PATHS = ['-isystem', '-I', '-iquote', '--sysroot='] |
| def transform_relative_paths_to_absolute_paths(arguments, build_path): |
| result = [] |
| make_next_absolute = False |
| for argument in arguments: |
| if make_next_absolute: |
| make_next_absolute = False |
| if not argument.startswith('/'): |
| argument = os.path.join(build_path, argument) |
| elif argument in FLAGS_PRECEDING_PATHS: |
| # Some flags precede the path in the list. For those we make the |
| # next argument absolute. |
| make_next_absolute = True |
| else: |
| # Some argument contain the flag and the path together. For these |
| # we parse the argument out of the path. |
| for flag in FLAGS_PRECEDING_PATHS: |
| if argument.startswith(flag): |
| argument = flag + os.path.join(build_path, argument[len(flag):]) |
| break |
| |
| result.append(argument) |
| return result |
| |
| |
| def get_build_path(): |
| webkitbuild_path = os.path.join(common.get_build_path(fatal=False), '..') |
| if not os.path.exists(webkitbuild_path): |
| return None |
| |
| release_build_path = os.path.join(webkitbuild_path, 'Release') |
| debug_build_path = os.path.join(webkitbuild_path, 'Debug') |
| |
| try: |
| release_mtime = os.path.getmtime(os.path.join(release_build_path, 'compile_commands.json')) |
| except os.error: |
| release_mtime = 0 |
| try: |
| debug_mtime = os.path.getmtime(os.path.join(debug_build_path, 'compile_commands.json')) |
| except os.error: |
| debug_mtime = 0 |
| |
| return release_build_path if release_mtime >= debug_mtime else debug_build_path |
| |
| |
| def getImplementationFilename(filename): |
| alternative_extensions = ['.cpp', '.c'] |
| for alternative_extension in alternative_extensions: |
| alternative_filename = filename[:-2] + alternative_extension |
| if os.path.exists(alternative_filename): |
| return alternative_filename |
| return None |
| |
| |
| def FlagsForFile(filename, **kwargs): |
| """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. |
| """ |
| |
| result = {'flags': ['-std=c++17', '-x', 'c++'], 'do_cache': True} |
| |
| # Headers can't be built, so we get the source file flags instead. |
| if filename.endswith('.h'): |
| implementationFilename = getImplementationFilename(filename) |
| if implementationFilename: |
| filename = implementationFilename |
| else: |
| if not filename.endswith('Inlines.h'): |
| return result |
| implementationFilename = getImplementationFilename(filename[:-len('Inlines.h')] + '.h') |
| if not implementationFilename: |
| return result |
| filename = implementationFilename |
| # Force config.h file inclusion, for GLib macros. |
| result['flags'].append("-includeconfig.h") |
| |
| build_path = os.path.normpath(get_build_path()) |
| if not build_path: |
| print("Could not find WebKit build path.") |
| return result |
| |
| database = ycm_core.CompilationDatabase(build_path) |
| if not database: |
| print("Could not find compile_commands.json in %s, You might forget to add CMAKE_EXPORT_COMPILE_COMMANDS=ON to cmakeargs" % build_path) |
| return result |
| |
| compilation_info = database.GetCompilationInfoForFile(filename) |
| if not compilation_info: |
| print("No compilation info.") |
| return result |
| |
| result['flags'] = transform_relative_paths_to_absolute_paths(list(compilation_info.compiler_flags_), compilation_info.compiler_working_dir_) |
| return result |
| |
| |
| if __name__ == "__main__": |
| import sys |
| if len(sys.argv) >= 2: |
| print(FlagsForFile(sys.argv[1])) |