Skip to content

Commit

Permalink
Replace compiler with language flag.
Browse files Browse the repository at this point in the history
Currently, if we have a header file for which its corresponding C++ file exists
in the compilation database, we forget that it's supposed to be a C++ header by
stripping away the compiler. Instead of just stripping it away, we should
replace the compiler with the corresponding language flag.
  • Loading branch information
chaoren committed Oct 9, 2015
1 parent 8d6cf88 commit 9fb379e
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 23 deletions.
31 changes: 22 additions & 9 deletions ycmd/completers/cpp/flags.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ def _CallExtraConfFlagsForFile( module, filename, client_data ):


def PrepareFlagsForClang( flags, filename ):
flags = _CompilerToLanguageFlag( flags )
flags = _RemoveXclangFlags( flags )
flags = _RemoveUnusedFlags( flags, filename )
flags = _SanitizeFlags( flags )
Expand Down Expand Up @@ -187,25 +188,37 @@ def _SanitizeFlags( flags ):
return vector


def _CompilerToLanguageFlag( flags ):
"""When flags come from the compile_commands.json file, the first flag is
usually the path to the compiler that should be invoked. We want to replace
it with a corresponding language flag.
E.g., -x c for gcc and -x c++ for g++."""

# First flag doesn't start with a '-', so it's probably a compiler.
if not flags[ 0 ].startswith( '-' ):

# If the compiler ends with '++', it's probably a C++ compiler
# (E.g., c++, g++, clang++, etc).
if flags[ 0 ].endswith( '++' ):
language = 'c++'
else:
language = 'c'

flags = [ '-x', language ] + flags[ 1: ]

return flags


def _RemoveUnusedFlags( flags, filename ):
"""Given an iterable 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. Same for '-MD' etc.
Also removes the first flag in the list if it does not
start with a '-' (it's highly likely to be the compiler name/path).
We also try to remove any stray filenames in the flags that aren't include
dirs."""

new_flags = []

# When flags come from the compile_commands.json file, the first flag is
# usually the path to the compiler that should be invoked. We want to strip
# that.
if not flags[ 0 ].startswith( '-' ):
flags = flags[ 1: ]

skip_next = False
previous_flag_is_include = False
previous_flag_starts_with_dash = False
Expand Down
45 changes: 31 additions & 14 deletions ycmd/completers/cpp/tests/flags_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,6 @@ def RemoveUnusedFlags_Passthrough_test():
flags._RemoveUnusedFlags( [ '-foo', '-bar' ], 'file' ) )


def RemoveUnusedFlags_RemoveCompilerPathIfFirst_test():
def tester( path ):
eq_( expected,
flags._RemoveUnusedFlags( [ path ] + expected, filename ) )

compiler_paths = [ 'c++', 'c', 'gcc', 'g++', 'clang', 'clang++',
'/usr/bin/c++', '/some/other/path', 'some_command' ]
expected = [ '-foo', '-bar' ]
filename = 'file'

for compiler in compiler_paths:
yield tester, compiler


def RemoveUnusedFlags_RemoveDashC_test():
expected = [ '-foo', '-bar' ]
to_remove = [ '-c' ]
Expand Down Expand Up @@ -189,3 +175,34 @@ def RemoveXclangFlags_test():

eq_( expected + expected,
flags._RemoveXclangFlags( expected + to_remove + expected ) )


def CompilerToLanguageFlag_Passthrough_test():
eq_( [ '-foo', '-bar' ],
flags._CompilerToLanguageFlag( [ '-foo', '-bar' ] ) )


def CompilerToLanguageFlag_ReplaceCCompiler_test():
def tester( path ):
eq_( [ '-x', 'c' ] + expected,
flags._CompilerToLanguageFlag( [ path ] + expected ) )

compiler_paths = [ 'cc', 'gcc', 'clang', '/usr/bin/cc',
'/some/other/path', 'some_command' ]
expected = [ '-foo', '-bar' ]

for compiler in compiler_paths:
yield tester, compiler


def CompilerToLanguageFlag_ReplaceCppCompiler_test():
def tester( path ):
eq_( [ '-x', 'c++' ] + expected,
flags._CompilerToLanguageFlag( [ path ] + expected ) )

compiler_paths = [ 'c++', 'g++', 'clang++', '/usr/bin/c++',
'/some/other/path++', 'some_command++' ]
expected = [ '-foo', '-bar' ]

for compiler in compiler_paths:
yield tester, compiler

0 comments on commit 9fb379e

Please sign in to comment.