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:
parent
7b6fa9e409
commit
482de517ba
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user