Skip to content

Instantly share code, notes, and snippets.

@kbenzie
Last active July 26, 2017 09:55
Show Gist options
  • Save kbenzie/193a448fee7bb38560c0 to your computer and use it in GitHub Desktop.
Save kbenzie/193a448fee7bb38560c0 to your computer and use it in GitHub Desktop.
YouCompleteMe extra configuration file
# This file is NOT licensed under the GPLv3, which is the license for the rest
# of YouCompleteMe.
#
# Here's the license text for this file:
#
# This is free and unencumbered software released into the public domain.
#
# Anyone is free to copy, modify, publish, use, compile, sell, or
# distribute this software, either in source code form or as a compiled
# binary, for any purpose, commercial or non-commercial, and by any
# means.
#
# In jurisdictions that recognize copyright laws, the author or authors
# of this software dedicate any and all copyright interest in the
# software to the public domain. We make this dedication for the benefit
# of the public at large and to the detriment of our heirs and
# successors. We intend this dedication to be an overt act of
# relinquishment in perpetuity of all present and future rights to this
# software under copyright law.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.
#
# For more information, please refer to <http://unlicense.org/>
"""YouCompleteMe extra configuation."""
from os import path
from platform import system
from subprocess import Popen, PIPE
import ycm_core # pylint: disable=import-error
FLAGS = [
'-Wall',
'-Wextra',
'-Wdocumentation',
'-x',
'c++',
# Add your project specific flags here
'-std=c++11',
'-Iinclude',
]
BUILD_DIRECTORY = 'build'
if path.exists(BUILD_DIRECTORY):
DATABASE = ycm_core.CompilationDatabase(BUILD_DIRECTORY)
else:
DATABASE = None
SYSTEM_FLAGS = []
if system() == 'Linux':
# Linux system include directories are not available in the include
# completer on Linux, so we get them from clang if its installed.
PROCESS = Popen(
'echo | clang -v -E -x c++ -', stdout=PIPE, stderr=PIPE, shell=True)
_, ERR = PROCESS.communicate(input='')
if PROCESS.returncode == 0:
START = False
for line in ERR.splitlines():
if line == '#include <...> search starts here:':
START = True
continue
if line == 'End of search list.':
break
if START:
if 'c++' in line:
SYSTEM_FLAGS += ['-isystem', path.abspath(line.strip())]
def make_include_paths_absolute(flags, working_directory):
"""Make relative flag paths absolute."""
if not working_directory:
return list(flags)
new_flags = []
make_next_absolute = False
path_flags = ['-isystem', '-I', '-iquote', '--sysroot=']
for flag in flags:
new_flag = flag
if make_next_absolute:
make_next_absolute = False
if not flag.startswith('/'):
new_flag = path.join(working_directory, flag)
for path_flag in path_flags:
if flag == path_flag:
make_next_absolute = True
break
if flag.startswith(path_flag):
new_path = flag[len(path_flag):]
new_flag = path_flag + path.join(working_directory, new_path)
break
if new_flag:
new_flags.append(new_flag)
return new_flags
def is_header_file(filename):
"""True if filename is a header, False otherwise."""
extension = path.splitext(filename)[1]
return extension in ['.h', '.hxx', '.hpp', '.hh']
def get_compilation_info_for_file(filename):
"""The compilation_commands.json file generated by CMake does not have
entries for header files. So we do our best by asking the db for flags for
a corresponding source file, if any. If one exists, the flags for that file
should be good enough."""
if is_header_file(filename):
basename = path.splitext(filename)[0]
for extension in ['.cpp', '.cxx', '.cc', '.c', '.m', '.mm', '.h',
'.hpp', '.hh', '.hxx']:
replacement_file = basename + extension
if path.exists(replacement_file):
compilation_info = DATABASE.GetCompilationInfoForFile(
replacement_file)
if compilation_info.compiler_flags_:
return compilation_info
return None
return DATABASE.GetCompilationInfoForFile(filename)
# pylint: disable=invalid-name,unused-argument
def FlagsForFile(filename, **kwargs):
"""Return compilation flags for the file called filename."""
if DATABASE and not is_header_file(filename):
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object
compilation_info = get_compilation_info_for_file(filename)
if not compilation_info:
return None
final_flags = make_include_paths_absolute(
compilation_info.compiler_flags_,
compilation_info.compiler_working_dir_)
else:
relative_to = path.dirname(path.abspath(__file__))
final_flags = make_include_paths_absolute(FLAGS, relative_to)
return {'flags': final_flags + SYSTEM_FLAGS, 'do_cache': True}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment