From 01989212f60d0853927544b05129a1bf7badffdb Mon Sep 17 00:00:00 2001 From: Samir Benmendil Date: Fri, 26 Oct 2018 17:24:53 +0100 Subject: [PATCH] vim: do a better job at finding files in compilation database --- vim/ycm_extra_conf.py | 136 ++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 84 deletions(-) diff --git a/vim/ycm_extra_conf.py b/vim/ycm_extra_conf.py index 678f3fb..190cabd 100644 --- a/vim/ycm_extra_conf.py +++ b/vim/ycm_extra_conf.py @@ -40,17 +40,6 @@ SOURCE_EXTENSIONS = [ '.mm' ] -HEADER_EXTENSIONS = [ - '.h', - '.hxx', - '.hpp', - '.hh' -] - - -def similarity_ratio(s, t): - return difflib.SequenceMatcher(a=s.lower(), b=t.lower()).ratio() - def generate_qt_flags(): flags = ['-isystem', '/usr/include/qt/'] @@ -59,42 +48,39 @@ def generate_qt_flags(): return flags +def similarity_ratio(s, t): + return difflib.SequenceMatcher(a=s.lower(), b=t.lower()).ratio() + + def find_similar_file_in_database(dbpath, filename): import json logging.info("Trying to find some file close to: " + filename) - db = json.load(open(dbpath)) + db = json.load(open(dbpath+ "/compile_commands.json")) + best_filename = '' best_ratio = 0 for entry in db: entry_filename = os.path.normpath(os.path.join(entry["directory"], entry["file"])) - ratio = similarity_ratio(str(filename), str(entry_filename)) - if ratio > best_ratio: - best_filename = entry_filename - best_ratio = ratio - return best_filename -def ok_compilation_info(info): - return bool(info.compiler_flags_) + if filename == entry_filename: + logging.info("Found exact match: " + entry_filename) + return entry_filename -def get_compilation_info_for_file(dbpath, database, filename): - info = database.GetCompilationInfoForFile(filename) - if ok_compilation_info(info): - logging.info("Flags for file where found in database: " + filename) - return info - else: - logging.info("Flags for file not found in database: " + filename) basename = os.path.splitext(filename)[0] for extension in SOURCE_EXTENSIONS: replacement_file = basename + extension - logging.info("Trying to replace extension with: " + extension) - info = database.GetCompilationInfoForFile(replacement_file) - if ok_compilation_info(info): - logging.info("Replacing header with: " + replacement_file) - return info - replacement_file = find_similar_file_in_database(dbpath, filename) - logging.info("Replacing header with: " + replacement_file) - return database.GetCompilationInfoForFile(replacement_file) + if entry_filename == replacement_file: + logging.info("Found match: " + replacement_file) + return entry_filename + + ratio = similarity_ratio(str(filename), str(entry_filename)) + if ratio > best_ratio: + best_filename = entry_filename + best_ratio = ratio + + logging.info("Found closest match: " + best_filename) + return best_filename def find_nearest_compilation_database(root='.'): @@ -105,7 +91,8 @@ def find_nearest_compilation_database(root='.'): elif len(dirs) > 1: logging.info("Multiple compilation databases found!") logging.info(dirs) - logging.info("Selecting first: %s" % (dir)) + dirs.sort(key=lambda x: os.stat(x).st_mtime) + logging.info("Selecting newest: %s" % (dirs[0])) return dirs[0] parent = os.path.dirname(os.path.abspath(root)) @@ -130,31 +117,6 @@ def find_nearest(path, target): return find_nearest(parent, target) -def make_relative_paths_in_flags_absolute(flags, working_directory): - if not working_directory: - return list(flags) - new_flags = [] - make_next_absolute = False - path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] - for flag in flags: - new_flag = flag - if make_next_absolute: - make_next_absolute = False - if not flag.startswith('/'): - new_flag = 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): ] - new_flag = path_flag + os.path.join(working_directory, path) - break - if new_flag: - new_flags.append(new_flag) - return new_flags - - def flags_for_include(root): try: include_path = find_nearest(root, 'include') @@ -170,48 +132,54 @@ def flags_for_include(root): return None -def flags_for_compilation_database(root, filename): +def get_compilation_database(root): try: compilation_db_path = find_nearest_compilation_database(root) compilation_db_dir = os.path.dirname(compilation_db_path) logging.info("Set compilation database directory to " + compilation_db_dir) - compilation_db = ycm_core.CompilationDatabase(compilation_db_dir) - if not compilation_db: + db = ycm_core.CompilationDatabase(compilation_db_dir) + if db is None: logging.info("Compilation database file found but unable to load") return None - compilation_info = get_compilation_info_for_file( - compilation_db_path, compilation_db, filename) - if not compilation_info: - logging.info("No compilation info for " + filename + " in compilation database") - return None - return make_relative_paths_in_flags_absolute( - compilation_info.compiler_flags_, - compilation_info.compiler_working_dir_) + return db except Exception as err: - logging.info("Error while trying to get flags for " + filename + " in compilation database") + logging.info("Error while trying to find compilation database: " + root) logging.error(err) return None -def FlagsForFile(filename, **kwargs): - client_data = kwargs['client_data'] - root = client_data['getcwd()'] +def Settings(**kwargs): + if kwargs['language'] != 'cfamily': + return {} - compilation_db_flags = flags_for_compilation_database(root, filename) - if compilation_db_flags: - final_flags = compilation_db_flags + print(kwargs) + client_data = kwargs['client_data'] + root = client_data.get('getcwd()', '.') + filename = kwargs['filename'] + + database = get_compilation_database(root) + if database: + filename = find_similar_file_in_database(database.database_directory, + filename) + compilation_info = database.GetCompilationInfoForFile(filename) + print(compilation_info) + if not compilation_info.compiler_flags_: + return {} #TODO use default flags + final_flags = list(compilation_info.compiler_flags_) + include_path_relative_to_dir = compilation_info.compiler_working_dir_ else: final_flags = BASE_FLAGS include_flags = flags_for_include(root) if include_flags: - final_flags = final_flags + include_flags + final_flags += include_flags + final_flags += generate_qt_flags() + final_flags += ['-I', root, + '-I', root + '/include'] + include_path_relative_to_dir = root - final_flags += generate_qt_flags() - final_flags += [ - '-I', root, - '-I', root + '/include', - ] return { 'flags': final_flags + EXTRA_FLAGS, + 'include_paths_relative_to_dir': include_path_relative_to_dir, + 'override_filename': filename, 'do_cache': True } -- 2.48.1