From 482de517ba10711f916df4b37f6bcfe69c02cfd4 Mon Sep 17 00:00:00 2001 From: Strahinja Val Markovic Date: Tue, 22 Jan 2013 16:30:49 -0800 Subject: [PATCH] Better support for CompilationDatabase We now use the compilation working directory for a file that is specified in the CompilationDatabase. We don't actually change the working directory of the process, even temporarily (that would be annoying to users); we munge the flags coming from the database so that all the relative paths in them are resolved to absolute ones. --- cpp/ycm/.ycm_clang_options.py | 42 +++++++++++++++++++++----- python/completers/cpp/clang_helpers.py | 6 +++- python/completers/cpp/flags.py | 4 +-- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/cpp/ycm/.ycm_clang_options.py b/cpp/ycm/.ycm_clang_options.py index b72f3058..cfa2b011 100644 --- a/cpp/ycm/.ycm_clang_options.py +++ b/cpp/ycm/.ycm_clang_options.py @@ -60,19 +60,46 @@ def DirectoryOfThisScript(): return os.path.dirname( os.path.abspath( __file__ ) ) -def MakeAbsoluteIfRelativePath( path ): - if not path.startswith( '.' ): - return path +def MakeRelativePathsInFlagsAbsolute( flags, working_directory ): + if not working_directory: + return flags + new_flags = [] + make_next_absolute = False + path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] + for flag in flags: + to_append = flag - full_path = os.path.join( DirectoryOfThisScript(), path ) - return os.path.normpath( full_path ) + if make_next_absolute: + make_next_absolute = False + if not flag.startswith( '/' ): + to_append = 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 ): ] + to_append = path_flag + os.path.join( working_directory, path ) + break + + if to_append: + new_flags.append( to_append ) + return new_flags def FlagsForFile( filename ): if database: # Bear in mind that database.FlagsForFile does NOT return a python list, but # a "list-like" StringVec object - final_flags = PrepareClangFlags( database.FlagsForFile( filename ) ) + working_directory = database.CompileCommandWorkingDirectoryForFile( + filename ) + raw_flags = database.FlagsForFile( filename ) + final_flags = PrepareClangFlags( + MakeRelativePathsInFlagsAbsolute( raw_flags, + working_directory ), + filename ) # 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 @@ -82,7 +109,8 @@ def FlagsForFile( filename ): except ValueError: pass else: - final_flags = [ MakeAbsoluteIfRelativePath( x ) for x in flags ] + relative_to = DirectoryOfThisScript() + final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to ) return { 'flags': final_flags, diff --git a/python/completers/cpp/clang_helpers.py b/python/completers/cpp/clang_helpers.py index 2b598f0f..7e6b7939 100644 --- a/python/completers/cpp/clang_helpers.py +++ b/python/completers/cpp/clang_helpers.py @@ -17,11 +17,12 @@ # You should have received a copy of the GNU General Public License # along with YouCompleteMe. If not, see . +import os # Given an interable object that produces strings (flags for Clang), removes the # '-c' and '-o' options that Clang does not like to see when it's producing # completions for a file. -def PrepareClangFlags( flags ): +def PrepareClangFlags( flags, filename ): new_flags = [] skip = True for flag in flags: @@ -37,5 +38,8 @@ def PrepareClangFlags( flags ): skip = True; continue + if flag == filename or os.path.realpath(flag) == filename: + continue + new_flags.append( flag ) return new_flags diff --git a/python/completers/cpp/flags.py b/python/completers/cpp/flags.py index 6004e113..631e1d3b 100644 --- a/python/completers/cpp/flags.py +++ b/python/completers/cpp/flags.py @@ -39,7 +39,7 @@ class Flags( object ): try: return self.flags_for_file[ filename ] except KeyError: - flags_module = self.FlagsModuleForFile( filename ) + flags_module = self._FlagsModuleForFile( filename ) if not flags_module: return ycm_core.StringVec() @@ -52,7 +52,7 @@ class Flags( object ): return sanitized_flags - def FlagsModuleForFile( self, filename ): + def _FlagsModuleForFile( self, filename ): try: return self.flags_module_for_file[ filename ] except KeyError: