maps_mobile_idl.py 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. import os
  2. import re
  3. from collections import namedtuple
  4. from _common import sort_by_keywords
  5. Framework = namedtuple(
  6. 'Framework', ['cpp_namespace_tokens', 'java_class_path', 'objc_framework_name', 'objc_framework_prefix']
  7. )
  8. def _get_proto_header_file(proto_file_name):
  9. return proto_file_name.split('.')[0] + '.pb.h'
  10. def _get_appended_values(unit, key):
  11. value = []
  12. raw_value = unit.get(key)
  13. if raw_value:
  14. value = filter(lambda x: len(x) > 0, raw_value.split(' '))
  15. assert len(value) == 0 or value[0] == '$' + key
  16. return value[1:] if len(value) > 0 else value
  17. def _load_framework_file_list(unit):
  18. frameworks = [
  19. unit.resolve(unit.resolve_arc_path(os.sep.join(path.split(os.sep)[1:])))
  20. for path in unit.get('MAPKIT_IDL_FRAMEWORK_FILES').split(' ')
  21. ]
  22. return frameworks
  23. def _require_framework_entry(entry, framework):
  24. if entry not in framework:
  25. raise Exception('No {} entry in {} framework'.format(entry, framework))
  26. def _read_framework(unit, framework_file):
  27. file_path = unit.resolve(framework_file)
  28. result = {}
  29. with open(file_path, 'r') as f:
  30. lineId = 0
  31. for line in f:
  32. lineId += 1
  33. tokens = line.split('=')
  34. if len(tokens) != 2:
  35. raise Exception('Malformed idl framework file {} line {}'.format(framework_file, lineId))
  36. result[tokens[0].strip()] = tokens[1].strip()
  37. _require_framework_entry('CPP_NAMESPACE', result)
  38. _require_framework_entry('JAVA_PACKAGE', result)
  39. _require_framework_entry('OBJC_FRAMEWORK', result)
  40. _require_framework_entry('OBJC_FRAMEWORK_PREFIX', result)
  41. return Framework(
  42. result['CPP_NAMESPACE'].split('.'),
  43. result['JAVA_PACKAGE'],
  44. result['OBJC_FRAMEWORK'],
  45. result['OBJC_FRAMEWORK_PREFIX'],
  46. )
  47. def _read_frameworks(unit):
  48. framework_file_list = _load_framework_file_list(unit)
  49. result = {}
  50. for file_name in framework_file_list:
  51. name = file_name.split(os.sep)[-1].split('.')[0]
  52. result[name] = _read_framework(unit, file_name)
  53. return result
  54. def _extract_by_regexp(line, regexp):
  55. re_match = regexp.search(line)
  56. if not re_match:
  57. return None
  58. return re_match.group(1)
  59. class RegExp:
  60. OBJC_INFIX = r'\bobjc_infix\s*([^\s]+);'
  61. IMPORT = r'^import\s+"([^"]+)"'
  62. WEAK_INTERFACE = r'\bweak_ref\s+interface\b'
  63. SHARED_INTERFACE = r'\bshared_ref\s+interface\b'
  64. STRONG_INTERFACE = r'^\s*interface\b'
  65. NATIVE_LISTENER = r'\bnative\s+listener\b'
  66. STATIC_INTERFACE = r'\bstatic\s+interface\b'
  67. VIEW_DELEGATE = r'\bview_delegate\b'
  68. CUSTOM_PROTO_HEADER = r'^\s*protoconv\s+"([^"]+)"\s*$'
  69. BASED_ON_PROTO_START = r'\bbased\s+on(\s|$)'
  70. BASED_ON_PROTO = r'\bbased\s+on\s+"([^"]+)"\s*:'
  71. CUSTOM_CPP_HEADER = r'^\s*cpp\s+"([^"]+)"\s*$'
  72. STRUCT = r'\bstruct\b'
  73. LITE_STRUCT = r'\blite\s+struct\b'
  74. BRIDGED_STRUCT = r'^(\s*options|\s*(navi_)?serializable|\s*abstract)*\s*struct\s+'
  75. LAMBDA_LISTENER = r'\blambda\s+listener\b'
  76. LISTENER = r'^\s*listener\s+'
  77. PLATFORM_INTERFACE = r'platform\s+interface'
  78. VARIANT = r'\bvariant\b'
  79. OPTIONAL = r'\boptional\b'
  80. INT_64 = r'\bint64\b'
  81. STRING = r'\bstring\b'
  82. POINT = r'\bpoint\b'
  83. BYTES = r'\bbytes\b'
  84. VECTOR = r'\bvector\b'
  85. DICTIONARY = r'\bdictionary\b'
  86. ANY = r'\bany[^_]'
  87. ENUM = r'\benum\b'
  88. TIME = r'\b(time_interval|abs_timestamp|rel_timestamp)\b'
  89. BITMAP = r'\bbitmap\b'
  90. VIEW_PROVIDER = r'\bview_provider\b'
  91. IMAGE_PROVIDER = r'\bimage_provider\b'
  92. ANIMATED_IMAGE_PROVIDER = r'\banimated_image_provider\b'
  93. MODEL_PROVIDER = r'\bmodel_provider\b'
  94. ANIMATED_MODEL_PROVIDER = r'\banimated_model_provider\b'
  95. COLOR = r'\bcolor\b'
  96. PLATFORM_VIEW = r'\bplatform_view\b'
  97. ERROR = r'\b(runtime\.)?Error\b'
  98. TYPE_DICTIONARY = r'\btype_dictionary\b'
  99. SERIALIZABLE = r'\bserializable\b'
  100. NAVI_SERIALIZABLE = r'\bnavi_serializable\b'
  101. class OutputType:
  102. BASE_HEADER = 1
  103. STRUCT_SOURCE = 2
  104. PROTOCONV_HEADER = 3
  105. PROTOCONV_SOURCE = 4
  106. ANDROID_HEADER = 5
  107. ANDROID_SOURCE = 6
  108. IOS_HEADER = 7
  109. IOS_SOURCE = 8
  110. IOS_PRIVATE_HEADER = 9
  111. IOS_BINDING_SOURCE = 10
  112. DART_CPP_HEADER = 11
  113. DART_CPP_SOURCE = 12
  114. DART_SOURCE = 13
  115. DART_SOURCE_PRIVATE = 14
  116. class OutputNameGenerator:
  117. def __init__(self, file_path, frameworks):
  118. path_tokens = file_path.split(os.sep)
  119. framework_name = path_tokens[0]
  120. self._framework = frameworks[framework_name]
  121. self._cpp_namespace_tokens = self._framework.cpp_namespace_tokens + path_tokens[1:-1]
  122. file_name = path_tokens[-1]
  123. self._cpp_name = file_name.split('.')[0]
  124. name_tokens = self._cpp_name.split('_')
  125. self._objc_name_core = ''.join((self._capitalize(token) for token in name_tokens))
  126. self._objc_name = self._framework.objc_framework_prefix + self._objc_name_core
  127. def set_objc_infix(self, objc_infix):
  128. if self._objc_name_core.startswith(objc_infix):
  129. self._objc_name = self._framework.objc_framework_prefix + self._objc_name_core
  130. else:
  131. self._objc_name = self._framework.objc_framework_prefix + objc_infix + self._objc_name_core
  132. def is_header(self, output_type):
  133. return output_type in [
  134. OutputType.BASE_HEADER,
  135. OutputType.PROTOCONV_HEADER,
  136. OutputType.ANDROID_HEADER,
  137. OutputType.IOS_HEADER,
  138. OutputType.IOS_PRIVATE_HEADER,
  139. OutputType.DART_CPP_HEADER
  140. ]
  141. def _cpp_file_name(self, extension, additional_tokens=[]):
  142. path_tokens = self._cpp_namespace_tokens + additional_tokens + [self._cpp_name + extension]
  143. return os.path.join(*path_tokens)
  144. def _dart_public_file_name(self, extension):
  145. return self._cpp_file_name(extension)
  146. def _dart_private_file_name(self, extension):
  147. path_tokens = ['src'] + self._cpp_namespace_tokens + [self._cpp_name + '_private' + extension]
  148. return os.path.join(*path_tokens)
  149. def _objc_file_name(self, extension, additional_tokens=[]):
  150. path_tokens = [self._framework.objc_framework_name] + additional_tokens + [self._objc_name + extension]
  151. return os.path.join(*path_tokens)
  152. def _capitalize(self, word):
  153. return word[:1].upper() + word[1:]
  154. def generate_name(self, output_type):
  155. if output_type is OutputType.BASE_HEADER:
  156. return self._cpp_file_name('.h')
  157. if output_type is OutputType.STRUCT_SOURCE:
  158. return self._cpp_file_name('.cpp')
  159. if output_type is OutputType.PROTOCONV_HEADER:
  160. return self._cpp_file_name('.conv.h')
  161. if output_type is OutputType.PROTOCONV_SOURCE:
  162. return self._cpp_file_name('.conv.cpp')
  163. if output_type is OutputType.ANDROID_HEADER:
  164. return self._cpp_file_name('_binding.h', ['internal', 'android'])
  165. if output_type is OutputType.ANDROID_SOURCE:
  166. return self._cpp_file_name('_binding.cpp', ['internal', 'android'])
  167. if output_type is OutputType.IOS_HEADER:
  168. return self._objc_file_name('.h')
  169. if output_type is OutputType.IOS_SOURCE:
  170. return self._objc_file_name('.m')
  171. if output_type is OutputType.IOS_PRIVATE_HEADER:
  172. return self._objc_file_name('_Private.h', ['Internal'])
  173. if output_type is OutputType.IOS_BINDING_SOURCE:
  174. return self._objc_file_name('_Binding.mm')
  175. if output_type is OutputType.DART_CPP_SOURCE:
  176. return self._cpp_file_name('_dart_binding.cpp')
  177. if output_type is OutputType.DART_SOURCE:
  178. return self._dart_public_file_name('.dart')
  179. if output_type is OutputType.DART_CPP_HEADER:
  180. return self._cpp_file_name('_dart_binding.h', ['bindings', 'flutter'])
  181. if output_type is OutputType.DART_SOURCE_PRIVATE:
  182. return self._dart_private_file_name('.dart')
  183. def generate_path(self, output_type):
  184. name = self.generate_name(output_type)
  185. if self.is_header(output_type):
  186. return os.path.join('include', name)
  187. return os.path.join('impl', name)
  188. class ProcessContext:
  189. def __init__(self, unit, frameworks, file_paths):
  190. self.unit = unit
  191. self.frameworks = frameworks
  192. self.file_paths = file_paths
  193. self.is_dart = unit.enabled("MAPKIT_DART_IDL")
  194. self.is_ios = unit.enabled("OS_IOS")
  195. self.is_android = unit.enabled("OS_ANDROID")
  196. self.output_name_generator = None
  197. self.add_generated_output_includes = unit.enabled("H_CPP_IDL")
  198. def runtime_include(self, include_name):
  199. name_tokens = self.frameworks['runtime'].cpp_namespace_tokens + [include_name]
  200. return os.path.join(*name_tokens)
  201. def runtime_objc_import(self, import_name):
  202. return os.path.join(
  203. self.frameworks['runtime'].objc_framework_name,
  204. self.frameworks['runtime'].objc_framework_prefix + import_name,
  205. )
  206. class BaseRule:
  207. def __init__(self, context):
  208. self.context = context
  209. def start_file(self, file_path):
  210. pass
  211. def process_line(self, line):
  212. pass
  213. def get_output_types(self):
  214. return set()
  215. def get_output_includes(self):
  216. return set()
  217. class ObjcInfixRule(BaseRule):
  218. def __init__(self, context):
  219. BaseRule.__init__(self, context)
  220. self._found_infix = False
  221. self._reg_exp = re.compile(RegExp.OBJC_INFIX)
  222. def start_file(self, file_path):
  223. BaseRule.start_file(self, file_path)
  224. self.context.output_name_generator.set_objc_infix('')
  225. self._found_infix = False
  226. def process_line(self, line):
  227. BaseRule.process_line(self, line)
  228. if self._found_infix:
  229. return
  230. infix = _extract_by_regexp(line, self._reg_exp)
  231. if infix:
  232. self._found_infix = True
  233. self.context.output_name_generator.set_objc_infix(infix)
  234. class ImportRule(BaseRule):
  235. def __init__(self, context):
  236. BaseRule.__init__(self, context)
  237. self._imports = set()
  238. self._import_reg_exp = re.compile(RegExp.IMPORT)
  239. def start_file(self, file_path):
  240. self._imports = set()
  241. def process_line(self, line):
  242. BaseRule.process_line(self, line)
  243. idl_import = _extract_by_regexp(line, self._import_reg_exp)
  244. if idl_import:
  245. self._imports.add(idl_import)
  246. def get_output_includes(self):
  247. result = set()
  248. for idl_import in self._imports:
  249. if idl_import in self.context.file_paths:
  250. continue
  251. name_generator = OutputNameGenerator(idl_import, self.context.frameworks)
  252. result.add(name_generator.generate_name(OutputType.BASE_HEADER))
  253. return result
  254. class DefaultRule(BaseRule):
  255. def __init__(self, context):
  256. BaseRule.__init__(self, context)
  257. def get_output_types(self):
  258. result = set()
  259. result.add(OutputType.BASE_HEADER)
  260. if self.context.is_dart:
  261. result.add(OutputType.DART_SOURCE)
  262. result.add(OutputType.DART_CPP_SOURCE)
  263. result.add(OutputType.DART_CPP_HEADER)
  264. result.add(OutputType.DART_SOURCE_PRIVATE)
  265. if self.context.is_ios:
  266. result.add(OutputType.IOS_HEADER)
  267. result.add(OutputType.IOS_SOURCE)
  268. return result
  269. def get_output_includes(self):
  270. result = set()
  271. if self.context.is_dart:
  272. result.add(self.context.runtime_include('bindings/flutter/base_types.h'))
  273. result.add(self.context.runtime_include('bindings/flutter/exception.h'))
  274. result.add(self.context.runtime_include('bindings/flutter/export.h'))
  275. result.add(self.context.runtime_include('bindings/flutter/to_native.h'))
  276. result.add(self.context.runtime_include('bindings/flutter/to_native_fwd.h'))
  277. result.add(self.context.runtime_include('bindings/flutter/to_platform.h'))
  278. result.add(self.context.runtime_include('bindings/flutter/to_platform_fwd.h'))
  279. result.add(self.context.runtime_include('bindings/flutter/vector.h'))
  280. result.add(self.context.runtime_include('bindings/flutter/string_map.h'))
  281. result.add(self.context.runtime_include('bindings/flutter/helper.h'))
  282. result.add(self.context.runtime_include('bindings/flutter/meta_type.h'))
  283. result.add(self.context.runtime_include('bindings/flutter/native.h'))
  284. result.add('yandex/maps/export.h')
  285. result.add(self.context.runtime_include('assert.h'))
  286. result.add(self.context.runtime_include('exception.h'))
  287. result.add(self.context.runtime_include('bindings/traits.h'))
  288. if self.context.is_ios:
  289. result.add(self.context.runtime_include('bindings/platform.h'))
  290. result.add('Foundation/Foundation.h')
  291. result.add(self.context.runtime_include('ios/object.h'))
  292. result.add(self.context.runtime_include('bindings/ios/to_native.h'))
  293. result.add(self.context.runtime_include('bindings/ios/to_platform.h'))
  294. result.add(self.context.runtime_include('ios/exception.h'))
  295. result.add(self.context.runtime_objc_import('Subscription.h'))
  296. if self.context.is_android:
  297. result.add(self.context.runtime_include('bindings/platform.h'))
  298. result.add(self.context.runtime_include('android/object.h'))
  299. result.add(self.context.runtime_include('bindings/android/to_native.h'))
  300. result.add(self.context.runtime_include('bindings/android/to_platform.h'))
  301. result.add(self.context.runtime_include('exception.h'))
  302. return result
  303. class CheckRule(BaseRule):
  304. def __init__(
  305. self,
  306. context,
  307. output_types=set(),
  308. output_includes=set(),
  309. ios_output_types=set(),
  310. ios_output_includes=set(),
  311. android_output_types=set(),
  312. android_output_includes=set(),
  313. dart_output_includes=set(),
  314. ):
  315. BaseRule.__init__(self, context)
  316. self._output_types = output_types
  317. self._output_includes = output_includes
  318. self._ios_output_types = ios_output_types
  319. self._ios_output_includes = ios_output_includes
  320. self._android_output_types = android_output_types
  321. self._android_output_includes = android_output_includes
  322. self._dart_output_includes = dart_output_includes
  323. def triggered_on_file(self):
  324. pass
  325. def get_output_types(self):
  326. result = set()
  327. if self.triggered_on_file():
  328. result.update(self._output_types)
  329. if self.context.is_ios:
  330. result.update(self._ios_output_types)
  331. if self.context.is_android:
  332. result.update(self._android_output_types)
  333. return result
  334. def get_output_includes(self):
  335. result = set()
  336. if self.triggered_on_file():
  337. result.update(self._output_includes)
  338. if self.context.is_ios:
  339. result.update(self._ios_output_includes)
  340. if self.context.is_android:
  341. result.update(self._android_output_includes)
  342. if self.context.is_dart:
  343. result.update(self._dart_output_includes)
  344. return result
  345. class OrRule(CheckRule):
  346. def __init__(self, check_rules, *args, **kwargs):
  347. CheckRule.__init__(self, *args, **kwargs)
  348. self._rules = check_rules
  349. def triggered_on_file(self):
  350. return any((rule.triggered_on_file() for rule in self._rules))
  351. class AndRule(CheckRule):
  352. def __init__(self, check_rules, *args, **kwargs):
  353. CheckRule.__init__(self, *args, **kwargs)
  354. self._rules = check_rules
  355. def triggered_on_file(self):
  356. return all((rule.triggered_on_file() for rule in self._rules))
  357. class RegExpRule(CheckRule):
  358. def __init__(self, reg_exp_string, *args, **kwargs):
  359. CheckRule.__init__(self, *args, **kwargs)
  360. self._reg_exp = re.compile(reg_exp_string)
  361. self._reg_exp_found_file = False
  362. def start_file(self, file_path):
  363. CheckRule.start_file(self, file_path)
  364. self._reg_exp_found_file = False
  365. def process_line(self, line):
  366. CheckRule.process_line(self, line)
  367. if self._reg_exp_found_file:
  368. return
  369. if self._reg_exp.search(line) is not None:
  370. self._reg_exp_found_file = True
  371. def triggered_on_file(self):
  372. return self._reg_exp_found_file
  373. class ProtoRule(BaseRule):
  374. def __init__(self, context):
  375. BaseRule.__init__(self, context)
  376. self._file_has_non_custom_proto = False
  377. self._currently_custom_proto = False
  378. self._currently_based_on = False
  379. self._running_line = ''
  380. self._custom_proto_headers = set()
  381. self._proto_files = set()
  382. self._custom_proto_reg_exp = re.compile(RegExp.CUSTOM_PROTO_HEADER)
  383. self._based_on_proto_start_reg_exp = re.compile(RegExp.BASED_ON_PROTO_START)
  384. self._based_on_proto_reg_exp = re.compile(RegExp.BASED_ON_PROTO)
  385. def start_file(self, file_path):
  386. BaseRule.start_file(self, file_path)
  387. self._currently_custom_proto = False
  388. self._file_has_non_custom_proto = False
  389. self._currently_based_on = False
  390. self._running_line = ''
  391. def process_line(self, line):
  392. BaseRule.process_line(self, line)
  393. proto_header = _extract_by_regexp(line, self._custom_proto_reg_exp)
  394. if proto_header:
  395. self._custom_proto_headers.add(proto_header)
  396. self._currently_based_on = False
  397. self._running_line = ''
  398. self._currently_custom_proto = True
  399. return
  400. if self._based_on_proto_start_reg_exp.search(line) is not None:
  401. self._currently_based_on = True
  402. self._running_line = ''
  403. if self._currently_based_on:
  404. self._running_line += '\n' + line
  405. proto_file = _extract_by_regexp(self._running_line, self._based_on_proto_reg_exp)
  406. if proto_file:
  407. self._currently_based_on = False
  408. self._running_line = ''
  409. self._proto_files.add(proto_file)
  410. if self._currently_custom_proto:
  411. self._currently_custom_proto = False
  412. else:
  413. self._file_has_non_custom_proto = True
  414. def get_output_types(self):
  415. if self._file_has_non_custom_proto:
  416. return {OutputType.PROTOCONV_HEADER, OutputType.PROTOCONV_SOURCE}
  417. return set()
  418. def get_output_includes(self):
  419. result = set()
  420. result.update(self._custom_proto_headers)
  421. result.update((proto_file.split('.')[0] + '.pb.h' for proto_file in self._proto_files))
  422. if self._file_has_non_custom_proto:
  423. result.update({'vector'})
  424. return result
  425. class StructImplementationRule(BaseRule):
  426. def __init__(self, context):
  427. BaseRule.__init__(self, context)
  428. self._file_has_non_custom_struct = False
  429. self._custom_cpp_headers = set()
  430. self._currently_custom_struct = False
  431. self._custom_cpp_header_reg_exp = re.compile(RegExp.CUSTOM_CPP_HEADER)
  432. self._struct_reg_exp = re.compile(RegExp.STRUCT)
  433. def start_file(self, file_path):
  434. BaseRule.start_file(self, file_path)
  435. self._currently_custom_struct = False
  436. self._file_has_non_custom_struct = False
  437. def process_line(self, line):
  438. BaseRule.process_line(self, line)
  439. cpp_header = _extract_by_regexp(line, self._custom_cpp_header_reg_exp)
  440. if cpp_header:
  441. self._custom_cpp_headers.add(cpp_header)
  442. self._currently_custom_struct = True
  443. return
  444. if not self._file_has_non_custom_struct:
  445. if self._struct_reg_exp.search(line) is not None:
  446. if self._currently_custom_struct:
  447. self._currently_custom_struct = False
  448. else:
  449. self._file_has_non_custom_struct = True
  450. def get_output_types(self):
  451. result = set()
  452. if self._file_has_non_custom_struct:
  453. result.add(OutputType.STRUCT_SOURCE)
  454. if self.context.is_ios:
  455. result.add(OutputType.IOS_BINDING_SOURCE)
  456. return result
  457. def get_output_includes(self):
  458. return self._custom_cpp_headers
  459. class IdlFileProcessor:
  460. def __init__(self, unit, frameworks, file_paths):
  461. self._context = ProcessContext(unit, frameworks, file_paths)
  462. self._resolved_idl_dir = unit.resolve(unit.resolve_arc_path(unit.path()))
  463. self._outputs = set()
  464. self._output_includes = set()
  465. self._rules = set()
  466. self._rules.add(ObjcInfixRule(self._context))
  467. self._rules.add(DefaultRule(self._context))
  468. self._rules.add(ImportRule(self._context))
  469. self._rules.add(ProtoRule(self._context))
  470. self._rules.add(StructImplementationRule(self._context))
  471. view_delegate_rule = self._create_reg_exp_rule(
  472. RegExp.VIEW_DELEGATE, output_includes={self._context.runtime_include('view/view_delegate.h')}
  473. )
  474. weak_interface_rule = self._create_or_rule(
  475. rules={
  476. self._create_reg_exp_rule(RegExp.WEAK_INTERFACE),
  477. view_delegate_rule,
  478. },
  479. output_includes={'boost/any.hpp', 'memory', self._context.runtime_include('platform_holder.h')},
  480. )
  481. strong_interface_rule = self._create_or_rule(
  482. rules={
  483. self._create_reg_exp_rule(RegExp.STRONG_INTERFACE),
  484. self._create_reg_exp_rule(RegExp.NATIVE_LISTENER),
  485. }
  486. )
  487. non_static_interface_rule = self._create_or_rule(
  488. rules={self._create_reg_exp_rule(RegExp.SHARED_INTERFACE), strong_interface_rule, weak_interface_rule},
  489. ios_output_types={OutputType.IOS_PRIVATE_HEADER},
  490. )
  491. # interface rule
  492. self._create_or_rule(
  493. rules={self._create_reg_exp_rule(RegExp.STATIC_INTERFACE), non_static_interface_rule},
  494. ios_output_types={OutputType.IOS_BINDING_SOURCE},
  495. android_output_types={OutputType.ANDROID_SOURCE},
  496. ios_output_includes={'memory'},
  497. )
  498. bridged_struct_rule = self._create_reg_exp_rule(
  499. RegExp.BRIDGED_STRUCT,
  500. output_includes={'memory', self._context.runtime_include('bindings/platform.h')},
  501. android_output_includes={self._context.runtime_include('bindings/android/internal/new_serialization.h')},
  502. )
  503. # struct rule
  504. self._create_or_rule(
  505. rules={self._create_reg_exp_rule(RegExp.LITE_STRUCT), bridged_struct_rule},
  506. ios_output_types={OutputType.IOS_PRIVATE_HEADER},
  507. android_output_types={OutputType.ANDROID_HEADER, OutputType.ANDROID_SOURCE},
  508. ios_output_includes={self._context.runtime_objc_import('NativeObject.h')},
  509. )
  510. lambda_listener_rule = self._create_reg_exp_rule(
  511. RegExp.LAMBDA_LISTENER,
  512. output_includes={'functional'},
  513. android_output_includes={self._context.runtime_include('verify_and_run.h')},
  514. ios_output_includes={self._context.runtime_include('verify_and_run.h')},
  515. )
  516. # listener rule
  517. self._create_or_rule(
  518. rules={
  519. self._create_reg_exp_rule(RegExp.PLATFORM_INTERFACE),
  520. self._create_reg_exp_rule(RegExp.LISTENER),
  521. lambda_listener_rule,
  522. },
  523. ios_output_types={OutputType.IOS_PRIVATE_HEADER, OutputType.IOS_BINDING_SOURCE},
  524. android_output_types={OutputType.ANDROID_HEADER, OutputType.ANDROID_SOURCE},
  525. output_includes={'memory'},
  526. android_output_includes={'string', self._context.runtime_include('verify_and_run.h')},
  527. ios_output_includes={self._context.runtime_include('verify_and_run.h')},
  528. )
  529. if self._context.unit.enabled("MAPS_MOBILE_USE_STD_VARIANT"):
  530. variant_header = 'variant'
  531. variant_serialization_header = self.context.runtime_include('serialization/variant.hpp')
  532. else:
  533. variant_header = 'boost/variant.hpp'
  534. variant_serialization_header = 'boost/serialization/variant.hpp'
  535. variant_rule = self._create_reg_exp_rule(
  536. RegExp.VARIANT,
  537. ios_output_types={OutputType.IOS_PRIVATE_HEADER, OutputType.IOS_BINDING_SOURCE},
  538. output_includes={variant_header, 'boost/variant/recursive_wrapper.hpp'},
  539. ios_output_includes={
  540. self._context.runtime_include('bindings/ios/to_platform_fwd.h'),
  541. self._context.runtime_include('bindings/ios/to_native_fwd.h'),
  542. 'type_traits',
  543. },
  544. )
  545. optional_rule = self._create_reg_exp_rule(RegExp.OPTIONAL, output_includes={'optional'})
  546. # int64 rule
  547. self._create_reg_exp_rule(RegExp.INT_64, output_includes={'cstdint'})
  548. string_rule = self._create_reg_exp_rule(
  549. RegExp.STRING, output_includes={'string', self._context.runtime_include('bindings/platform.h')}
  550. )
  551. point_rule = self._create_reg_exp_rule(
  552. RegExp.POINT,
  553. output_includes={'Eigen/Geometry', self._context.runtime_include('bindings/point_traits.h')},
  554. android_output_includes={
  555. self._context.runtime_include('bindings/android/point_to_native.h'),
  556. self._context.runtime_include('bindings/android/point_to_platform.h'),
  557. },
  558. ios_output_includes={
  559. self._context.runtime_include('bindings/ios/point_to_native.h'),
  560. self._context.runtime_include('bindings/ios/point_to_platform.h'),
  561. 'UIKit/UIKit.h',
  562. },
  563. )
  564. bytes_rule = self._create_reg_exp_rule(RegExp.BYTES, output_includes={'cstdint', 'vector'})
  565. vector_rule = self._create_reg_exp_rule(
  566. RegExp.VECTOR,
  567. output_includes={'memory', self._context.runtime_include('bindings/platform.h')},
  568. android_output_includes={
  569. self._context.runtime_include('bindings/android/vector_to_native.h'),
  570. self._context.runtime_include('bindings/android/vector_to_platform.h'),
  571. },
  572. ios_output_includes={
  573. self._context.runtime_include('bindings/ios/vector_to_native.h'),
  574. self._context.runtime_include('bindings/ios/vector_to_platform.h'),
  575. },
  576. )
  577. dictionary_rule = self._create_reg_exp_rule(
  578. RegExp.DICTIONARY,
  579. output_includes={'memory', self._context.runtime_include('bindings/platform.h')},
  580. android_output_includes={
  581. self._context.runtime_include('bindings/android/dictionary_to_native.h'),
  582. self._context.runtime_include('bindings/android/dictionary_to_platform.h'),
  583. },
  584. ios_output_includes={
  585. self._context.runtime_include('bindings/ios/dictionary_to_native.h'),
  586. self._context.runtime_include('bindings/ios/dictionary_to_platform.h'),
  587. },
  588. )
  589. # any rule
  590. self._create_reg_exp_rule(
  591. RegExp.ANY, output_includes={'boost/any.hpp', self._context.runtime_include('bindings/platform.h')}
  592. )
  593. time_rule = self._create_reg_exp_rule(RegExp.TIME, output_includes={self._context.runtime_include('time.h')})
  594. # bitmap rule
  595. self._create_reg_exp_rule(
  596. RegExp.BITMAP,
  597. output_includes={self._context.runtime_include('platform_bitmap.h')},
  598. ios_output_includes={'UIKit/UIKit.h'},
  599. )
  600. # image_provider rule
  601. self._create_reg_exp_rule(
  602. RegExp.IMAGE_PROVIDER,
  603. output_includes={self._context.runtime_include('image/image_provider.h')},
  604. android_output_includes={self._context.runtime_include('image/android/image_provider_binding.h')},
  605. ios_output_includes={self._context.runtime_include('image/ios/image_provider_binding.h'), 'UIKit/UIKit.h'},
  606. dart_output_includes={self._context.runtime_include('image/flutter/image_provider_binding.h')},
  607. )
  608. # animated_image_provider rule
  609. self._create_reg_exp_rule(
  610. RegExp.ANIMATED_IMAGE_PROVIDER,
  611. output_includes={self._context.runtime_include('image/animated_image_provider.h')},
  612. android_output_includes={self._context.runtime_include('image/android/animated_image_provider_binding.h')},
  613. ios_output_includes={
  614. self._context.runtime_include('image/ios/animated_image_provider_binding.h'),
  615. self._context.runtime_objc_import('AnimatedImageProvider.h'),
  616. },
  617. dart_output_includes={
  618. self._context.runtime_include('image/flutter/animated_image_provider_binding.h')
  619. },
  620. )
  621. # model_provider and animated_model_provider rules
  622. model_provider_rule = self._create_reg_exp_rule(
  623. RegExp.MODEL_PROVIDER, output_includes={self._context.runtime_include('model/model_provider.h')}
  624. )
  625. animated_model_provider_rule = self._create_reg_exp_rule(
  626. RegExp.ANIMATED_MODEL_PROVIDER,
  627. output_includes={self._context.runtime_include('model/animated_model_provider.h')},
  628. )
  629. if not unit.enabled('MAPS_MOBILE_PUBLIC_API'):
  630. self._create_or_rule(
  631. rules={model_provider_rule},
  632. android_output_includes={self._context.runtime_include('model/android/model_provider_binding.h')},
  633. ios_output_includes={
  634. self._context.runtime_include('model/ios/model_provider_binding.h'),
  635. self._context.runtime_objc_import('ModelProvider.h'),
  636. },
  637. )
  638. self._create_or_rule(
  639. rules={animated_model_provider_rule},
  640. android_output_includes={
  641. self._context.runtime_include('model/android/animated_model_provider_binding.h')
  642. },
  643. ios_output_includes={
  644. self._context.runtime_include('model/ios/animated_model_provider_binding.h'),
  645. self._context.runtime_objc_import('AnimatedModelProvider.h'),
  646. },
  647. )
  648. # view_provider rule
  649. self._create_reg_exp_rule(
  650. RegExp.VIEW_PROVIDER,
  651. output_includes={self._context.runtime_include('ui_view/view_provider.h')},
  652. android_output_includes={self._context.runtime_include('ui_view/android/view_provider_binding.h')},
  653. ios_output_includes={
  654. self._context.runtime_include('ui_view/ios/view_provider_binding.h'),
  655. self._context.runtime_objc_import('ViewProvider.h'),
  656. },
  657. dart_output_includes={
  658. self._context.runtime_include('ui_view/flutter/view_provider_binding.h')
  659. },
  660. )
  661. # platform_view rule
  662. self._create_reg_exp_rule(
  663. RegExp.PLATFORM_VIEW,
  664. output_includes={self._context.runtime_include('view/platform_view.h')},
  665. android_output_includes={self._context.runtime_include('view/android/to_native.h')},
  666. ios_output_includes={
  667. self._context.runtime_include('view/ios/to_native.h'),
  668. self._context.runtime_objc_import('PlatformView_Fwd.h'),
  669. self._context.runtime_objc_import('PlatformView_Private.h'),
  670. },
  671. dart_output_includes={
  672. self._context.runtime_include('view/flutter/to_native.h')
  673. },
  674. )
  675. # type_dictionary rule
  676. self._create_reg_exp_rule(
  677. RegExp.TYPE_DICTIONARY,
  678. output_includes={
  679. self._context.runtime_include('bindings/platform.h'),
  680. self._context.runtime_include('bindings/type_dictionary.h'),
  681. },
  682. android_output_includes={
  683. self._context.runtime_include('bindings/android/type_dictionary_to_native.h'),
  684. self._context.runtime_include('bindings/android/type_dictionary_to_platform.h'),
  685. },
  686. ios_output_includes={
  687. self._context.runtime_include('bindings/ios/type_dictionary_to_native.h'),
  688. self._context.runtime_include('bindings/ios/type_dictionary_to_platform.h'),
  689. self._context.runtime_objc_import('TypeDictionary.h'),
  690. },
  691. )
  692. # color rule
  693. self._create_reg_exp_rule(
  694. RegExp.COLOR,
  695. output_includes={self._context.runtime_include('color.h')},
  696. ios_output_includes={'UIKit/UIKit.h'},
  697. )
  698. # error rule
  699. self._create_reg_exp_rule(
  700. RegExp.ERROR,
  701. android_output_includes={self._context.runtime_include('android/make_error.h')},
  702. ios_output_includes={self._context.runtime_include('ios/make_error.h')},
  703. )
  704. navi_serialization = self._context.unit.enabled('MAPS_MOBILE_ENABLE_NAVI_SERIALIZATION')
  705. if navi_serialization:
  706. serialization_rule = self._create_or_rule(
  707. {self._create_reg_exp_rule(RegExp.SERIALIZABLE), self._create_reg_exp_rule(RegExp.NAVI_SERIALIZABLE)}
  708. )
  709. else:
  710. serialization_rule = self._create_reg_exp_rule(RegExp.SERIALIZABLE)
  711. self._serialization_rule = self._create_or_rule(
  712. rules={serialization_rule, variant_rule},
  713. output_includes={
  714. 'boost/serialization/nvp.hpp',
  715. self._context.runtime_include('serialization/ptr.h'),
  716. self._context.runtime_include('bindings/internal/archive_generator.h'),
  717. self._context.runtime_include('bindings/internal/archive_reader.h'),
  718. self._context.runtime_include('bindings/internal/archive_writer.h'),
  719. },
  720. )
  721. # point serialization rule
  722. self._create_serialization_rule(point_rule, self._context.runtime_include('serialization/math.h'))
  723. # optional serialization rule
  724. self._create_serialization_rule(
  725. optional_rule, self._context.runtime_include('serialization/serialization_std.h')
  726. )
  727. # bridged struct serialization rule
  728. self._create_serialization_rule(bridged_struct_rule, self._context.runtime_include('bindings/export.h'))
  729. # time serialization rule
  730. self._create_serialization_rule(time_rule, self._context.runtime_include('serialization/chrono.h'))
  731. # string serialization rule
  732. self._create_serialization_rule(string_rule, 'boost/serialization/string.hpp')
  733. # bytes serialization rule
  734. self._create_serialization_rule(bytes_rule, 'boost/serialization/vector.hpp')
  735. # vector serialization rule
  736. self._create_serialization_rule(vector_rule, 'boost/serialization/vector.hpp')
  737. # dictionary serialization rule
  738. self._create_serialization_rule(dictionary_rule, 'boost/serialization/map.hpp')
  739. # variant serialization rule
  740. self._create_serialization_rule(variant_rule, variant_serialization_header)
  741. def _create_reg_exp_rule(self, reg_exp_string, *args, **kwargs):
  742. rule = RegExpRule(reg_exp_string, self._context, *args, **kwargs)
  743. self._rules.add(rule)
  744. return rule
  745. def _create_or_rule(self, rules, *args, **kwargs):
  746. rule = OrRule(rules, self._context, *args, **kwargs)
  747. self._rules.add(rule)
  748. return rule
  749. def _create_and_rule(self, rules, *args, **kwargs):
  750. rule = AndRule(rules, self._context, *args, **kwargs)
  751. self._rules.add(rule)
  752. return rule
  753. def _create_serialization_rule(self, additional_rule, serialization_header):
  754. rule = self._create_and_rule(
  755. rules={self._serialization_rule, additional_rule}, output_includes={serialization_header}
  756. )
  757. return rule
  758. def _split_and_remove_comments(self, input_file):
  759. inside_comment = False
  760. for line in input_file:
  761. current_line = line
  762. if inside_comment:
  763. closing_index = current_line.find("*/")
  764. if closing_index == -1:
  765. continue
  766. current_line = current_line[closing_index + 2 :]
  767. inside_comment = False
  768. oneline_index = current_line.find("//")
  769. if oneline_index != -1:
  770. current_line = current_line[:oneline_index]
  771. opening_index = current_line.find("/*")
  772. while opening_index != -1:
  773. closing_index = current_line.find("*/")
  774. if closing_index == -1:
  775. current_line = current_line[:opening_index]
  776. inside_comment = True
  777. else:
  778. current_line = current_line[:opening_index] + current_line[closing_index + 2 :]
  779. opening_index = current_line.find("/*")
  780. yield current_line
  781. def _should_add_to_output_includes(self, output_type):
  782. return self._context.add_generated_output_includes and self._context.output_name_generator.is_header(
  783. output_type
  784. )
  785. def process_files(self):
  786. for file_path in self._context.file_paths:
  787. self._context.output_name_generator = OutputNameGenerator(file_path, self._context.frameworks)
  788. for rule in self._rules:
  789. rule.start_file(file_path)
  790. with open(os.path.join(self._resolved_idl_dir, file_path), 'r') as f:
  791. for line in self._split_and_remove_comments(f):
  792. for rule in self._rules:
  793. rule.process_line(line)
  794. for rule in self._rules:
  795. for output_type in rule.get_output_types():
  796. self._outputs.add(self._context.output_name_generator.generate_path(output_type))
  797. if self._should_add_to_output_includes(output_type):
  798. self._output_includes.add(self._context.output_name_generator.generate_name(output_type))
  799. self._output_includes.update(rule.get_output_includes())
  800. def get_outputs(self):
  801. return self._outputs
  802. def get_output_includes(self):
  803. return self._output_includes
  804. def process_files(unit, file_paths):
  805. frameworks = _read_frameworks(unit)
  806. processor = IdlFileProcessor(unit, frameworks, file_paths)
  807. processor.process_files()
  808. outputs = processor.get_outputs()
  809. output_includes = processor.get_output_includes()
  810. return (outputs, output_includes)
  811. def on_process_maps_mobile_idl(unit, *args):
  812. if not unit.enabled('MAPSMOBI_BUILD_TARGET'):
  813. return
  814. idl_files, kwds = sort_by_keywords({'FILTER': -1, 'FILTER_OUT': -1, 'GLOBAL_OUTPUTS': 0}, args)
  815. if len(idl_files) == 0:
  816. return
  817. is_global_outputs = 'GLOBAL_OUTPUTS' in kwds
  818. filter_in = kwds.get('FILTER', [])
  819. filter_out = kwds.get('FILTER_OUT', [])
  820. is_java_idl = unit.enabled("JAVA_IDL")
  821. is_dart_idl = unit.enabled("MAPKIT_DART_IDL") and not is_java_idl
  822. outputs, output_includes = process_files(unit, idl_files)
  823. if filter_in:
  824. outputs = [o for o in outputs if any([o.endswith(x) for x in filter_in])]
  825. if filter_out:
  826. outputs = [o for o in outputs if not any([o.endswith(x) for x in filter_out])]
  827. if len(outputs) == 0 and not is_java_idl:
  828. return
  829. base_out_dir = '${{ARCADIA_BUILD_ROOT}}/{}'.format(unit.path()[3:])
  830. unit.onaddincl(['GLOBAL', '{}/include'.format(base_out_dir)])
  831. include_dirs = _get_appended_values(unit, 'MAPKIT_IDL_INCLUDES')
  832. include_dirs.append(unit.path()[3:])
  833. framework_dir = unit.get('MAPKIT_IDL_FRAMEWORK')
  834. extra_inputs = unit.get('MAPKIT_IDL_EXTRA_INPUTS').split(' ')
  835. idl_args = []
  836. idl_args.extend(['OUT_BASE_ROOT', base_out_dir, 'OUT_ANDROID_ROOT', base_out_dir, 'OUT_IOS_ROOT', base_out_dir])
  837. if framework_dir:
  838. idl_args.extend(['FRAMEWORK_DIRS', framework_dir])
  839. if include_dirs:
  840. idl_args.append('INCLUDES')
  841. idl_args.extend(include_dirs)
  842. idl_args.append('IN')
  843. idl_args.extend(idl_files)
  844. if extra_inputs:
  845. idl_args.extend(extra_inputs)
  846. sorted_outputs = sorted(outputs)
  847. dart_outputs = []
  848. global_outputs = []
  849. if is_dart_idl:
  850. dart_outputs = [x for x in sorted_outputs if x.endswith('.dart')]
  851. if is_global_outputs:
  852. global_outputs = [x for x in sorted_outputs if x.endswith('.cpp')]
  853. elif not is_java_idl:
  854. if is_global_outputs:
  855. global_outputs = [x for x in sorted_outputs if x.endswith(('.cpp', '.m', '.mm'))]
  856. if not is_java_idl:
  857. non_global_outputs = sorted(set(outputs) - set(global_outputs) - set(dart_outputs))
  858. if global_outputs:
  859. idl_args.append('OUT_NOAUTO')
  860. idl_args.extend(global_outputs + dart_outputs)
  861. unit.onglobal_srcs(global_outputs)
  862. if non_global_outputs:
  863. idl_args.append('OUT')
  864. idl_args.extend(non_global_outputs)
  865. idl_args.append('OUTPUT_INCLUDES')
  866. idl_args.extend(sorted(set(output_includes) - set(outputs)))
  867. idl_args.append('IDLS')
  868. idl_args.extend(idl_files)
  869. if is_java_idl:
  870. unit.on_run_idl_tool_java(idl_args)
  871. else:
  872. unit.on_run_idl_tool(idl_args)