Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 137 additions & 65 deletions .ycm_extra_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,36 +28,57 @@
#
# For more information, please refer to <http://unlicense.org/>

import os
import ycm_core
from sysconfig import get_path
import platform
import os.path as p
import subprocess

DIR_OF_THIS_SCRIPT = p.abspath( p.dirname( __file__ ) )
DIR_OF_THIRD_PARTY = p.join( DIR_OF_THIS_SCRIPT, 'third_party' )
DIR_OF_WATCHDOG_DEPS = p.join( DIR_OF_THIRD_PARTY, 'watchdog_deps' )
SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]

database = None

# These are the compilation flags that will be used in case there's no
# compilation database set (by default, one is not set).
# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.
flags = [
'-Wall',
'-Wextra',
# '-Werror',
'-Werror',
'-Wno-long-long',
'-Wno-variadic-macros',
'-fexceptions',
'-DNDEBUG',
# You 100% do NOT need -DUSE_CLANG_COMPLETER in your flags; only the YCM
# source code needs it.
# You 100% do NOT need -DUSE_CLANG_COMPLETER and/or -DYCM_EXPORT in your flags;
# only the YCM source code needs it.
'-DUSE_CLANG_COMPLETER',
# THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't know which
# language to use when compiling headers. So it will guess. Badly. So C++
# headers will be compiled as C headers. You don't want that so ALWAYS specify
# a "-std=<something>".
# For a C project, you would set this to something like 'c99' instead of
# 'c++11'.
'-std=c++17',
# ...and the same thing goes for the magic -x option which specifies the
# language that the files to be compiled are written in. This is mostly
# relevant for c++ headers.
'-DYCM_EXPORT=',
'-DYCM_ABSEIL_SUPPORTED',
# THIS IS IMPORTANT! Without the '-x' flag, Clang won't know which language to
# use when compiling headers. So it will guess. Badly. So C++ headers will be
# compiled as C headers. You don't want that so ALWAYS specify the '-x' flag.
# For a C project, you would set this to 'c' instead of 'c++'.
'-x',
'c++',
'-std=c++17',

# AArch64
'-isystem',
'/usr/include/c++/11',
'-isystem',
'/usr/include/aarch64-linux-gnu/c++/11',
'-isystem',
'/usr/include/c++/11/backward',
'-isystem',
'/usr/lib/gcc/aarch64-linux-gnu/11/include',
'-isystem',
'/usr/local/include',
'-isystem',
'/usr/include/aarch64-linux-gnu',
'-isystem',
'/usr/include',

# c/c++ include path
'-isystem',
Expand All @@ -83,11 +104,7 @@
'-isystem',
'/usr/include/c++/10.2.0',
'-isystem',
'/usr/include',
'-isystem',
'/usr/include/x86_64-linux-gnu',
'-isystem',
'/usr/local/include',

# Termux
'-isystem',
Expand All @@ -98,7 +115,6 @@
'/data/data/com.termux/files/usr/include/c++/v1/experimental',
]


# Set this to the absolute path to the folder (NOT the file!) containing the
# compile_commands.json file to use that instead of 'flags'. See here for
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
Expand All @@ -111,64 +127,120 @@
# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
compilation_database_folder = ''

if os.path.exists( compilation_database_folder ):
database = ycm_core.CompilationDatabase( compilation_database_folder )
else:
database = None

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

def DirectoryOfThisScript():
return os.path.dirname( os.path.abspath( __file__ ) )


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


def GetCompilationInfoForFile( 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.
def FindCorrespondingSourceFile( filename ):
if IsHeaderFile( filename ):
basename = os.path.splitext( filename )[ 0 ]
basename = p.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
if p.exists( replacement_file ):
return replacement_file
return filename


def PathToPythonUsedDuringBuild():
try:
filepath = p.join( DIR_OF_THIS_SCRIPT, 'PYTHON_USED_DURING_BUILDING' )
with open( filepath ) as f:
return f.read().strip()
except OSError:
return None
return database.GetCompilationInfoForFile( filename )


def FlagsForFile( filename, **kwargs ):
if not database:
def Settings( **kwargs ):
# Do NOT import ycm_core at module scope.
import ycm_core

global database
if database is None and p.exists( compilation_database_folder ):
database = ycm_core.CompilationDatabase( compilation_database_folder )

language = kwargs[ 'language' ]

if language == 'cfamily':
# If the file is a header, try to find the corresponding source file and
# retrieve its flags from the compilation database if using one. This is
# necessary since compilation databases don't have entries for header files.
# In addition, use this source file as the translation unit. This makes it
# possible to jump from a declaration in the header file to its definition
# in the corresponding source file.
filename = FindCorrespondingSourceFile( kwargs[ 'filename' ] )

if not database:
return {
'flags': flags,
'include_paths_relative_to_dir': DIR_OF_THIS_SCRIPT,
'override_filename': filename
}

compilation_info = database.GetCompilationInfoForFile( filename )
if not compilation_info.compiler_flags_:
return {}

# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object.
final_flags = list( compilation_info.compiler_flags_ )

# NOTE: This is just for YouCompleteMe; it's highly likely that your project
# does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR
# ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT.
try:
final_flags.remove( '-stdlib=libc++' )
except ValueError:
pass

return {
'flags': flags,
'include_paths_relative_to_dir': DirectoryOfThisScript()
'flags': final_flags,
'include_paths_relative_to_dir': compilation_info.compiler_working_dir_,
'override_filename': filename
}

compilation_info = GetCompilationInfoForFile( filename )
if not compilation_info:
return None
if language == 'python':
return {
'interpreter_path': PathToPythonUsedDuringBuild(),
'ls': {
'python': {
'analysis': {
'extraPaths': [
p.join( DIR_OF_THIS_SCRIPT ),
p.join( DIR_OF_THIRD_PARTY, 'bottle' ),
p.join( DIR_OF_THIRD_PARTY, 'regex-build' ),
p.join( DIR_OF_THIRD_PARTY, 'frozendict' ),
p.join( DIR_OF_THIRD_PARTY, 'jedi_deps', 'jedi' ),
p.join( DIR_OF_THIRD_PARTY, 'jedi_deps', 'parso' ),
p.join( DIR_OF_WATCHDOG_DEPS, 'watchdog', 'build', 'lib3' ),
p.join( DIR_OF_WATCHDOG_DEPS, 'pathtools' ),
p.join( DIR_OF_THIRD_PARTY, 'waitress' )
],
'useLibraryCodeForTypes': True
}
}
}
}

# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object.
final_flags = list( compilation_info.compiler_flags_ )
return {}

# NOTE: This is just for YouCompleteMe; it's highly likely that your project
# does NOT need to remove the stdlib flag. DO NOT USE THIS IN YOUR
# ycm_extra_conf IF YOU'RE NOT 100% SURE YOU NEED IT.
try:
final_flags.remove( '-stdlib=libc++' )
except ValueError:
pass

return {
'flags': final_flags,
'include_paths_relative_to_dir': compilation_info.compiler_working_dir_
}

def PythonSysPath( **kwargs ):
sys_path = kwargs[ 'sys_path' ]

sys_path[ 0:0 ] = [ p.join( DIR_OF_THIS_SCRIPT ),
p.join( DIR_OF_THIRD_PARTY, 'bottle' ),
p.join( DIR_OF_THIRD_PARTY, 'regex-build' ),
p.join( DIR_OF_THIRD_PARTY, 'frozendict' ),
p.join( DIR_OF_THIRD_PARTY, 'jedi_deps', 'jedi' ),
p.join( DIR_OF_THIRD_PARTY, 'jedi_deps', 'parso' ),
p.join( DIR_OF_WATCHDOG_DEPS,
'watchdog',
'build',
'lib3' ),
p.join( DIR_OF_WATCHDOG_DEPS, 'pathtools' ),
p.join( DIR_OF_THIRD_PARTY, 'waitress' ) ]

sys_path.append( p.join( DIR_OF_THIRD_PARTY, 'jedi_deps', 'numpydoc' ) )
return sys_path
Loading