comparison scripts/ycm_extra_conf.py @ 0:5d2c0db51914

Initial commit
author Ludovic Chabant <ludovic@chabant.com>
date Tue, 17 Sep 2019 13:24:24 -0700
parents
children f444739dd8af
comparison
equal deleted inserted replaced
-1:000000000000 0:5d2c0db51914
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 vsutil import SolutionCache
13
14
15 logger = logging.getLogger(__name__)
16
17
18 def _build_cflags(filename, solution, buildenv=None, slncache=None):
19 # Load the solution.
20 if not solution:
21 raise Exception(
22 "No solution path was provided in the client data!")
23
24 cache, loaded = SolutionCache.load_or_rebuild(solution, slncache)
25 if not loaded:
26 cache.build_cache()
27
28 # Find the current file in the solution.
29 filename_lower = filename.lower()
30 projpath = None
31 for pp, pi in cache.index.items():
32 if filename_lower in pi:
33 projpath = pp
34 break
35 else:
36 raise Exception("File doesn't belong to the solution: %s" % filename)
37
38 # Find the project that our file belongs to.
39 proj = cache.slnobj.find_project_by_path(projpath)
40 if not proj:
41 raise Exception("Can't find project in solution: %s" % projpath)
42 logger.debug("Found project %s: %s" % (proj.name, proj.abspath))
43
44 # Get the provided config/platform combo, which represent a solution
45 # configuration, and find the corresponding project configuration.
46 # For instance, a solution configuration of "Debug|Win64" could map
47 # to a "MyDebug|AnyCPU" configuration on a specific project.
48 sln_config_platform = '%s|%s' % (buildenv['Configuration'],
49 buildenv['Platform'])
50 proj_config_platform = cache.slnobj.find_project_configuration(
51 proj.guid, sln_config_platform)
52 if not proj_config_platform:
53 raise Exception("Can't find project configuration and platform for "
54 "solution configuration and platform: %s" %
55 sln_config_platform)
56
57 # Make a build environment for the project, and figure out what
58 # kind of project it is.
59 proj_config, proj_platform = proj_config_platform.split('|')
60
61 proj_buildenv = buildenv.copy()
62 proj_buildenv['Configuration'] = proj_config
63 proj_buildenv['Platform'] = proj_platform
64
65 cfggroup = proj.propertygroup('Configuration', proj_buildenv)
66 cfgtype = cfggroup.get('ConfigurationType')
67 if not cfgtype:
68 raise Exception("Can't find configuration type. Did you specify a "
69 "configuration name and platform? Got: %s" %
70 proj_buildenv)
71 logger.debug("Found configuration type: %s" % cfgtype)
72
73 # Let's prepare a list of standard stuff for C++.
74 preproc = []
75 incpaths = []
76 projdir = os.path.dirname(proj.abspath)
77
78 if cfgtype == 'Makefile':
79 # It's a 'Makefile' project, which means we know as little about
80 # compiler flags as whatever information was given to VS. As
81 # such, if the solution setup doesn't give enough info, VS
82 # intellisense won't work, and neither will YouCompleteMe.
83 defaultpropgroup = proj.defaultpropertygroup(proj_buildenv)
84
85 nmake_preproc = defaultpropgroup.get('NMakePreprocessorDefinitions')
86 preproc += nmake_preproc.strip(';').split(';')
87
88 nmake_incpaths = defaultpropgroup.get('NMakeIncludeSearchPath')
89 incpaths += [os.path.abspath(os.path.join(projdir, p))
90 for p in nmake_incpaths.strip(';').split(';')]
91
92 else:
93 # We should definitely support standard VC++ projects here but
94 # I don't need it yet :)
95 raise Exception("Don't know how to handle configuration type: %s" %
96 cfgtype)
97
98 # Build the clang/YCM flags with what we found.
99 flags = ['-x', 'c++'] # TODO: check language type from project file.
100
101 for symbol in preproc:
102 flags.append('-D%s' % symbol)
103 for path in incpaths:
104 if path.startswith("C:\\Program Files"):
105 flags.append('-isystem')
106 else:
107 flags.append('-I')
108 flags.append(path)
109
110 return {'flags': flags}
111
112
113 def _build_env_from_vim(client_data):
114 buildenv = {}
115 buildenv['Configuration'] = client_data.get('g:vimcrosoft_current_config', '')
116 buildenv['Platform'] = client_data.get('g:vimcrosoft_current_platform', '')
117 return buildenv
118
119
120 def Settings(**kwargs):
121 language = kwargs.get('language')
122 filename = kwargs.get('filename')
123
124 client_data = kwargs.get('client_data', {})
125 from_cli = kwargs.get('from_cli', False)
126 if from_cli:
127 solution = client_data.get('solution')
128 slncache = client_data.get('slncache')
129 buildenv = client_data.get('env', {})
130 else:
131 solution = client_data.get('g:vimcrosoft_current_sln')
132 slncache = client_data.get('g:vimcrosoft_current_sln_cache')
133 buildenv = _build_env_from_vim(client_data)
134
135 flags = None
136
137 if language == 'cfamily':
138 try:
139 flags = _build_cflags(filename, solution,
140 buildenv=buildenv, slncache=slncache)
141 except Exception as exc:
142 if from_cli:
143 raise
144 flags = {'error': str(exc)}
145 else:
146 flags = {'error': f"Unknown language: {language}"}
147
148 with open("D:\\P4\\DevEditor\\debug.txt", 'w') as fp:
149 fp.write("kwargs:")
150 fp.write(str(kwargs))
151 fp.write("client_data:")
152 fp.write(str(list(kwargs['client_data'].items())))
153 fp.write("flags:")
154 fp.write(str(flags))
155 return flags
156
157
158 languages = {
159 'cfamily': ['h', 'c', 'hpp', 'cpp', 'inl']
160 }
161
162
163 def _get_language(filename):
164 _, ext = os.path.splitext(filename)
165 ext = ext.lstrip('.')
166 for lang, exts in languages.items():
167 if ext in exts:
168 return lang
169 return None
170
171
172 def main():
173 parser = argparse.ArgumentParser()
174 parser.add_argument('solution',
175 help="The solution file")
176 parser.add_argument('filename',
177 help="The filename for which to get flags")
178 parser.add_argument('-p', '--property',
179 action="append",
180 help="Specifies a build property")
181 parser.add_argument('-c', '--cache',
182 help="The solution cache to use")
183 parser.add_argument('-v', '--verbose',
184 action='store_true',
185 help="Show debugging information")
186 args = parser.parse_args()
187 setup_logging(args.verbose)
188
189 lang = _get_language(args.filename)
190 logger.debug(f"Got language {lang} for {args.filename}")
191
192 build_env = {}
193 if args.property:
194 for p in args.property:
195 pname, pval = p.split('=', 1)
196 build_env[pname] = pval
197 logger.debug(f"Got build environment: {build_env}")
198 client_data = {'solution': args.solution,
199 'slncache': args.cache,
200 'env': build_env}
201
202 params = {'from_cli': True,
203 'language': lang,
204 'filename': args.filename,
205 'client_data': client_data
206 }
207 flags = Settings(**params)
208 logger.info("Flags:")
209 import pprint
210 pp = pprint.PrettyPrinter(indent=2)
211 pp.pprint(flags)
212
213
214 if __name__ == '__main__':
215 main()