]>
git.rmz.io Git - dotfiles.git/blob - vim/ycm_extra_conf.py
77f13b32be6d47cfd747979a4f8dd92be7cbaa62
1 # https://github.com/Valloric/ycmd/blob/master/cpp/ycm/.ycm_extra_conf.py
2 # https://jonasdevlieghere.com/a-better-youcompleteme-config/
3 # https://github.com/arximboldi/dotfiles/blob/master/emacs/.ycm_extra_conf.py
12 # flags used when no compilation_db is found
18 # flags are always added
26 # '-Wno-variadic-macros',
48 def similarity_ratio(s
, t
):
49 return difflib
.SequenceMatcher(a
=s
.lower(), b
=t
.lower()).ratio()
52 def generate_qt_flags():
53 flags
= ['-isystem', '/usr/include/qt/']
54 for p
in glob('/usr/include/qt/*/'):
55 flags
+= ['-isystem', p
]
59 def find_similar_file_in_database(dbpath
, filename
):
61 logging
.info("Trying to find some file close to: " + filename
)
62 db
= json
.load(open(dbpath
))
66 entry_filename
= os
.path
.normpath(os
.path
.join(entry
["directory"],
68 ratio
= similarity_ratio(str(filename
), str(entry_filename
))
69 if ratio
> best_ratio
:
70 best_filename
= entry_filename
74 def ok_compilation_info(info
):
75 return bool(info
.compiler_flags_
)
77 def get_compilation_info_for_file(dbpath
, database
, filename
):
78 info
= database
.GetCompilationInfoForFile(filename
)
79 if ok_compilation_info(info
):
80 logging
.info("Flags for file where found in database: " + filename
)
83 logging
.info("Flags for file not found in database: " + filename
)
84 basename
= os
.path
.splitext(filename
)[0]
85 for extension
in SOURCE_EXTENSIONS
:
86 replacement_file
= basename
+ extension
87 logging
.info("Trying to replace extension with: " + extension
)
88 info
= database
.GetCompilationInfoForFile(replacement_file
)
89 if ok_compilation_info(info
):
90 logging
.info("Replacing header with: " + replacement_file
)
92 replacement_file
= find_similar_file_in_database(dbpath
, filename
)
93 logging
.info("Replacing header with: " + replacement_file
)
94 return database
.GetCompilationInfoForFile(replacement_file
)
97 def find_nearest_compilation_database(root
='.'):
98 dirs
= glob(root
+ '/*/compile_commands.json', recursive
=True)
103 logging
.info("Multiple compilation databases found!")
105 logging
.info("Selecting first: %s" % (dir))
108 parent
= os
.path
.dirname(os
.path
.abspath(root
))
110 raise RuntimeError("Could not find compile_commands.json")
111 return find_nearest_compilation_database(parent
)
114 def find_nearest(path
, target
):
116 os
.path
.join(path
, target
),
117 os
.path
.join(path
, 'build', target
),
118 os
.path
.join(path
, 'output', target
),
120 for candidate
in candidates
:
121 if os
.path
.isfile(candidate
) or os
.path
.isdir(candidate
):
122 logging
.info("Found nearest " + target
+ " at " + candidate
)
124 parent
= os
.path
.dirname(os
.path
.abspath(path
))
126 raise RuntimeError("Could not find " + target
)
127 return find_nearest(parent
, target
)
130 def make_relative_paths_in_flags_absolute(flags
, working_directory
):
131 if not working_directory
:
134 make_next_absolute
= False
135 path_flags
= [ '-isystem', '-I', '-iquote', '--sysroot=' ]
138 if make_next_absolute
:
139 make_next_absolute
= False
140 if not flag
.startswith('/'):
141 new_flag
= os
.path
.join(working_directory
, flag
)
142 for path_flag
in path_flags
:
143 if flag
== path_flag
:
144 make_next_absolute
= True
146 if flag
.startswith(path_flag
):
147 path
= flag
[ len(path_flag
): ]
148 new_flag
= path_flag
+ os
.path
.join(working_directory
, path
)
151 new_flags
.append(new_flag
)
155 def flags_for_include(root
):
157 include_path
= find_nearest(root
, 'include')
159 for dirroot
, dirnames
, filenames
in os
.walk(include_path
):
160 for dir_path
in dirnames
:
161 real_path
= os
.path
.join(dirroot
, dir_path
)
162 flags
= flags
+ ["-I" + real_path
]
164 except Exception as err
:
165 logging
.info("Error while looking flags for includes in root: " + root
)
170 def flags_for_compilation_database(root
, filename
):
172 compilation_db_path
= find_nearest_compilation_database(root
)
173 compilation_db_dir
= os
.path
.dirname(compilation_db_path
)
174 logging
.info("Set compilation database directory to " + compilation_db_dir
)
175 compilation_db
= ycm_core
.CompilationDatabase(compilation_db_dir
)
176 if not compilation_db
:
177 logging
.info("Compilation database file found but unable to load")
179 compilation_info
= get_compilation_info_for_file(
180 compilation_db_path
, compilation_db
, filename
)
181 if not compilation_info
:
182 logging
.info("No compilation info for " + filename
+ " in compilation database")
184 return make_relative_paths_in_flags_absolute(
185 compilation_info
.compiler_flags_
,
186 compilation_info
.compiler_working_dir_
)
187 except Exception as err
:
188 logging
.info("Error while trying to get flags for " + filename
+ " in compilation database")
193 def FlagsForFile(filename
, **kwargs
):
194 client_data
= kwargs
['client_data']
195 root
= client_data
['getcwd()']
197 compilation_db_flags
= flags_for_compilation_database(root
, filename
)
198 if compilation_db_flags
:
199 final_flags
= compilation_db_flags
201 final_flags
= BASE_FLAGS
202 include_flags
= flags_for_include(root
)
204 final_flags
= final_flags
+ include_flags
206 final_flags
+= generate_qt_flags()
209 '-I', root
+ '/include',
212 'flags': final_flags
+ EXTRA_FLAGS
,