.ycm_extra_conf.py

1
# This is largely taken from https://github.com/Valloric/ycmd/blob/master/cpp/ycm/.ycm_extra_conf.py
2
3
import os
4
import ycm_core
5
6
# These are the compilation flags that will be used in case there's no
7
# compilation database set (by default, one is not set).
8
flags = [
9
'-Wall',
10
'-Wextra',
11
'-Werror',
12
'-Wc++98-compat',
13
'-Wno-long-long',
14
'-Wno-variadic-macros',
15
'-fexceptions',
16
'-DNDEBUG',
17
# I try to refrain from having to write C++, so c99 is good for me.
18
'-std=c',
19
'-x',
20
'c',
21
'-isystem',
22
'../BoostParts',
23
'-isystem',
24
# This path will only work on OS X, but extra paths that don't exist are not
25
# harmful
26
'/System/Library/Frameworks/Python.framework/Headers',
27
'-isystem',
28
'../llvm/include',
29
'-isystem',
30
'../llvm/tools/clang/include',
31
'-I',
32
'.',
33
'-I',
34
'./ClangCompleter',
35
'-isystem',
36
'./tests/gmock/gtest',
37
'-isystem',
38
'./tests/gmock/gtest/include',
39
'-isystem',
40
'./tests/gmock',
41
'-isystem',
42
'./tests/gmock/include',
43
]
44
45
compilation_database_folder = ''
46
47
if os.path.exists( compilation_database_folder ):
48
  database = ycm_core.CompilationDatabase( compilation_database_folder )
49
else:
50
  database = None
51
52
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]
53
54
def DirectoryOfThisScript():
55
  return os.path.dirname( os.path.abspath( __file__ ) )
56
57
58
def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
59
  if not working_directory:
60
    return list( flags )
61
  new_flags = []
62
  make_next_absolute = False
63
  path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
64
  for flag in flags:
65
    new_flag = flag
66
67
    if make_next_absolute:
68
      make_next_absolute = False
69
      if not flag.startswith( '/' ):
70
        new_flag = os.path.join( working_directory, flag )
71
72
    for path_flag in path_flags:
73
      if flag == path_flag:
74
        make_next_absolute = True
75
        break
76
77
      if flag.startswith( path_flag ):
78
        path = flag[ len( path_flag ): ]
79
        new_flag = path_flag + os.path.join( working_directory, path )
80
        break
81
82
    if new_flag:
83
      new_flags.append( new_flag )
84
  return new_flags
85
86
87
def IsHeaderFile( filename ):
88
  extension = os.path.splitext( filename )[ 1 ]
89
  return extension in [ '.h', '.hxx', '.hpp', '.hh' ]
90
91
92
def GetCompilationInfoForFile( filename ):
93
  # The compilation_commands.json file generated by CMake does not have entries
94
  # for header files. So we do our best by asking the db for flags for a
95
  # corresponding source file, if any. If one exists, the flags for that file
96
  # should be good enough.
97
  if IsHeaderFile( filename ):
98
    basename = os.path.splitext( filename )[ 0 ]
99
    for extension in SOURCE_EXTENSIONS:
100
      replacement_file = basename + extension
101
      if os.path.exists( replacement_file ):
102
        compilation_info = database.GetCompilationInfoForFile(
103
          replacement_file )
104
        if compilation_info.compiler_flags_:
105
          return compilation_info
106
    return None
107
  return database.GetCompilationInfoForFile( filename )
108
109
110
def FlagsForFile( filename, **kwargs ):
111
  if database:
112
    # Bear in mind that compilation_info.compiler_flags_ does NOT return a
113
    # python list, but a "list-like" StringVec object
114
    compilation_info = GetCompilationInfoForFile( filename )
115
    if not compilation_info:
116
      return None
117
118
    final_flags = MakeRelativePathsInFlagsAbsolute(
119
      compilation_info.compiler_flags_,
120
      compilation_info.compiler_working_dir_ )
121
  else:
122
    relative_to = DirectoryOfThisScript()
123
    final_flags = MakeRelativePathsInFlagsAbsolute( flags, relative_to )
124
125
  return {
126
    'flags': final_flags,
127
    'do_cache': True
128
  }
129