From 8173b618dc93bf8e702bc7e4ff5af0542bd1e944 Mon Sep 17 00:00:00 2001
From: Adrien Oliva <aoliva@sefas.com>
Date: Thu, 14 Apr 2022 09:32:01 +0200
Subject: [PATCH] Support YCM vim plugin

Run  once a new file is created to update compilation database
---
 .compile_commands.json | 67 +++++++++++++++++++++++++++++
 .ycm_extra_conf.py     | 96 ++++++++++++++++++++++++++++++++++++++++++
 cmake/00_config.cmake  |  6 +++
 3 files changed, 169 insertions(+)
 create mode 100644 .compile_commands.json
 create mode 100644 .ycm_extra_conf.py

diff --git a/.compile_commands.json b/.compile_commands.json
new file mode 100644
index 0000000..9052385
--- /dev/null
+++ b/.compile_commands.json
@@ -0,0 +1,67 @@
+[
+{
+  "directory": "<bindir>/src",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_gui_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtGui  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit_gui.dir/fcb1010edit_gui_autogen/mocs_compilation.cpp.o -c <bindir>/src/fcb1010edit_gui_autogen/mocs_compilation.cpp",
+  "file": "<bindir>/src/fcb1010edit_gui_autogen/mocs_compilation.cpp"
+},
+{
+  "directory": "<bindir>/src",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_gui_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtGui  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit_gui.dir/Fcb1010Edit.cpp.o -c <srcdir>/src/Fcb1010Edit.cpp",
+  "file": "<srcdir>/src/Fcb1010Edit.cpp"
+},
+{
+  "directory": "<bindir>/src",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_gui_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtGui  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit_gui.dir/mainView.cpp.o -c <srcdir>/src/mainView.cpp",
+  "file": "<srcdir>/src/mainView.cpp"
+},
+{
+  "directory": "<bindir>/src",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit.dir/fcb1010edit_autogen/mocs_compilation.cpp.o -c <bindir>/src/fcb1010edit_autogen/mocs_compilation.cpp",
+  "file": "<bindir>/src/fcb1010edit_autogen/mocs_compilation.cpp"
+},
+{
+  "directory": "<bindir>/src",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/src -I<srcdir>/src -I<bindir>/src/fcb1010edit_autogen/include -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/fcb1010edit.dir/main.cpp.o -c <srcdir>/src/main.cpp",
+  "file": "<srcdir>/src/main.cpp"
+},
+{
+  "directory": "<bindir>/src/controller",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -D__DEBUG -I<bindir>/src/controller -I<srcdir>/src/controller -I<bindir>/src/controller/midi_controller_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/midi_controller.dir/midi_controller_autogen/mocs_compilation.cpp.o -c <bindir>/src/controller/midi_controller_autogen/mocs_compilation.cpp",
+  "file": "<bindir>/src/controller/midi_controller_autogen/mocs_compilation.cpp"
+},
+{
+  "directory": "<bindir>/src/controller",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -D__DEBUG -I<bindir>/src/controller -I<srcdir>/src/controller -I<bindir>/src/controller/midi_controller_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/midi_controller.dir/rtmidi_controller.cpp.o -c <srcdir>/src/controller/rtmidi_controller.cpp",
+  "file": "<srcdir>/src/controller/rtmidi_controller.cpp"
+},
+{
+  "directory": "<bindir>/unittests",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestFcb1010Edit_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestFcb1010Edit.dir/TestFcb1010Edit_autogen/mocs_compilation.cpp.o -c <bindir>/unittests/TestFcb1010Edit_autogen/mocs_compilation.cpp",
+  "file": "<bindir>/unittests/TestFcb1010Edit_autogen/mocs_compilation.cpp"
+},
+{
+  "directory": "<bindir>/unittests",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestFcb1010Edit_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestFcb1010Edit.dir/TestFcb1010Edit.cpp.o -c <srcdir>/unittests/TestFcb1010Edit.cpp",
+  "file": "<srcdir>/unittests/TestFcb1010Edit.cpp"
+},
+{
+  "directory": "<bindir>/unittests",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestMainView_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestMainView.dir/TestMainView_autogen/mocs_compilation.cpp.o -c <bindir>/unittests/TestMainView_autogen/mocs_compilation.cpp",
+  "file": "<bindir>/unittests/TestMainView_autogen/mocs_compilation.cpp"
+},
+{
+  "directory": "<bindir>/unittests",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests\\\" -DQT_TESTLIB_LIB -DQT_WIDGETS_LIB -D__DEBUG -I<bindir>/unittests -I<srcdir>/unittests -I<bindir>/unittests/TestMainView_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtCore -isystem /usr/include/qt6 -isystem /usr/lib/qt6/mkspecs/linux-g++ -isystem /usr/include/qt6/QtWidgets -isystem /usr/include/qt6/QtGui -isystem /usr/include/qt6/QtTest  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -std=gnu++17 -o CMakeFiles/TestMainView.dir/TestMainView.cpp.o -c <srcdir>/unittests/TestMainView.cpp",
+  "file": "<srcdir>/unittests/TestMainView.cpp"
+},
+{
+  "directory": "<bindir>/unittests/mock",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests/mock\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests/mock\\\" -DQT_TESTLIB_LIB -D__DEBUG -Dcontroller_mock_EXPORTS -I<bindir>/unittests/mock -I<srcdir>/unittests/mock -I<bindir>/unittests/mock/controller_mock_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtTest -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -fPIC -std=gnu++17 -o CMakeFiles/controller_mock.dir/controller_mock_autogen/mocs_compilation.cpp.o -c <bindir>/unittests/mock/controller_mock_autogen/mocs_compilation.cpp",
+  "file": "<bindir>/unittests/mock/controller_mock_autogen/mocs_compilation.cpp"
+},
+{
+  "directory": "<bindir>/unittests/mock",
+  "command": "/usr/bin/c++ -DQT_CORE_LIB -DQT_TESTCASE_BUILDDIR=\\\"<bindir>/unittests/mock\\\" -DQT_TESTCASE_SOURCEDIR=\\\"<srcdir>/unittests/mock\\\" -DQT_TESTLIB_LIB -D__DEBUG -Dcontroller_mock_EXPORTS -I<bindir>/unittests/mock -I<srcdir>/unittests/mock -I<bindir>/unittests/mock/controller_mock_autogen/include -I<bindir>/src -I<srcdir>/src -I<srcdir> -isystem /usr/include/qt6/QtTest -isystem /usr/include/qt6 -isystem /usr/include/qt6/QtCore -isystem /usr/lib/qt6/mkspecs/linux-g++  -Wall -Wextra -fdiagnostics-color=always -g --coverage -fPIC -fPIC -std=gnu++17 -o CMakeFiles/controller_mock.dir/controller.cpp.o -c <srcdir>/unittests/mock/controller.cpp",
+  "file": "<srcdir>/unittests/mock/controller.cpp"
+}
+]
\ No newline at end of file
diff --git a/.ycm_extra_conf.py b/.ycm_extra_conf.py
new file mode 100644
index 0000000..23133d7
--- /dev/null
+++ b/.ycm_extra_conf.py
@@ -0,0 +1,96 @@
+import os
+import json
+import typing
+
+
+def get_root_absolute_path() -> str:
+    """Retrieve project root directory."""
+    return os.path.dirname(os.path.abspath(__file__))
+
+
+def get_compile_command_database() -> str:
+    """Retrieve compile_commands file as created by `ycm` target."""
+    return os.path.join(get_root_absolute_path(), '.compile_commands.json')
+
+
+class MyDatabase:
+
+    builddir = os.environ.get('CMAKE_BUILDDIR', os.path.join(
+        get_root_absolute_path(), 'build'
+    ))
+
+    def __init__(self, compile_command_path: str):
+        with open(compile_command_path, 'r', encoding='utf-8') as cc_fh:
+            self.__compile_command = json.load(cc_fh)
+        self.__memo = {}
+
+    def get_info_for_file(
+        self,
+        filename: str
+    ) -> typing.Tuple[str, typing.Iterable[str]]:
+        if filename in self.__memo:
+            return self.__memo[filename]
+
+        absolute_filename = os.path.normpath(os.path.abspath(filename))
+        for entry in self.__compile_command:
+            entry_filename = entry['file']
+            entry_filename = entry_filename.replace(
+                '<srcdir>', get_root_absolute_path()
+            ).replace(
+                '<bindir>', self.builddir
+            )
+            entry_filename = os.path.normpath(entry_filename)
+            if absolute_filename == entry_filename:
+                cwd = entry['directory']
+                flags = [
+                    arg.replace(
+                        '<srcdir>', get_root_absolute_path()
+                    ).replace(
+                        '<bindir>', self.builddir
+                    )
+                    for arg in entry['command'].split(' ')[1:]
+                ]
+                self.__memo[filename] = cwd, flags
+                return self.__memo[filename]
+
+        return os.path.dirname(absolute_filename), []
+
+
+SOURCE_EXTENSIONS = ['.cpp']
+DATABASE = MyDatabase(get_compile_command_database())
+
+
+def is_header_file(filename):
+    extension = os.path.splitext(filename)[1]
+    return extension in ['.h']
+
+
+def get_compilation_info_for_file(filename):
+    """
+    The compilation_commands.json file generated by CMake does not have entries
+    for header files. So we do our best by asking the db for flags for a
+    corresponding source file, if any. If one exists, the flags for that file
+    should be good enough.
+    """
+    if is_header_file(filename):
+        basename = os.path.splitext(filename)[0]
+        for extension in SOURCE_EXTENSIONS:
+            replacement_file = basename + extension
+            if os.path.exists(replacement_file):
+                compilation_info = DATABASE.get_info_for_file(
+                    replacement_file
+                )
+                return compilation_info
+    return DATABASE.get_info_for_file(filename)
+
+
+def FlagsForFile(filename, **kwargs):
+    if DATABASE:
+        # Bear in mind that compilation_info.compiler_flags_ does NOT return a
+        # python list, but a "list-like" StringVec object
+        compilation_info = get_compilation_info_for_file(filename)
+
+    return {
+        'flags': compilation_info[1],
+        'do_cache': True
+    }
diff --git a/cmake/00_config.cmake b/cmake/00_config.cmake
index c44cc49..db6ab03 100644
--- a/cmake/00_config.cmake
+++ b/cmake/00_config.cmake
@@ -24,4 +24,10 @@ if(NOT DEFINED 00_CONFIG_CMAKE)
 
     set(INTERNAL_SOURCE_DIRECTORIES "src")
 
+    # Export compilation command, use to create .ycm_extra_config.py
+    set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+    add_custom_target(ycm
+        COMMAND cp "${CMAKE_BINARY_DIR}/compile_commands.json" "${CMAKE_SOURCE_DIR}/.compile_commands.json"
+        COMMAND sed -i "\"s|${CMAKE_BINARY_DIR}|<bindir>|g;s|${CMAKE_SOURCE_DIR}|<srcdir>|g\"" "${CMAKE_SOURCE_DIR}/.compile_commands.json"
+    )
 endif()
-- 
GitLab