Guest User

Untitled

a guest
Nov 20th, 2018
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.45 KB | None | 0 0
  1. import os
  2. import os.path
  3. import logging
  4. import ycm_core
  5.  
  6. BASE_FLAGS = [
  7. # '-Wall',
  8. # '-Wextra',
  9. # '-Werror',
  10. '-Wno-long-long',
  11. '-Wno-variadic-macros',
  12. '-fexceptions',
  13. '-DNDEBUG',
  14. '-std=c++11',
  15. '-stdlib=libc++',
  16. '-isystem', '/usr/local/include',
  17. '-isystem', '/Library/Developer/CommandLineTools/usr/include/c++/v1',
  18. '-isystem', '/Library/Developer/CommandLineTools/usr/lib/clang/10.0.0/include',
  19. '-isystem', '/Library/Developer/CommandLineTools/usr/include',
  20. '-isystem', '/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include',
  21. '-I', 'include',
  22. '-I.',
  23. '-xc++',
  24. ]
  25.  
  26. SOURCE_EXTENSIONS = [
  27. '.cpp',
  28. '.cxx',
  29. '.cc',
  30. '.c',
  31. '.m',
  32. '.mm'
  33. ]
  34.  
  35. HEADER_EXTENSIONS = [
  36. '.h',
  37. '.hxx',
  38. '.hpp',
  39. '.hh'
  40. ]
  41.  
  42.  
  43. def IsHeaderFile(filename):
  44. extension = os.path.splitext(filename)[1]
  45. return extension in HEADER_EXTENSIONS
  46.  
  47.  
  48. def GetCompilationInfoForFile(database, filename):
  49. if IsHeaderFile(filename):
  50. basename = os.path.splitext(filename)[0]
  51. for extension in SOURCE_EXTENSIONS:
  52. replacement_file = basename + extension
  53. if os.path.exists(replacement_file):
  54. compilation_info = database.GetCompilationInfoForFile(
  55. replacement_file)
  56. if compilation_info.compiler_flags_:
  57. return compilation_info
  58. return None
  59. return database.GetCompilationInfoForFile(filename)
  60.  
  61.  
  62. def FindNearest(path, target, build_folder):
  63. candidate = os.path.join(path, target)
  64. if(os.path.isfile(candidate) or os.path.isdir(candidate)):
  65. logging.info("Found nearest " + target + " at " + candidate)
  66. return candidate
  67.  
  68. parent = os.path.dirname(os.path.abspath(path))
  69. if(parent == path):
  70. raise RuntimeError("Could not find " + target)
  71.  
  72. if(build_folder):
  73. candidate = os.path.join(parent, build_folder, target)
  74. if(os.path.isfile(candidate) or os.path.isdir(candidate)):
  75. logging.info(
  76. "Found nearest " + target +
  77. " in build folder at " + candidate)
  78. return candidate
  79.  
  80. return FindNearest(parent, target, build_folder)
  81.  
  82.  
  83. def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
  84. if not working_directory:
  85. return list(flags)
  86. new_flags = []
  87. make_next_absolute = False
  88. path_flags = ['-isystem', '-I', '-iquote', '--sysroot=']
  89. for flag in flags:
  90. new_flag = flag
  91.  
  92. if make_next_absolute:
  93. make_next_absolute = False
  94. if not flag.startswith('/'):
  95. new_flag = os.path.join(working_directory, flag)
  96.  
  97. for path_flag in path_flags:
  98. if flag == path_flag:
  99. make_next_absolute = True
  100. break
  101.  
  102. if flag.startswith(path_flag):
  103. path = flag[len(path_flag):]
  104. new_flag = path_flag + os.path.join(working_directory, path)
  105. break
  106.  
  107. if new_flag:
  108. new_flags.append(new_flag)
  109. return new_flags
  110.  
  111.  
  112. def FlagsForClangComplete(root):
  113. try:
  114. clang_complete_path = FindNearest(root, '.clang_complete')
  115. clang_complete_flags = open(
  116. clang_complete_path, 'r').read().splitlines()
  117. return clang_complete_flags
  118. except:
  119. return None
  120.  
  121.  
  122. def FlagsForInclude(root):
  123. try:
  124. include_path = FindNearest(root, 'include')
  125. flags = []
  126. for dirroot, dirnames, filenames in os.walk(include_path):
  127. for dir_path in dirnames:
  128. real_path = os.path.join(dirroot, dir_path)
  129. flags = flags + ["-I" + real_path]
  130. return flags
  131. except:
  132. return None
  133.  
  134.  
  135. def FlagsForCompilationDatabase(root, filename):
  136. try:
  137. # Last argument of next function is the name of the build folder for
  138. # out of source projects
  139. compilation_db_path = FindNearest(
  140. root, 'compile_commands.json', 'build')
  141. compilation_db_dir = os.path.dirname(compilation_db_path)
  142. logging.info(
  143. "Set compilation database directory to " + compilation_db_dir)
  144. compilation_db = ycm_core.CompilationDatabase(compilation_db_dir)
  145. if not compilation_db:
  146. logging.info("Compilation database file found but unable to load")
  147. return None
  148. compilation_info = GetCompilationInfoForFile(compilation_db, filename)
  149. if not compilation_info:
  150. logging.info(
  151. "No compilation info for " + filename
  152. + " in compilation database")
  153. return None
  154. return MakeRelativePathsInFlagsAbsolute(
  155. compilation_info.compiler_flags_,
  156. compilation_info.compiler_working_dir_)
  157. except:
  158. return None
  159.  
  160.  
  161. def FlagsForFile(filename):
  162. root = os.path.realpath(filename)
  163. compilation_db_flags = FlagsForCompilationDatabase(root, filename)
  164. if compilation_db_flags:
  165. final_flags = compilation_db_flags
  166. else:
  167. final_flags = BASE_FLAGS
  168. clang_flags = FlagsForClangComplete(root)
  169. if clang_flags:
  170. final_flags = final_flags + clang_flags
  171. include_flags = FlagsForInclude(root)
  172. if include_flags:
  173. final_flags = final_flags + include_flags
  174. return {
  175. 'flags': final_flags,
  176. 'do_cache': True
  177. }
Add Comment
Please, Sign In to add comment