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.
This commit is contained in:
Strahinja Val Markovic 2013-01-22 16:30:49 -08:00
parent 7b6fa9e409
commit 482de517ba
3 changed files with 42 additions and 10 deletions

View File

@ -60,19 +60,46 @@ def DirectoryOfThisScript():
return os.path.dirname( os.path.abspath( __file__ ) ) return os.path.dirname( os.path.abspath( __file__ ) )
def MakeAbsoluteIfRelativePath( path ): def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
if not path.startswith( '.' ): if not working_directory:
return path 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 ) if make_next_absolute:
return os.path.normpath( full_path ) 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 ): def FlagsForFile( filename ):
if database: if database:
# Bear in mind that database.FlagsForFile does NOT return a python list, but # Bear in mind that database.FlagsForFile does NOT return a python list, but
# a "list-like" StringVec object # 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 # 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 # does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR
@ -82,7 +109,8 @@ def FlagsForFile( filename ):
except ValueError: except ValueError:
pass pass
else: else:
final_flags = [ MakeAbsoluteIfRelativePath( x ) for x in flags ] relative_to = DirectoryOfThisScript()
final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
return { return {
'flags': final_flags, 'flags': final_flags,

View File

@ -17,11 +17,12 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>. # along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import os
# Given an interable object that produces strings (flags for Clang), removes the # 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 # '-c' and '-o' options that Clang does not like to see when it's producing
# completions for a file. # completions for a file.
def PrepareClangFlags( flags ): def PrepareClangFlags( flags, filename ):
new_flags = [] new_flags = []
skip = True skip = True
for flag in flags: for flag in flags:
@ -37,5 +38,8 @@ def PrepareClangFlags( flags ):
skip = True; skip = True;
continue continue
if flag == filename or os.path.realpath(flag) == filename:
continue
new_flags.append( flag ) new_flags.append( flag )
return new_flags return new_flags

View File

@ -39,7 +39,7 @@ class Flags( object ):
try: try:
return self.flags_for_file[ filename ] return self.flags_for_file[ filename ]
except KeyError: except KeyError:
flags_module = self.FlagsModuleForFile( filename ) flags_module = self._FlagsModuleForFile( filename )
if not flags_module: if not flags_module:
return ycm_core.StringVec() return ycm_core.StringVec()
@ -52,7 +52,7 @@ class Flags( object ):
return sanitized_flags return sanitized_flags
def FlagsModuleForFile( self, filename ): def _FlagsModuleForFile( self, filename ):
try: try:
return self.flags_module_for_file[ filename ] return self.flags_module_for_file[ filename ]
except KeyError: except KeyError: