# Copied from https://gist.github.com/micbou/f8ed3f8bd6bd24e9f89bef286437306b. Kudos to micbou

import os
import ycm_core


SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]


def IsHeaderFile( filename ):
  extension = os.path.splitext( filename )[ 1 ]
  return extension in [ '.h', '.hxx', '.hpp', '.hh' ]


def GetCompilationInfoForFile( database, 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 IsHeaderFile( 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.GetCompilationInfoForFile(
          replacement_file )
        if compilation_info.compiler_flags_:
          return compilation_info
    return None
  return database.GetCompilationInfoForFile( filename )


def PathsToAllParentFolders( path ):
  folder = os.path.normpath( path )
  if os.path.isdir( folder ):
    yield folder
  while True:
    parent = os.path.dirname( folder )
    if parent == folder:
      break
    folder = parent
    yield folder


def FindCompilationDatabase( filename, compilation_database_folder):
  if os.path.exists(os.path.abspath( compilation_database_folder )):
    return compilation_database_folder

  for folder in PathsToAllParentFolders( filename ):
    compile_commands = os.path.join( folder, compilation_database_folder,
                                     'compile_commands.json' )
    if os.path.exists( compile_commands ):
      return os.path.dirname( compile_commands )
  return None


def FlagsForFile( filename, **kwargs ):
  compilation_database_folder = kwargs[ 'client_data' ].get(
      'g:ycm_compilation_database_folder' )
  if not compilation_database_folder:
    return {}
  
  compilation_database_folder = FindCompilationDatabase(
      filename, compilation_database_folder )
  if not compilation_database_folder:
    return {}

  database = ycm_core.CompilationDatabase( compilation_database_folder )
  if not database.DatabaseSuccessfullyLoaded():
    return {}

  compilation_info = GetCompilationInfoForFile( database, filename )
  if not compilation_info:
    return {}
  
  return {
    'flags': compilation_info.compiler_flags_,
    'include_paths_relative_to_dir': compilation_info.compiler_working_dir_
  }

Add YCM configuration