comparison scripts/find_companion.py @ 10:f444739dd8af

Improvements to YCM dynamic flags. - Fallback to a "companion" item (e.g. header/source) or a nearby item when no flags are found for an item. - Finding a "companion" is also exposed as a standalone script. - Ability to pass extra clang flags, including some from a special file found in the .vimcrosoft directory. - Add support for PCH and other forced-include files. - Add options for short/long args, or forcing forward slashes. - Debugging/troubleshooting options, including dumping a batch file and response file to run clang directly, and the ability to auto-load a solution's last known environment when running in command line.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 24 Sep 2020 23:02:16 -0700
parents
children
comparison
equal deleted inserted replaced
9:4ba6df1b2f97 10:f444739dd8af
1 import argparse
2 import logging
3 import os.path
4 import sys
5
6
7 if True: # 'vim' in sys.modules:
8 sys.path.append(os.path.dirname(__file__))
9
10
11 from logutil import setup_logging
12 from vshelpers import load_vimcrosoft_auto_env, find_vimcrosoft_slncache, find_item_project
13 from vsutil import SolutionCache, ITEM_TYPE_CPP_SRC, ITEM_TYPE_CPP_HDR
14
15
16 logger = logging.getLogger(__name__)
17
18
19 def _find_companion_item(solution, item_path, companion_name=None, companion_type=None, slncache=None):
20 # Try to guess the default companion file if needed.
21 if companion_name == None or companion_type == None:
22 primary_name, primary_ext = os.path.splitext(item_path)
23 primary_name = os.path.basename(primary_name)
24 if primary_ext == '.cpp':
25 companion_name = primary_name + '.h'
26 companion_type = ITEM_TYPE_CPP_HDR
27 elif primary_ext == '.h':
28 companion_name = primary_name + '.cpp'
29 companion_type = ITEM_TYPE_CPP_SRC
30 else:
31 raise Exception("Can't guess the companion file for: %s" % item_path)
32
33 # Find the primary file in the solution.
34 cache, proj = find_item_project(item_path, solution, slncache)
35 logger.debug("Found project %s: %s" % (proj.name, proj.abspath))
36
37 # Look for the companion file in that project:
38 candidates = []
39 dfgroup = proj.defaultitemgroup()
40 for cur_item in dfgroup.get_items_of_type(companion_type):
41 cur_item_name = os.path.basename(cur_item.include)
42 if cur_item_name == companion_name:
43 cur_item_path = proj.get_abs_item_include(cur_item)
44 candidates.append((cur_item, _get_companion_score(cur_item_path, item_path)))
45 candidates = sorted(candidates, key=lambda i: i[1], reverse=True)
46 logger.debug("Found candidates: %s" % [(c[0].include, c[1]) for c in candidates])
47 if candidates:
48 return proj.get_abs_item_include(candidates[0][0])
49 return None
50
51
52 def _get_companion_score(item_path, ref_path):
53 for i, c in enumerate(zip(item_path, ref_path)):
54 if c[0] != c[1]:
55 return i
56 return min(len(item_path, ref_path))
57
58
59 def main():
60 parser = argparse.ArgumentParser()
61 parser.add_argument('solution',
62 help="The solution file")
63 parser.add_argument('filename',
64 help="The filename for which to get the companion")
65 parser.add_argument('--no-auto-env',
66 action='store_true',
67 help="Don't read configuration information from Vimcrosoft cache")
68 parser.add_argument('-c', '--cache',
69 help="The solution cache to use")
70 parser.add_argument('-v', '--verbose',
71 action='store_true',
72 help="Show debugging information")
73 args = parser.parse_args()
74 setup_logging(args.verbose)
75
76 build_env = {}
77 slncache = args.cache
78 if not args.no_auto_env:
79 load_vimcrosoft_auto_env(args.solution, build_env)
80 if not slncache:
81 slncache = find_vimcrosoft_slncache(args.solution)
82
83 companion = _find_companion_item(args.solution, args.filename,
84 slncache=slncache)
85 print(companion)
86
87 if __name__ == '__main__':
88 main()