]> git.rmz.io Git - dotfiles.git/commitdiff
vim: do a better job at finding files in compilation database
authorSamir Benmendil <samir.benmendil@ultrahaptics.com>
Fri, 26 Oct 2018 16:24:53 +0000 (17:24 +0100)
committerSamir Benmendil <samir.benmendil@ultrahaptics.com>
Fri, 26 Oct 2018 16:24:53 +0000 (17:24 +0100)
vim/ycm_extra_conf.py

index 678f3fb7afbd72b904cbc98df38dd51215881a0e..190cabd1908edb2ee78609ac9ad6875193b99430 100644 (file)
@@ -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
     }