diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py index 95562fbd..d4a9cd71 100644 --- a/.ycm_extra_conf.py +++ b/.ycm_extra_conf.py @@ -1,134 +1,126 @@ -# 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 - import os import ycm_core +# Default flags flags = [ -'-std=c++14', -'-Wall', -'-Wextra', -] + '-std=c++14', + '-Wall', + '-Wextra', -compilation_database_folder = '' + # Relative paths are corrected by MakeRelativePathsInFlagsAbsolute + '-Isrc', + '-Iinclude', + '-Ilib/concurrentqueue/include', + '-Ilib/i3ipcpp/include', + '-Ilib/xpp/include', + '-Itests', -if os.path.exists( compilation_database_folder ): - database = ycm_core.CompilationDatabase( compilation_database_folder ) + '-I/usr/include', + '-I/usr/include/freetype2', + ] + +# Base directory of the project, parent directory of all source files +project_dir = os.path.dirname(os.path.abspath(__file__)) + +# This assumes that everyone coding for this project builds inside the 'build' +# directory +compilation_database_folder = project_dir + "/build" + +if os.path.exists(compilation_database_folder): + database = ycm_core.CompilationDatabase(compilation_database_folder) else: database = None SOURCE_EXTENSIONS = ['.cpp', '.cxx', '.cc', '.c', '.m', '.mm'] -def DirectoryOfThisScript(): - return os.path.dirname( os.path.abspath( __file__ ) ) - -flags.append('-I'+ DirectoryOfThisScript() +'/src') -flags.append('-I'+ DirectoryOfThisScript() +'/include') -flags.append('-I'+ DirectoryOfThisScript() +'/lib/concurrentqueue/include') -flags.append('-I'+ DirectoryOfThisScript() +'/lib/i3ipcpp/include') -flags.append('-I'+ DirectoryOfThisScript() +'/lib/xpp/include') -flags.append('-I'+ DirectoryOfThisScript() +'/tests') -flags.append('-I/usr/include') -flags.append('-I/usr/include/freetype2') - -def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): +# Converts all relative paths in the given flag list to absolute paths with +# working_directory as the base directory +def MakeRelativePathsInFlagsAbsolute(flags, working_directory): if not working_directory: - return list( flags ) + return list(flags) new_flags = [] make_next_absolute = False - path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + 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 = os.path.join( working_directory, flag ) + if not flag.startswith('/'): + new_flag = os.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 ): - path = flag[ len( path_flag ): ] - new_flag = path_flag + os.path.join( working_directory, path ) + if flag.startswith(path_flag): + path = flag[len(path_flag):] + new_flag = path_flag + os.path.join(working_directory, path) break if new_flag: - new_flags.append( new_flag ) + new_flags.append(new_flag) return new_flags -def IsHeaderFile( filename ): - extension = os.path.splitext( filename )[ 1 ] - return extension in [ '.h', '.hxx', '.hpp', '.hh' ] +def IsHeaderFile(filename): + extension = os.path.splitext(filename)[1] + return extension in ['.h', '.hxx', '.hpp', '.hh', ".inl"] -def GetCompilationInfoForFile( 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 IsHeaderFile( filename ): - basename = os.path.splitext( filename )[ 0 ] - for extension in SOURCE_EXTENSIONS: - replacement_file = basename + extension - if os.path.exists( replacement_file ): - compilation_info = database.GetCompilationInfoForFile( - replacement_file ) - if compilation_info.compiler_flags_: - return compilation_info +# Tries to query the compilation database for flags +# For header files it tries to use the flags for a corresponding source file +def GetCompilationInfoForFile(filename): + if not database: return None - return database.GetCompilationInfoForFile( filename ) - -def FlagsForFile( filename, **kwargs ): - # if database: - # # Bear in mind that compilation_info.compiler_flags_ does NOT return a - # # python list, but a "list-like" StringVec object - # compilation_info = GetCompilationInfoForFile( filename ) - # if not compilation_info: - # return None + # The compilation_commands.json file generated by CMake does not have entries + # for header files. We try to use the compile flags used for the corresponding + # source file. # - # final_flags = MakeRelativePathsInFlagsAbsolute( - # compilation_info.compiler_flags_, - # compilation_info.compiler_working_dir_ ) - # - # # NOTE: This is just for YouCompleteMe; it's highly likely that your project - # # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR - # # ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT. - # try: - # final_flags.remove( '-stdlib=libc++' ) - # except ValueError: - # pass - # else: - relative_to = DirectoryOfThisScript() - final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) + # For this try to replace the file extension with an extension that + # corresponds to a source and we also try to replace the 'include' folder in + # the path with 'src' + if IsHeaderFile(filename) : + basename = os.path.splitext(filename)[0] - return { - 'flags': final_flags, - 'do_cache': True - } + # Absolute path of the include and source directories + include_dir = project_dir + "/include" + src_dir = project_dir + "/src" + + # Absolute path without file extension, with the 'include' folder replaced + # with 'src' in the path + src_basename = None + # If the header file is inside the include dir, try to search in the src dir + if basename.startswith(include_dir): + # file path relative to include dir + rel_path_include = os.path.relpath(basename, include_dir) + src_basename = os.path.join(src_dir, rel_path_include) + + for extension in SOURCE_EXTENSIONS: + # A list of all possible replacement files to be searched + replacement_files = [basename + extension] + + if src_basename: + replacement_files.append(src_basename + extension) + + for replacement_file in replacement_files: + if os.path.exists(replacement_file): + comp_info = database.GetCompilationInfoForFile(replacement_file) + if comp_info.compiler_flags_: + return comp_info + return database.GetCompilationInfoForFile(filename) + +def FlagsForFile(filename, **kwargs): + compilation_info = GetCompilationInfoForFile(filename) + if compilation_info and compilation_info.compiler_flags_: + # Bear in mind that compilation_info.compiler_flags_ does NOT return a + # python list, but a "list-like" StringVec object + final_flags = MakeRelativePathsInFlagsAbsolute( + compilation_info.compiler_flags_, + compilation_info.compiler_working_dir_) + else: + # We use default flags if GetCompilationInfoForFile can't find any flags + relative_to = project_dir + final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to) + + return {'flags': final_flags, 'do_cache': True}