CodeGeneratorInspector.py 96 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414
  1. #!/usr/bin/env python
  2. # Copyright (c) 2011 Google Inc. All rights reserved.
  3. # Copyright (c) 2012 Intel Corporation. All rights reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are
  7. # met:
  8. #
  9. # * Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # * Redistributions in binary form must reproduce the above
  12. # copyright notice, this list of conditions and the following disclaimer
  13. # in the documentation and/or other materials provided with the
  14. # distribution.
  15. # * Neither the name of Google Inc. nor the names of its
  16. # contributors may be used to endorse or promote products derived from
  17. # this software without specific prior written permission.
  18. #
  19. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. import os.path
  31. import sys
  32. import string
  33. import optparse
  34. import re
  35. try:
  36. import json
  37. except ImportError:
  38. import simplejson as json
  39. import CodeGeneratorInspectorStrings
  40. DOMAIN_DEFINE_NAME_MAP = {
  41. "Database": "SQL_DATABASE",
  42. "Debugger": "JAVASCRIPT_DEBUGGER",
  43. "DOMDebugger": "JAVASCRIPT_DEBUGGER",
  44. "FileSystem": "FILE_SYSTEM",
  45. "IndexedDB": "INDEXED_DATABASE",
  46. "Profiler": "JAVASCRIPT_DEBUGGER",
  47. "Worker": "WORKERS",
  48. }
  49. # Manually-filled map of type name replacements.
  50. TYPE_NAME_FIX_MAP = {
  51. "RGBA": "Rgba", # RGBA is reported to be conflicting with a define name in Windows CE.
  52. "": "Empty",
  53. }
  54. TYPES_WITH_RUNTIME_CAST_SET = frozenset(["Runtime.RemoteObject", "Runtime.PropertyDescriptor", "Runtime.InternalPropertyDescriptor",
  55. "Debugger.FunctionDetails", "Debugger.CallFrame",
  56. "Canvas.TraceLog", "Canvas.ResourceInfo", "Canvas.ResourceState",
  57. # This should be a temporary hack. TimelineEvent should be created via generated C++ API.
  58. "Timeline.TimelineEvent"])
  59. TYPES_WITH_OPEN_FIELD_LIST_SET = frozenset(["Timeline.TimelineEvent",
  60. # InspectorStyleSheet not only creates this property but wants to read it and modify it.
  61. "CSS.CSSProperty",
  62. # InspectorResourceAgent needs to update mime-type.
  63. "Network.Response"])
  64. EXACTLY_INT_SUPPORTED = False
  65. cmdline_parser = optparse.OptionParser()
  66. cmdline_parser.add_option("--output_h_dir")
  67. cmdline_parser.add_option("--output_cpp_dir")
  68. cmdline_parser.add_option("--write_always", action="store_true")
  69. try:
  70. arg_options, arg_values = cmdline_parser.parse_args()
  71. if (len(arg_values) != 1):
  72. raise Exception("Exactly one plain argument expected (found %s)" % len(arg_values))
  73. input_json_filename = arg_values[0]
  74. output_header_dirname = arg_options.output_h_dir
  75. output_cpp_dirname = arg_options.output_cpp_dir
  76. write_always = arg_options.write_always
  77. if not output_header_dirname:
  78. raise Exception("Output .h directory must be specified")
  79. if not output_cpp_dirname:
  80. raise Exception("Output .cpp directory must be specified")
  81. except Exception:
  82. # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html
  83. exc = sys.exc_info()[1]
  84. sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc)
  85. sys.stderr.write("Usage: <script> Inspector.json --output_h_dir <output_header_dir> --output_cpp_dir <output_cpp_dir> [--write_always]\n")
  86. exit(1)
  87. def dash_to_camelcase(word):
  88. return ''.join(x.capitalize() or '-' for x in word.split('-'))
  89. def fix_camel_case(name):
  90. refined = re.sub(r'-(\w)', lambda pat: pat.group(1).upper(), name)
  91. refined = to_title_case(refined)
  92. return re.sub(r'(?i)HTML|XML|WML|API', lambda pat: pat.group(0).upper(), refined)
  93. def to_title_case(name):
  94. return name[:1].upper() + name[1:]
  95. class Capitalizer:
  96. @staticmethod
  97. def lower_camel_case_to_upper(str):
  98. if len(str) > 0 and str[0].islower():
  99. str = str[0].upper() + str[1:]
  100. return str
  101. @staticmethod
  102. def upper_camel_case_to_lower(str):
  103. pos = 0
  104. while pos < len(str) and str[pos].isupper():
  105. pos += 1
  106. if pos == 0:
  107. return str
  108. if pos == 1:
  109. return str[0].lower() + str[1:]
  110. if pos < len(str):
  111. pos -= 1
  112. possible_abbreviation = str[0:pos]
  113. if possible_abbreviation not in Capitalizer.ABBREVIATION:
  114. raise Exception("Unknown abbreviation %s" % possible_abbreviation)
  115. str = possible_abbreviation.lower() + str[pos:]
  116. return str
  117. @staticmethod
  118. def camel_case_to_capitalized_with_underscores(str):
  119. if len(str) == 0:
  120. return str
  121. output = Capitalizer.split_camel_case_(str)
  122. return "_".join(output).upper()
  123. @staticmethod
  124. def split_camel_case_(str):
  125. output = []
  126. pos_being = 0
  127. pos = 1
  128. has_oneletter = False
  129. while pos < len(str):
  130. if str[pos].isupper():
  131. output.append(str[pos_being:pos].upper())
  132. if pos - pos_being == 1:
  133. has_oneletter = True
  134. pos_being = pos
  135. pos += 1
  136. output.append(str[pos_being:])
  137. if has_oneletter:
  138. array_pos = 0
  139. while array_pos < len(output) - 1:
  140. if len(output[array_pos]) == 1:
  141. array_pos_end = array_pos + 1
  142. while array_pos_end < len(output) and len(output[array_pos_end]) == 1:
  143. array_pos_end += 1
  144. if array_pos_end - array_pos > 1:
  145. possible_abbreviation = "".join(output[array_pos:array_pos_end])
  146. if possible_abbreviation.upper() in Capitalizer.ABBREVIATION:
  147. output[array_pos:array_pos_end] = [possible_abbreviation]
  148. else:
  149. array_pos = array_pos_end - 1
  150. array_pos += 1
  151. return output
  152. ABBREVIATION = frozenset(["XHR", "DOM", "CSS"])
  153. VALIDATOR_IFDEF_NAME = "!ASSERT_DISABLED"
  154. class DomainNameFixes:
  155. @classmethod
  156. def get_fixed_data(cls, domain_name):
  157. field_name_res = Capitalizer.upper_camel_case_to_lower(domain_name) + "Agent"
  158. class Res(object):
  159. skip_js_bind = domain_name in cls.skip_js_bind_domains
  160. agent_field_name = field_name_res
  161. @staticmethod
  162. def get_guard():
  163. if domain_name in DOMAIN_DEFINE_NAME_MAP:
  164. define_name = DOMAIN_DEFINE_NAME_MAP[domain_name]
  165. class Guard:
  166. @staticmethod
  167. def generate_open(output):
  168. output.append("#if ENABLE(%s)\n" % define_name)
  169. @staticmethod
  170. def generate_close(output):
  171. output.append("#endif // ENABLE(%s)\n" % define_name)
  172. return Guard
  173. return Res
  174. skip_js_bind_domains = set(["DOMDebugger"])
  175. class RawTypes(object):
  176. @staticmethod
  177. def get(json_type):
  178. if json_type == "boolean":
  179. return RawTypes.Bool
  180. elif json_type == "string":
  181. return RawTypes.String
  182. elif json_type == "array":
  183. return RawTypes.Array
  184. elif json_type == "object":
  185. return RawTypes.Object
  186. elif json_type == "integer":
  187. return RawTypes.Int
  188. elif json_type == "number":
  189. return RawTypes.Number
  190. elif json_type == "any":
  191. return RawTypes.Any
  192. else:
  193. raise Exception("Unknown type: %s" % json_type)
  194. # For output parameter all values are passed by pointer except RefPtr-based types.
  195. class OutputPassModel:
  196. class ByPointer:
  197. @staticmethod
  198. def get_argument_prefix():
  199. return "&"
  200. @staticmethod
  201. def get_parameter_type_suffix():
  202. return "*"
  203. class ByReference:
  204. @staticmethod
  205. def get_argument_prefix():
  206. return ""
  207. @staticmethod
  208. def get_parameter_type_suffix():
  209. return "&"
  210. class BaseType(object):
  211. need_internal_runtime_cast_ = False
  212. @classmethod
  213. def request_raw_internal_runtime_cast(cls):
  214. if not cls.need_internal_runtime_cast_:
  215. cls.need_internal_runtime_cast_ = True
  216. @classmethod
  217. def get_raw_validator_call_text(cls):
  218. return "RuntimeCastHelper::assertType<InspectorValue::Type%s>" % cls.get_validate_method_params().template_type
  219. class String(BaseType):
  220. @staticmethod
  221. def get_getter_name():
  222. return "String"
  223. get_setter_name = get_getter_name
  224. @staticmethod
  225. def get_c_initializer():
  226. return "\"\""
  227. @staticmethod
  228. def get_js_bind_type():
  229. return "string"
  230. @staticmethod
  231. def get_validate_method_params():
  232. class ValidateMethodParams:
  233. template_type = "String"
  234. return ValidateMethodParams
  235. @staticmethod
  236. def get_output_pass_model():
  237. return RawTypes.OutputPassModel.ByPointer
  238. @staticmethod
  239. def is_heavy_value():
  240. return True
  241. @staticmethod
  242. def get_array_item_raw_c_type_text():
  243. return "String"
  244. @staticmethod
  245. def get_raw_type_model():
  246. return TypeModel.String
  247. class Int(BaseType):
  248. @staticmethod
  249. def get_getter_name():
  250. return "Int"
  251. @staticmethod
  252. def get_setter_name():
  253. return "Number"
  254. @staticmethod
  255. def get_c_initializer():
  256. return "0"
  257. @staticmethod
  258. def get_js_bind_type():
  259. return "number"
  260. @classmethod
  261. def get_raw_validator_call_text(cls):
  262. return "RuntimeCastHelper::assertInt"
  263. @staticmethod
  264. def get_output_pass_model():
  265. return RawTypes.OutputPassModel.ByPointer
  266. @staticmethod
  267. def is_heavy_value():
  268. return False
  269. @staticmethod
  270. def get_array_item_raw_c_type_text():
  271. return "int"
  272. @staticmethod
  273. def get_raw_type_model():
  274. return TypeModel.Int
  275. class Number(BaseType):
  276. @staticmethod
  277. def get_getter_name():
  278. return "Double"
  279. @staticmethod
  280. def get_setter_name():
  281. return "Number"
  282. @staticmethod
  283. def get_c_initializer():
  284. return "0"
  285. @staticmethod
  286. def get_js_bind_type():
  287. return "number"
  288. @staticmethod
  289. def get_validate_method_params():
  290. class ValidateMethodParams:
  291. template_type = "Number"
  292. return ValidateMethodParams
  293. @staticmethod
  294. def get_output_pass_model():
  295. return RawTypes.OutputPassModel.ByPointer
  296. @staticmethod
  297. def is_heavy_value():
  298. return False
  299. @staticmethod
  300. def get_array_item_raw_c_type_text():
  301. return "double"
  302. @staticmethod
  303. def get_raw_type_model():
  304. return TypeModel.Number
  305. class Bool(BaseType):
  306. @staticmethod
  307. def get_getter_name():
  308. return "Boolean"
  309. get_setter_name = get_getter_name
  310. @staticmethod
  311. def get_c_initializer():
  312. return "false"
  313. @staticmethod
  314. def get_js_bind_type():
  315. return "boolean"
  316. @staticmethod
  317. def get_validate_method_params():
  318. class ValidateMethodParams:
  319. template_type = "Boolean"
  320. return ValidateMethodParams
  321. @staticmethod
  322. def get_output_pass_model():
  323. return RawTypes.OutputPassModel.ByPointer
  324. @staticmethod
  325. def is_heavy_value():
  326. return False
  327. @staticmethod
  328. def get_array_item_raw_c_type_text():
  329. return "bool"
  330. @staticmethod
  331. def get_raw_type_model():
  332. return TypeModel.Bool
  333. class Object(BaseType):
  334. @staticmethod
  335. def get_getter_name():
  336. return "Object"
  337. @staticmethod
  338. def get_setter_name():
  339. return "Value"
  340. @staticmethod
  341. def get_c_initializer():
  342. return "InspectorObject::create()"
  343. @staticmethod
  344. def get_js_bind_type():
  345. return "object"
  346. @staticmethod
  347. def get_output_argument_prefix():
  348. return ""
  349. @staticmethod
  350. def get_validate_method_params():
  351. class ValidateMethodParams:
  352. template_type = "Object"
  353. return ValidateMethodParams
  354. @staticmethod
  355. def get_output_pass_model():
  356. return RawTypes.OutputPassModel.ByReference
  357. @staticmethod
  358. def is_heavy_value():
  359. return True
  360. @staticmethod
  361. def get_array_item_raw_c_type_text():
  362. return "InspectorObject"
  363. @staticmethod
  364. def get_raw_type_model():
  365. return TypeModel.Object
  366. class Any(BaseType):
  367. @staticmethod
  368. def get_getter_name():
  369. return "Value"
  370. get_setter_name = get_getter_name
  371. @staticmethod
  372. def get_c_initializer():
  373. raise Exception("Unsupported")
  374. @staticmethod
  375. def get_js_bind_type():
  376. raise Exception("Unsupported")
  377. @staticmethod
  378. def get_raw_validator_call_text():
  379. return "RuntimeCastHelper::assertAny"
  380. @staticmethod
  381. def get_output_pass_model():
  382. return RawTypes.OutputPassModel.ByReference
  383. @staticmethod
  384. def is_heavy_value():
  385. return True
  386. @staticmethod
  387. def get_array_item_raw_c_type_text():
  388. return "InspectorValue"
  389. @staticmethod
  390. def get_raw_type_model():
  391. return TypeModel.Any
  392. class Array(BaseType):
  393. @staticmethod
  394. def get_getter_name():
  395. return "Array"
  396. @staticmethod
  397. def get_setter_name():
  398. return "Value"
  399. @staticmethod
  400. def get_c_initializer():
  401. return "InspectorArray::create()"
  402. @staticmethod
  403. def get_js_bind_type():
  404. return "object"
  405. @staticmethod
  406. def get_output_argument_prefix():
  407. return ""
  408. @staticmethod
  409. def get_validate_method_params():
  410. class ValidateMethodParams:
  411. template_type = "Array"
  412. return ValidateMethodParams
  413. @staticmethod
  414. def get_output_pass_model():
  415. return RawTypes.OutputPassModel.ByReference
  416. @staticmethod
  417. def is_heavy_value():
  418. return True
  419. @staticmethod
  420. def get_array_item_raw_c_type_text():
  421. return "InspectorArray"
  422. @staticmethod
  423. def get_raw_type_model():
  424. return TypeModel.Array
  425. def replace_right_shift(input_str):
  426. return input_str.replace(">>", "> >")
  427. class CommandReturnPassModel:
  428. class ByReference:
  429. def __init__(self, var_type, set_condition):
  430. self.var_type = var_type
  431. self.set_condition = set_condition
  432. def get_return_var_type(self):
  433. return self.var_type
  434. @staticmethod
  435. def get_output_argument_prefix():
  436. return ""
  437. @staticmethod
  438. def get_output_to_raw_expression():
  439. return "%s"
  440. def get_output_parameter_type(self):
  441. return self.var_type + "&"
  442. def get_set_return_condition(self):
  443. return self.set_condition
  444. class ByPointer:
  445. def __init__(self, var_type):
  446. self.var_type = var_type
  447. def get_return_var_type(self):
  448. return self.var_type
  449. @staticmethod
  450. def get_output_argument_prefix():
  451. return "&"
  452. @staticmethod
  453. def get_output_to_raw_expression():
  454. return "%s"
  455. def get_output_parameter_type(self):
  456. return self.var_type + "*"
  457. @staticmethod
  458. def get_set_return_condition():
  459. return None
  460. class OptOutput:
  461. def __init__(self, var_type):
  462. self.var_type = var_type
  463. def get_return_var_type(self):
  464. return "TypeBuilder::OptOutput<%s>" % self.var_type
  465. @staticmethod
  466. def get_output_argument_prefix():
  467. return "&"
  468. @staticmethod
  469. def get_output_to_raw_expression():
  470. return "%s.getValue()"
  471. def get_output_parameter_type(self):
  472. return "TypeBuilder::OptOutput<%s>*" % self.var_type
  473. @staticmethod
  474. def get_set_return_condition():
  475. return "%s.isAssigned()"
  476. class TypeModel:
  477. class RefPtrBased(object):
  478. def __init__(self, class_name):
  479. self.class_name = class_name
  480. self.optional = False
  481. def get_optional(self):
  482. result = TypeModel.RefPtrBased(self.class_name)
  483. result.optional = True
  484. return result
  485. def get_command_return_pass_model(self):
  486. if self.optional:
  487. set_condition = "%s"
  488. else:
  489. set_condition = None
  490. return CommandReturnPassModel.ByReference(replace_right_shift("RefPtr<%s>" % self.class_name), set_condition)
  491. def get_input_param_type_text(self):
  492. return replace_right_shift("PassRefPtr<%s>" % self.class_name)
  493. @staticmethod
  494. def get_event_setter_expression_pattern():
  495. return "%s"
  496. class Enum(object):
  497. def __init__(self, base_type_name):
  498. self.type_name = base_type_name + "::Enum"
  499. def get_optional(base_self):
  500. class EnumOptional:
  501. @classmethod
  502. def get_optional(cls):
  503. return cls
  504. @staticmethod
  505. def get_command_return_pass_model():
  506. return CommandReturnPassModel.OptOutput(base_self.type_name)
  507. @staticmethod
  508. def get_input_param_type_text():
  509. return base_self.type_name + "*"
  510. @staticmethod
  511. def get_event_setter_expression_pattern():
  512. raise Exception("TODO")
  513. return EnumOptional
  514. def get_command_return_pass_model(self):
  515. return CommandReturnPassModel.ByPointer(self.type_name)
  516. def get_input_param_type_text(self):
  517. return self.type_name
  518. @staticmethod
  519. def get_event_setter_expression_pattern():
  520. return "%s"
  521. class ValueType(object):
  522. def __init__(self, type_name, is_heavy):
  523. self.type_name = type_name
  524. self.is_heavy = is_heavy
  525. def get_optional(self):
  526. return self.ValueOptional(self)
  527. def get_command_return_pass_model(self):
  528. return CommandReturnPassModel.ByPointer(self.type_name)
  529. def get_input_param_type_text(self):
  530. if self.is_heavy:
  531. return "const %s&" % self.type_name
  532. else:
  533. return self.type_name
  534. def get_opt_output_type_(self):
  535. return self.type_name
  536. @staticmethod
  537. def get_event_setter_expression_pattern():
  538. return "%s"
  539. class ValueOptional:
  540. def __init__(self, base):
  541. self.base = base
  542. def get_optional(self):
  543. return self
  544. def get_command_return_pass_model(self):
  545. return CommandReturnPassModel.OptOutput(self.base.get_opt_output_type_())
  546. def get_input_param_type_text(self):
  547. return "const %s* const" % self.base.type_name
  548. @staticmethod
  549. def get_event_setter_expression_pattern():
  550. return "*%s"
  551. class ExactlyInt(ValueType):
  552. def __init__(self):
  553. TypeModel.ValueType.__init__(self, "int", False)
  554. def get_input_param_type_text(self):
  555. return "TypeBuilder::ExactlyInt"
  556. def get_opt_output_type_(self):
  557. return "TypeBuilder::ExactlyInt"
  558. @classmethod
  559. def init_class(cls):
  560. cls.Bool = cls.ValueType("bool", False)
  561. if EXACTLY_INT_SUPPORTED:
  562. cls.Int = cls.ExactlyInt()
  563. else:
  564. cls.Int = cls.ValueType("int", False)
  565. cls.Number = cls.ValueType("double", False)
  566. cls.String = cls.ValueType("String", True,)
  567. cls.Object = cls.RefPtrBased("InspectorObject")
  568. cls.Array = cls.RefPtrBased("InspectorArray")
  569. cls.Any = cls.RefPtrBased("InspectorValue")
  570. TypeModel.init_class()
  571. # Collection of InspectorObject class methods that are likely to be overloaded in generated class.
  572. # We must explicitly import all overloaded methods or they won't be available to user.
  573. INSPECTOR_OBJECT_SETTER_NAMES = frozenset(["setValue", "setBoolean", "setNumber", "setString", "setValue", "setObject", "setArray"])
  574. def fix_type_name(json_name):
  575. if json_name in TYPE_NAME_FIX_MAP:
  576. fixed = TYPE_NAME_FIX_MAP[json_name]
  577. class Result(object):
  578. class_name = fixed
  579. @staticmethod
  580. def output_comment(writer):
  581. writer.newline("// Type originally was named '%s'.\n" % json_name)
  582. else:
  583. class Result(object):
  584. class_name = json_name
  585. @staticmethod
  586. def output_comment(writer):
  587. pass
  588. return Result
  589. class Writer:
  590. def __init__(self, output, indent):
  591. self.output = output
  592. self.indent = indent
  593. def newline(self, str):
  594. if (self.indent):
  595. self.output.append(self.indent)
  596. self.output.append(str)
  597. def append(self, str):
  598. self.output.append(str)
  599. def newline_multiline(self, str):
  600. parts = str.split('\n')
  601. self.newline(parts[0])
  602. for p in parts[1:]:
  603. self.output.append('\n')
  604. if p:
  605. self.newline(p)
  606. def append_multiline(self, str):
  607. parts = str.split('\n')
  608. self.append(parts[0])
  609. for p in parts[1:]:
  610. self.output.append('\n')
  611. if p:
  612. self.newline(p)
  613. def get_indent(self):
  614. return self.indent
  615. def get_indented(self, additional_indent):
  616. return Writer(self.output, self.indent + additional_indent)
  617. def insert_writer(self, additional_indent):
  618. new_output = []
  619. self.output.append(new_output)
  620. return Writer(new_output, self.indent + additional_indent)
  621. class EnumConstants:
  622. map_ = {}
  623. constants_ = []
  624. @classmethod
  625. def add_constant(cls, value):
  626. if value in cls.map_:
  627. return cls.map_[value]
  628. else:
  629. pos = len(cls.map_)
  630. cls.map_[value] = pos
  631. cls.constants_.append(value)
  632. return pos
  633. @classmethod
  634. def get_enum_constant_code(cls):
  635. output = []
  636. for item in cls.constants_:
  637. output.append(" \"" + item + "\"")
  638. return ",\n".join(output) + "\n"
  639. # Typebuilder code is generated in several passes: first typedefs, then other classes.
  640. # Manual pass management is needed because we cannot have forward declarations for typedefs.
  641. class TypeBuilderPass:
  642. TYPEDEF = "typedef"
  643. MAIN = "main"
  644. class TypeBindings:
  645. @staticmethod
  646. def create_named_type_declaration(json_typable, context_domain_name, type_data):
  647. json_type = type_data.get_json_type()
  648. class Helper:
  649. is_ad_hoc = False
  650. full_name_prefix_for_use = "TypeBuilder::" + context_domain_name + "::"
  651. full_name_prefix_for_impl = "TypeBuilder::" + context_domain_name + "::"
  652. @staticmethod
  653. def write_doc(writer):
  654. if "description" in json_type:
  655. writer.newline("/* ")
  656. writer.append(json_type["description"])
  657. writer.append(" */\n")
  658. @staticmethod
  659. def add_to_forward_listener(forward_listener):
  660. forward_listener.add_type_data(type_data)
  661. fixed_type_name = fix_type_name(json_type["id"])
  662. return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
  663. @staticmethod
  664. def create_ad_hoc_type_declaration(json_typable, context_domain_name, ad_hoc_type_context):
  665. class Helper:
  666. is_ad_hoc = True
  667. full_name_prefix_for_use = ad_hoc_type_context.container_relative_name_prefix
  668. full_name_prefix_for_impl = ad_hoc_type_context.container_full_name_prefix
  669. @staticmethod
  670. def write_doc(writer):
  671. pass
  672. @staticmethod
  673. def add_to_forward_listener(forward_listener):
  674. pass
  675. fixed_type_name = ad_hoc_type_context.get_type_name_fix()
  676. return TypeBindings.create_type_declaration_(json_typable, context_domain_name, fixed_type_name, Helper)
  677. @staticmethod
  678. def create_type_declaration_(json_typable, context_domain_name, fixed_type_name, helper):
  679. if json_typable["type"] == "string":
  680. if "enum" in json_typable:
  681. class EnumBinding:
  682. need_user_runtime_cast_ = False
  683. need_internal_runtime_cast_ = False
  684. @classmethod
  685. def resolve_inner(cls, resolve_context):
  686. pass
  687. @classmethod
  688. def request_user_runtime_cast(cls, request):
  689. if request:
  690. cls.need_user_runtime_cast_ = True
  691. request.acknowledge()
  692. @classmethod
  693. def request_internal_runtime_cast(cls):
  694. cls.need_internal_runtime_cast_ = True
  695. @classmethod
  696. def get_code_generator(enum_binding_cls):
  697. #FIXME: generate ad-hoc enums too once we figure out how to better implement them in C++.
  698. comment_out = helper.is_ad_hoc
  699. class CodeGenerator:
  700. @staticmethod
  701. def generate_type_builder(writer, generate_context):
  702. enum = json_typable["enum"]
  703. helper.write_doc(writer)
  704. enum_name = fixed_type_name.class_name
  705. fixed_type_name.output_comment(writer)
  706. writer.newline("struct ")
  707. writer.append(enum_name)
  708. writer.append(" {\n")
  709. writer.newline(" enum Enum {\n")
  710. for enum_item in enum:
  711. enum_pos = EnumConstants.add_constant(enum_item)
  712. item_c_name = enum_item.replace('-', '_')
  713. item_c_name = Capitalizer.lower_camel_case_to_upper(item_c_name)
  714. if item_c_name in TYPE_NAME_FIX_MAP:
  715. item_c_name = TYPE_NAME_FIX_MAP[item_c_name]
  716. writer.newline(" ")
  717. writer.append(item_c_name)
  718. writer.append(" = ")
  719. writer.append("%s" % enum_pos)
  720. writer.append(",\n")
  721. writer.newline(" };\n")
  722. if enum_binding_cls.need_user_runtime_cast_:
  723. raise Exception("Not yet implemented")
  724. if enum_binding_cls.need_internal_runtime_cast_:
  725. writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
  726. writer.newline(" static void assertCorrectValue(InspectorValue* value);\n")
  727. writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME)
  728. validator_writer = generate_context.validator_writer
  729. domain_fixes = DomainNameFixes.get_fixed_data(context_domain_name)
  730. domain_guard = domain_fixes.get_guard()
  731. if domain_guard:
  732. domain_guard.generate_open(validator_writer)
  733. validator_writer.newline("void %s%s::assertCorrectValue(InspectorValue* value)\n" % (helper.full_name_prefix_for_impl, enum_name))
  734. validator_writer.newline("{\n")
  735. validator_writer.newline(" WTF::String s;\n")
  736. validator_writer.newline(" bool cast_res = value->asString(&s);\n")
  737. validator_writer.newline(" ASSERT(cast_res);\n")
  738. if len(enum) > 0:
  739. condition_list = []
  740. for enum_item in enum:
  741. enum_pos = EnumConstants.add_constant(enum_item)
  742. condition_list.append("s == \"%s\"" % enum_item)
  743. validator_writer.newline(" ASSERT(%s);\n" % " || ".join(condition_list))
  744. validator_writer.newline("}\n")
  745. if domain_guard:
  746. domain_guard.generate_close(validator_writer)
  747. validator_writer.newline("\n\n")
  748. writer.newline("}; // struct ")
  749. writer.append(enum_name)
  750. writer.append("\n\n")
  751. @staticmethod
  752. def register_use(forward_listener):
  753. pass
  754. @staticmethod
  755. def get_generate_pass_id():
  756. return TypeBuilderPass.MAIN
  757. return CodeGenerator
  758. @classmethod
  759. def get_validator_call_text(cls):
  760. return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
  761. @classmethod
  762. def get_array_item_c_type_text(cls):
  763. return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::Enum"
  764. @staticmethod
  765. def get_setter_value_expression_pattern():
  766. return "TypeBuilder::getEnumConstantValue(%s)"
  767. @staticmethod
  768. def reduce_to_raw_type():
  769. return RawTypes.String
  770. @staticmethod
  771. def get_type_model():
  772. return TypeModel.Enum(helper.full_name_prefix_for_use + fixed_type_name.class_name)
  773. return EnumBinding
  774. else:
  775. if helper.is_ad_hoc:
  776. class PlainString:
  777. @classmethod
  778. def resolve_inner(cls, resolve_context):
  779. pass
  780. @staticmethod
  781. def request_user_runtime_cast(request):
  782. raise Exception("Unsupported")
  783. @staticmethod
  784. def request_internal_runtime_cast():
  785. pass
  786. @staticmethod
  787. def get_code_generator():
  788. return None
  789. @classmethod
  790. def get_validator_call_text(cls):
  791. return RawTypes.String.get_raw_validator_call_text()
  792. @staticmethod
  793. def reduce_to_raw_type():
  794. return RawTypes.String
  795. @staticmethod
  796. def get_type_model():
  797. return TypeModel.String
  798. @staticmethod
  799. def get_setter_value_expression_pattern():
  800. return None
  801. @classmethod
  802. def get_array_item_c_type_text(cls):
  803. return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
  804. return PlainString
  805. else:
  806. class TypedefString:
  807. @classmethod
  808. def resolve_inner(cls, resolve_context):
  809. pass
  810. @staticmethod
  811. def request_user_runtime_cast(request):
  812. raise Exception("Unsupported")
  813. @staticmethod
  814. def request_internal_runtime_cast():
  815. RawTypes.String.request_raw_internal_runtime_cast()
  816. @staticmethod
  817. def get_code_generator():
  818. class CodeGenerator:
  819. @staticmethod
  820. def generate_type_builder(writer, generate_context):
  821. helper.write_doc(writer)
  822. fixed_type_name.output_comment(writer)
  823. writer.newline("typedef String ")
  824. writer.append(fixed_type_name.class_name)
  825. writer.append(";\n\n")
  826. @staticmethod
  827. def register_use(forward_listener):
  828. pass
  829. @staticmethod
  830. def get_generate_pass_id():
  831. return TypeBuilderPass.TYPEDEF
  832. return CodeGenerator
  833. @classmethod
  834. def get_validator_call_text(cls):
  835. return RawTypes.String.get_raw_validator_call_text()
  836. @staticmethod
  837. def reduce_to_raw_type():
  838. return RawTypes.String
  839. @staticmethod
  840. def get_type_model():
  841. return TypeModel.ValueType("%s%s" % (helper.full_name_prefix_for_use, fixed_type_name.class_name), True)
  842. @staticmethod
  843. def get_setter_value_expression_pattern():
  844. return None
  845. @classmethod
  846. def get_array_item_c_type_text(cls):
  847. return "const %s%s&" % (helper.full_name_prefix_for_use, fixed_type_name.class_name)
  848. return TypedefString
  849. elif json_typable["type"] == "object":
  850. if "properties" in json_typable:
  851. class ClassBinding:
  852. resolve_data_ = None
  853. need_user_runtime_cast_ = False
  854. need_internal_runtime_cast_ = False
  855. @classmethod
  856. def resolve_inner(cls, resolve_context):
  857. if cls.resolve_data_:
  858. return
  859. properties = json_typable["properties"]
  860. main = []
  861. optional = []
  862. ad_hoc_type_list = []
  863. for prop in properties:
  864. prop_name = prop["name"]
  865. ad_hoc_type_context = cls.AdHocTypeContextImpl(prop_name, fixed_type_name.class_name, resolve_context, ad_hoc_type_list, helper.full_name_prefix_for_impl)
  866. binding = resolve_param_type(prop, context_domain_name, ad_hoc_type_context)
  867. code_generator = binding.get_code_generator()
  868. if code_generator:
  869. code_generator.register_use(resolve_context.forward_listener)
  870. class PropertyData:
  871. param_type_binding = binding
  872. p = prop
  873. if prop.get("optional"):
  874. optional.append(PropertyData)
  875. else:
  876. main.append(PropertyData)
  877. class ResolveData:
  878. main_properties = main
  879. optional_properties = optional
  880. ad_hoc_types = ad_hoc_type_list
  881. cls.resolve_data_ = ResolveData
  882. for ad_hoc in ad_hoc_type_list:
  883. ad_hoc.resolve_inner(resolve_context)
  884. @classmethod
  885. def request_user_runtime_cast(cls, request):
  886. if not request:
  887. return
  888. cls.need_user_runtime_cast_ = True
  889. request.acknowledge()
  890. cls.request_internal_runtime_cast()
  891. @classmethod
  892. def request_internal_runtime_cast(cls):
  893. if cls.need_internal_runtime_cast_:
  894. return
  895. cls.need_internal_runtime_cast_ = True
  896. for p in cls.resolve_data_.main_properties:
  897. p.param_type_binding.request_internal_runtime_cast()
  898. for p in cls.resolve_data_.optional_properties:
  899. p.param_type_binding.request_internal_runtime_cast()
  900. @classmethod
  901. def get_code_generator(class_binding_cls):
  902. class CodeGenerator:
  903. @classmethod
  904. def generate_type_builder(cls, writer, generate_context):
  905. resolve_data = class_binding_cls.resolve_data_
  906. helper.write_doc(writer)
  907. class_name = fixed_type_name.class_name
  908. is_open_type = (context_domain_name + "." + class_name) in TYPES_WITH_OPEN_FIELD_LIST_SET
  909. fixed_type_name.output_comment(writer)
  910. writer.newline("class ")
  911. writer.append(class_name)
  912. writer.append(" : public ")
  913. if is_open_type:
  914. writer.append("InspectorObject")
  915. else:
  916. writer.append("InspectorObjectBase")
  917. writer.append(" {\n")
  918. writer.newline("public:\n")
  919. ad_hoc_type_writer = writer.insert_writer(" ")
  920. for ad_hoc_type in resolve_data.ad_hoc_types:
  921. code_generator = ad_hoc_type.get_code_generator()
  922. if code_generator:
  923. code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
  924. writer.newline_multiline(
  925. """ enum {
  926. NoFieldsSet = 0,
  927. """)
  928. state_enum_items = []
  929. if len(resolve_data.main_properties) > 0:
  930. pos = 0
  931. for prop_data in resolve_data.main_properties:
  932. item_name = Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]) + "Set"
  933. state_enum_items.append(item_name)
  934. writer.newline(" %s = 1 << %s,\n" % (item_name, pos))
  935. pos += 1
  936. all_fields_set_value = "(" + (" | ".join(state_enum_items)) + ")"
  937. else:
  938. all_fields_set_value = "0"
  939. writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_1
  940. % (all_fields_set_value, class_name, class_name))
  941. pos = 0
  942. for prop_data in resolve_data.main_properties:
  943. prop_name = prop_data.p["name"]
  944. param_type_binding = prop_data.param_type_binding
  945. param_raw_type = param_type_binding.reduce_to_raw_type()
  946. writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_2
  947. % (state_enum_items[pos],
  948. Capitalizer.lower_camel_case_to_upper(prop_name),
  949. param_type_binding.get_type_model().get_input_param_type_text(),
  950. state_enum_items[pos], prop_name,
  951. param_raw_type.get_setter_name(), prop_name,
  952. format_setter_value_expression(param_type_binding, "value"),
  953. state_enum_items[pos]))
  954. pos += 1
  955. writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_3
  956. % (class_name, class_name, class_name, class_name, class_name))
  957. writer.newline(" /*\n")
  958. writer.newline(" * Synthetic constructor:\n")
  959. writer.newline(" * RefPtr<%s> result = %s::create()" % (class_name, class_name))
  960. for prop_data in resolve_data.main_properties:
  961. writer.append_multiline("\n * .set%s(...)" % Capitalizer.lower_camel_case_to_upper(prop_data.p["name"]))
  962. writer.append_multiline(";\n */\n")
  963. writer.newline_multiline(CodeGeneratorInspectorStrings.class_binding_builder_part_4)
  964. writer.newline(" typedef TypeBuilder::StructItemTraits ItemTraits;\n")
  965. for prop_data in resolve_data.optional_properties:
  966. prop_name = prop_data.p["name"]
  967. param_type_binding = prop_data.param_type_binding
  968. setter_name = "set%s" % Capitalizer.lower_camel_case_to_upper(prop_name)
  969. writer.append_multiline("\n void %s" % setter_name)
  970. writer.append("(%s value)\n" % param_type_binding.get_type_model().get_input_param_type_text())
  971. writer.newline(" {\n")
  972. writer.newline(" this->set%s(\"%s\", %s);\n"
  973. % (param_type_binding.reduce_to_raw_type().get_setter_name(), prop_data.p["name"],
  974. format_setter_value_expression(param_type_binding, "value")))
  975. writer.newline(" }\n")
  976. if setter_name in INSPECTOR_OBJECT_SETTER_NAMES:
  977. writer.newline(" using InspectorObjectBase::%s;\n\n" % setter_name)
  978. if class_binding_cls.need_user_runtime_cast_:
  979. writer.newline(" static PassRefPtr<%s> runtimeCast(PassRefPtr<InspectorValue> value)\n" % class_name)
  980. writer.newline(" {\n")
  981. writer.newline(" RefPtr<InspectorObject> object;\n")
  982. writer.newline(" bool castRes = value->asObject(&object);\n")
  983. writer.newline(" ASSERT_UNUSED(castRes, castRes);\n")
  984. writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
  985. writer.newline(" assertCorrectValue(object.get());\n")
  986. writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME)
  987. writer.newline(" COMPILE_ASSERT(sizeof(%s) == sizeof(InspectorObjectBase), type_cast_problem);\n" % class_name)
  988. writer.newline(" return static_cast<%s*>(static_cast<InspectorObjectBase*>(object.get()));\n" % class_name)
  989. writer.newline(" }\n")
  990. writer.append("\n")
  991. if class_binding_cls.need_internal_runtime_cast_:
  992. writer.append("#if %s\n" % VALIDATOR_IFDEF_NAME)
  993. writer.newline(" static void assertCorrectValue(InspectorValue* value);\n")
  994. writer.append("#endif // %s\n" % VALIDATOR_IFDEF_NAME)
  995. closed_field_set = (context_domain_name + "." + class_name) not in TYPES_WITH_OPEN_FIELD_LIST_SET
  996. validator_writer = generate_context.validator_writer
  997. domain_fixes = DomainNameFixes.get_fixed_data(context_domain_name)
  998. domain_guard = domain_fixes.get_guard()
  999. if domain_guard:
  1000. domain_guard.generate_open(validator_writer)
  1001. validator_writer.newline("void %s%s::assertCorrectValue(InspectorValue* value)\n" % (helper.full_name_prefix_for_impl, class_name))
  1002. validator_writer.newline("{\n")
  1003. validator_writer.newline(" RefPtr<InspectorObject> object;\n")
  1004. validator_writer.newline(" bool castRes = value->asObject(&object);\n")
  1005. validator_writer.newline(" ASSERT_UNUSED(castRes, castRes);\n")
  1006. for prop_data in resolve_data.main_properties:
  1007. validator_writer.newline(" {\n")
  1008. it_name = "%sPos" % prop_data.p["name"]
  1009. validator_writer.newline(" InspectorObject::iterator %s;\n" % it_name)
  1010. validator_writer.newline(" %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
  1011. validator_writer.newline(" ASSERT(%s != object->end());\n" % it_name)
  1012. validator_writer.newline(" %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
  1013. validator_writer.newline(" }\n")
  1014. if closed_field_set:
  1015. validator_writer.newline(" int foundPropertiesCount = %s;\n" % len(resolve_data.main_properties))
  1016. for prop_data in resolve_data.optional_properties:
  1017. validator_writer.newline(" {\n")
  1018. it_name = "%sPos" % prop_data.p["name"]
  1019. validator_writer.newline(" InspectorObject::iterator %s;\n" % it_name)
  1020. validator_writer.newline(" %s = object->find(\"%s\");\n" % (it_name, prop_data.p["name"]))
  1021. validator_writer.newline(" if (%s != object->end()) {\n" % it_name)
  1022. validator_writer.newline(" %s(%s->value.get());\n" % (prop_data.param_type_binding.get_validator_call_text(), it_name))
  1023. if closed_field_set:
  1024. validator_writer.newline(" ++foundPropertiesCount;\n")
  1025. validator_writer.newline(" }\n")
  1026. validator_writer.newline(" }\n")
  1027. if closed_field_set:
  1028. validator_writer.newline(" if (foundPropertiesCount != object->size()) {\n")
  1029. validator_writer.newline(" FATAL(\"Unexpected properties in object: %s\\n\", object->toJSONString().ascii().data());\n")
  1030. validator_writer.newline(" }\n")
  1031. validator_writer.newline("}\n")
  1032. if domain_guard:
  1033. domain_guard.generate_close(validator_writer)
  1034. validator_writer.newline("\n\n")
  1035. if is_open_type:
  1036. cpp_writer = generate_context.cpp_writer
  1037. writer.append("\n")
  1038. writer.newline(" // Property names for type generated as open.\n")
  1039. for prop_data in resolve_data.main_properties + resolve_data.optional_properties:
  1040. prop_name = prop_data.p["name"]
  1041. prop_field_name = Capitalizer.lower_camel_case_to_upper(prop_name)
  1042. writer.newline(" static const char* %s;\n" % (prop_field_name))
  1043. cpp_writer.newline("const char* %s%s::%s = \"%s\";\n" % (helper.full_name_prefix_for_impl, class_name, prop_field_name, prop_name))
  1044. writer.newline("};\n\n")
  1045. @staticmethod
  1046. def generate_forward_declaration(writer):
  1047. class_name = fixed_type_name.class_name
  1048. writer.newline("class ")
  1049. writer.append(class_name)
  1050. writer.append(";\n")
  1051. @staticmethod
  1052. def register_use(forward_listener):
  1053. helper.add_to_forward_listener(forward_listener)
  1054. @staticmethod
  1055. def get_generate_pass_id():
  1056. return TypeBuilderPass.MAIN
  1057. return CodeGenerator
  1058. @staticmethod
  1059. def get_validator_call_text():
  1060. return helper.full_name_prefix_for_use + fixed_type_name.class_name + "::assertCorrectValue"
  1061. @classmethod
  1062. def get_array_item_c_type_text(cls):
  1063. return helper.full_name_prefix_for_use + fixed_type_name.class_name
  1064. @staticmethod
  1065. def get_setter_value_expression_pattern():
  1066. return None
  1067. @staticmethod
  1068. def reduce_to_raw_type():
  1069. return RawTypes.Object
  1070. @staticmethod
  1071. def get_type_model():
  1072. return TypeModel.RefPtrBased(helper.full_name_prefix_for_use + fixed_type_name.class_name)
  1073. class AdHocTypeContextImpl:
  1074. def __init__(self, property_name, class_name, resolve_context, ad_hoc_type_list, parent_full_name_prefix):
  1075. self.property_name = property_name
  1076. self.class_name = class_name
  1077. self.resolve_context = resolve_context
  1078. self.ad_hoc_type_list = ad_hoc_type_list
  1079. self.container_full_name_prefix = parent_full_name_prefix + class_name + "::"
  1080. self.container_relative_name_prefix = ""
  1081. def get_type_name_fix(self):
  1082. class NameFix:
  1083. class_name = Capitalizer.lower_camel_case_to_upper(self.property_name)
  1084. @staticmethod
  1085. def output_comment(writer):
  1086. writer.newline("// Named after property name '%s' while generating %s.\n" % (self.property_name, self.class_name))
  1087. return NameFix
  1088. def add_type(self, binding):
  1089. self.ad_hoc_type_list.append(binding)
  1090. return ClassBinding
  1091. else:
  1092. class PlainObjectBinding:
  1093. @classmethod
  1094. def resolve_inner(cls, resolve_context):
  1095. pass
  1096. @staticmethod
  1097. def request_user_runtime_cast(request):
  1098. pass
  1099. @staticmethod
  1100. def request_internal_runtime_cast():
  1101. RawTypes.Object.request_raw_internal_runtime_cast()
  1102. @staticmethod
  1103. def get_code_generator():
  1104. pass
  1105. @staticmethod
  1106. def get_validator_call_text():
  1107. return "RuntimeCastHelper::assertType<InspectorValue::TypeObject>"
  1108. @classmethod
  1109. def get_array_item_c_type_text(cls):
  1110. return cls.reduce_to_raw_type().get_array_item_raw_c_type_text()
  1111. @staticmethod
  1112. def get_setter_value_expression_pattern():
  1113. return None
  1114. @staticmethod
  1115. def reduce_to_raw_type():
  1116. return RawTypes.Object
  1117. @staticmethod
  1118. def get_type_model():
  1119. return TypeModel.Object
  1120. return PlainObjectBinding
  1121. elif json_typable["type"] == "array":
  1122. if "items" in json_typable:
  1123. ad_hoc_types = []
  1124. class AdHocTypeContext:
  1125. container_full_name_prefix = "<not yet defined>"
  1126. container_relative_name_prefix = ""
  1127. @staticmethod
  1128. def get_type_name_fix():
  1129. return fixed_type_name
  1130. @staticmethod
  1131. def add_type(binding):
  1132. ad_hoc_types.append(binding)
  1133. item_binding = resolve_param_type(json_typable["items"], context_domain_name, AdHocTypeContext)
  1134. class ArrayBinding:
  1135. resolve_data_ = None
  1136. need_internal_runtime_cast_ = False
  1137. @classmethod
  1138. def resolve_inner(cls, resolve_context):
  1139. if cls.resolve_data_:
  1140. return
  1141. class ResolveData:
  1142. item_type_binding = item_binding
  1143. ad_hoc_type_list = ad_hoc_types
  1144. cls.resolve_data_ = ResolveData
  1145. for t in ad_hoc_types:
  1146. t.resolve_inner(resolve_context)
  1147. @classmethod
  1148. def request_user_runtime_cast(cls, request):
  1149. raise Exception("Not implemented yet")
  1150. @classmethod
  1151. def request_internal_runtime_cast(cls):
  1152. if cls.need_internal_runtime_cast_:
  1153. return
  1154. cls.need_internal_runtime_cast_ = True
  1155. cls.resolve_data_.item_type_binding.request_internal_runtime_cast()
  1156. @classmethod
  1157. def get_code_generator(array_binding_cls):
  1158. class CodeGenerator:
  1159. @staticmethod
  1160. def generate_type_builder(writer, generate_context):
  1161. ad_hoc_type_writer = writer
  1162. resolve_data = array_binding_cls.resolve_data_
  1163. for ad_hoc_type in resolve_data.ad_hoc_type_list:
  1164. code_generator = ad_hoc_type.get_code_generator()
  1165. if code_generator:
  1166. code_generator.generate_type_builder(ad_hoc_type_writer, generate_context)
  1167. @staticmethod
  1168. def generate_forward_declaration(writer):
  1169. pass
  1170. @staticmethod
  1171. def register_use(forward_listener):
  1172. item_code_generator = item_binding.get_code_generator()
  1173. if item_code_generator:
  1174. item_code_generator.register_use(forward_listener)
  1175. @staticmethod
  1176. def get_generate_pass_id():
  1177. return TypeBuilderPass.MAIN
  1178. return CodeGenerator
  1179. @classmethod
  1180. def get_validator_call_text(cls):
  1181. return cls.get_array_item_c_type_text() + "::assertCorrectValue"
  1182. @classmethod
  1183. def get_array_item_c_type_text(cls):
  1184. return replace_right_shift("TypeBuilder::Array<%s>" % cls.resolve_data_.item_type_binding.get_array_item_c_type_text())
  1185. @staticmethod
  1186. def get_setter_value_expression_pattern():
  1187. return None
  1188. @staticmethod
  1189. def reduce_to_raw_type():
  1190. return RawTypes.Array
  1191. @classmethod
  1192. def get_type_model(cls):
  1193. return TypeModel.RefPtrBased(cls.get_array_item_c_type_text())
  1194. return ArrayBinding
  1195. else:
  1196. # Fall-through to raw type.
  1197. pass
  1198. raw_type = RawTypes.get(json_typable["type"])
  1199. return RawTypeBinding(raw_type)
  1200. class RawTypeBinding:
  1201. def __init__(self, raw_type):
  1202. self.raw_type_ = raw_type
  1203. def resolve_inner(self, resolve_context):
  1204. pass
  1205. def request_user_runtime_cast(self, request):
  1206. raise Exception("Unsupported")
  1207. def request_internal_runtime_cast(self):
  1208. self.raw_type_.request_raw_internal_runtime_cast()
  1209. def get_code_generator(self):
  1210. return None
  1211. def get_validator_call_text(self):
  1212. return self.raw_type_.get_raw_validator_call_text()
  1213. def get_array_item_c_type_text(self):
  1214. return self.raw_type_.get_array_item_raw_c_type_text()
  1215. def get_setter_value_expression_pattern(self):
  1216. return None
  1217. def reduce_to_raw_type(self):
  1218. return self.raw_type_
  1219. def get_type_model(self):
  1220. return self.raw_type_.get_raw_type_model()
  1221. class TypeData(object):
  1222. def __init__(self, json_type, json_domain, domain_data):
  1223. self.json_type_ = json_type
  1224. self.json_domain_ = json_domain
  1225. self.domain_data_ = domain_data
  1226. if "type" not in json_type:
  1227. raise Exception("Unknown type")
  1228. json_type_name = json_type["type"]
  1229. raw_type = RawTypes.get(json_type_name)
  1230. self.raw_type_ = raw_type
  1231. self.binding_being_resolved_ = False
  1232. self.binding_ = None
  1233. def get_raw_type(self):
  1234. return self.raw_type_
  1235. def get_binding(self):
  1236. if not self.binding_:
  1237. if self.binding_being_resolved_:
  1238. raise Error("Type %s is already being resolved" % self.json_type_["type"])
  1239. # Resolve only lazily, because resolving one named type may require resolving some other named type.
  1240. self.binding_being_resolved_ = True
  1241. try:
  1242. self.binding_ = TypeBindings.create_named_type_declaration(self.json_type_, self.json_domain_["domain"], self)
  1243. finally:
  1244. self.binding_being_resolved_ = False
  1245. return self.binding_
  1246. def get_json_type(self):
  1247. return self.json_type_
  1248. def get_name(self):
  1249. return self.json_type_["id"]
  1250. def get_domain_name(self):
  1251. return self.json_domain_["domain"]
  1252. class DomainData:
  1253. def __init__(self, json_domain):
  1254. self.json_domain = json_domain
  1255. self.types_ = []
  1256. def add_type(self, type_data):
  1257. self.types_.append(type_data)
  1258. def name(self):
  1259. return self.json_domain["domain"]
  1260. def types(self):
  1261. return self.types_
  1262. class TypeMap:
  1263. def __init__(self, api):
  1264. self.map_ = {}
  1265. self.domains_ = []
  1266. for json_domain in api["domains"]:
  1267. domain_name = json_domain["domain"]
  1268. domain_map = {}
  1269. self.map_[domain_name] = domain_map
  1270. domain_data = DomainData(json_domain)
  1271. self.domains_.append(domain_data)
  1272. if "types" in json_domain:
  1273. for json_type in json_domain["types"]:
  1274. type_name = json_type["id"]
  1275. type_data = TypeData(json_type, json_domain, domain_data)
  1276. domain_map[type_name] = type_data
  1277. domain_data.add_type(type_data)
  1278. def domains(self):
  1279. return self.domains_
  1280. def get(self, domain_name, type_name):
  1281. return self.map_[domain_name][type_name]
  1282. def resolve_param_type(json_parameter, scope_domain_name, ad_hoc_type_context):
  1283. if "$ref" in json_parameter:
  1284. json_ref = json_parameter["$ref"]
  1285. type_data = get_ref_data(json_ref, scope_domain_name)
  1286. return type_data.get_binding()
  1287. elif "type" in json_parameter:
  1288. result = TypeBindings.create_ad_hoc_type_declaration(json_parameter, scope_domain_name, ad_hoc_type_context)
  1289. ad_hoc_type_context.add_type(result)
  1290. return result
  1291. else:
  1292. raise Exception("Unknown type")
  1293. def resolve_param_raw_type(json_parameter, scope_domain_name):
  1294. if "$ref" in json_parameter:
  1295. json_ref = json_parameter["$ref"]
  1296. type_data = get_ref_data(json_ref, scope_domain_name)
  1297. return type_data.get_raw_type()
  1298. elif "type" in json_parameter:
  1299. json_type = json_parameter["type"]
  1300. return RawTypes.get(json_type)
  1301. else:
  1302. raise Exception("Unknown type")
  1303. def get_ref_data(json_ref, scope_domain_name):
  1304. dot_pos = json_ref.find(".")
  1305. if dot_pos == -1:
  1306. domain_name = scope_domain_name
  1307. type_name = json_ref
  1308. else:
  1309. domain_name = json_ref[:dot_pos]
  1310. type_name = json_ref[dot_pos + 1:]
  1311. return type_map.get(domain_name, type_name)
  1312. input_file = open(input_json_filename, "r")
  1313. json_string = input_file.read()
  1314. json_api = json.loads(json_string)
  1315. class Templates:
  1316. def get_this_script_path_(absolute_path):
  1317. absolute_path = os.path.abspath(absolute_path)
  1318. components = []
  1319. def fill_recursive(path_part, depth):
  1320. if depth <= 0 or path_part == '/':
  1321. return
  1322. fill_recursive(os.path.dirname(path_part), depth - 1)
  1323. components.append(os.path.basename(path_part))
  1324. # Typical path is /Source/WebCore/inspector/CodeGeneratorInspector.py
  1325. # Let's take 4 components from the real path then.
  1326. fill_recursive(absolute_path, 4)
  1327. return "/".join(components)
  1328. file_header_ = ("// File is generated by %s\n\n" % get_this_script_path_(sys.argv[0]) +
  1329. """// Copyright (c) 2011 The Chromium Authors. All rights reserved.
  1330. // Use of this source code is governed by a BSD-style license that can be
  1331. // found in the LICENSE file.
  1332. """)
  1333. frontend_domain_class = string.Template(CodeGeneratorInspectorStrings.frontend_domain_class)
  1334. backend_method = string.Template(CodeGeneratorInspectorStrings.backend_method)
  1335. frontend_method = string.Template(CodeGeneratorInspectorStrings.frontend_method)
  1336. callback_method = string.Template(CodeGeneratorInspectorStrings.callback_method)
  1337. frontend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_h)
  1338. backend_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_h)
  1339. backend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_cpp)
  1340. frontend_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.frontend_cpp)
  1341. typebuilder_h = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_h)
  1342. typebuilder_cpp = string.Template(file_header_ + CodeGeneratorInspectorStrings.typebuilder_cpp)
  1343. backend_js = string.Template(file_header_ + CodeGeneratorInspectorStrings.backend_js)
  1344. param_container_access_code = CodeGeneratorInspectorStrings.param_container_access_code
  1345. type_map = TypeMap(json_api)
  1346. class NeedRuntimeCastRequest:
  1347. def __init__(self):
  1348. self.ack_ = None
  1349. def acknowledge(self):
  1350. self.ack_ = True
  1351. def is_acknowledged(self):
  1352. return self.ack_
  1353. def resolve_all_types():
  1354. runtime_cast_generate_requests = {}
  1355. for type_name in TYPES_WITH_RUNTIME_CAST_SET:
  1356. runtime_cast_generate_requests[type_name] = NeedRuntimeCastRequest()
  1357. class ForwardListener:
  1358. type_data_set = set()
  1359. already_declared_set = set()
  1360. @classmethod
  1361. def add_type_data(cls, type_data):
  1362. if type_data not in cls.already_declared_set:
  1363. cls.type_data_set.add(type_data)
  1364. class ResolveContext:
  1365. forward_listener = ForwardListener
  1366. for domain_data in type_map.domains():
  1367. for type_data in domain_data.types():
  1368. # Do not generate forwards for this type any longer.
  1369. ForwardListener.already_declared_set.add(type_data)
  1370. binding = type_data.get_binding()
  1371. binding.resolve_inner(ResolveContext)
  1372. for domain_data in type_map.domains():
  1373. for type_data in domain_data.types():
  1374. full_type_name = "%s.%s" % (type_data.get_domain_name(), type_data.get_name())
  1375. request = runtime_cast_generate_requests.pop(full_type_name, None)
  1376. binding = type_data.get_binding()
  1377. if request:
  1378. binding.request_user_runtime_cast(request)
  1379. if request and not request.is_acknowledged():
  1380. raise Exception("Failed to generate runtimeCast in " + full_type_name)
  1381. for full_type_name in runtime_cast_generate_requests:
  1382. raise Exception("Failed to generate runtimeCast. Type " + full_type_name + " not found")
  1383. return ForwardListener
  1384. global_forward_listener = resolve_all_types()
  1385. def get_annotated_type_text(raw_type, annotated_type):
  1386. if annotated_type != raw_type:
  1387. return "/*%s*/ %s" % (annotated_type, raw_type)
  1388. else:
  1389. return raw_type
  1390. def format_setter_value_expression(param_type_binding, value_ref):
  1391. pattern = param_type_binding.get_setter_value_expression_pattern()
  1392. if pattern:
  1393. return pattern % value_ref
  1394. else:
  1395. return value_ref
  1396. class Generator:
  1397. frontend_class_field_lines = []
  1398. frontend_domain_class_lines = []
  1399. method_name_enum_list = []
  1400. backend_method_declaration_list = []
  1401. backend_method_implementation_list = []
  1402. backend_method_name_declaration_list = []
  1403. method_handler_list = []
  1404. frontend_method_list = []
  1405. backend_js_domain_initializer_list = []
  1406. backend_virtual_setters_list = []
  1407. backend_agent_interface_list = []
  1408. backend_setters_list = []
  1409. backend_constructor_init_list = []
  1410. backend_field_list = []
  1411. frontend_constructor_init_list = []
  1412. type_builder_fragments = []
  1413. type_builder_forwards = []
  1414. validator_impl_list = []
  1415. type_builder_impl_list = []
  1416. @staticmethod
  1417. def go():
  1418. Generator.process_types(type_map)
  1419. first_cycle_guardable_list_list = [
  1420. Generator.backend_method_declaration_list,
  1421. Generator.backend_method_implementation_list,
  1422. Generator.backend_method_name_declaration_list,
  1423. Generator.backend_agent_interface_list,
  1424. Generator.frontend_class_field_lines,
  1425. Generator.frontend_constructor_init_list,
  1426. Generator.frontend_domain_class_lines,
  1427. Generator.frontend_method_list,
  1428. Generator.method_handler_list,
  1429. Generator.method_name_enum_list,
  1430. Generator.backend_constructor_init_list,
  1431. Generator.backend_virtual_setters_list,
  1432. Generator.backend_setters_list,
  1433. Generator.backend_field_list]
  1434. for json_domain in json_api["domains"]:
  1435. domain_name = json_domain["domain"]
  1436. domain_name_lower = domain_name.lower()
  1437. domain_fixes = DomainNameFixes.get_fixed_data(domain_name)
  1438. domain_guard = domain_fixes.get_guard()
  1439. if domain_guard:
  1440. for l in first_cycle_guardable_list_list:
  1441. domain_guard.generate_open(l)
  1442. agent_field_name = domain_fixes.agent_field_name
  1443. frontend_method_declaration_lines = []
  1444. Generator.backend_js_domain_initializer_list.append("// %s.\n" % domain_name)
  1445. if not domain_fixes.skip_js_bind:
  1446. Generator.backend_js_domain_initializer_list.append("InspectorBackend.register%sDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, \"%s\");\n" % (domain_name, domain_name))
  1447. if "types" in json_domain:
  1448. for json_type in json_domain["types"]:
  1449. if "type" in json_type and json_type["type"] == "string" and "enum" in json_type:
  1450. enum_name = "%s.%s" % (domain_name, json_type["id"])
  1451. Generator.process_enum(json_type, enum_name)
  1452. elif json_type["type"] == "object":
  1453. if "properties" in json_type:
  1454. for json_property in json_type["properties"]:
  1455. if "type" in json_property and json_property["type"] == "string" and "enum" in json_property:
  1456. enum_name = "%s.%s%s" % (domain_name, json_type["id"], to_title_case(json_property["name"]))
  1457. Generator.process_enum(json_property, enum_name)
  1458. if "events" in json_domain:
  1459. for json_event in json_domain["events"]:
  1460. Generator.process_event(json_event, domain_name, frontend_method_declaration_lines)
  1461. Generator.frontend_class_field_lines.append(" %s m_%s;\n" % (domain_name, domain_name_lower))
  1462. if Generator.frontend_constructor_init_list:
  1463. Generator.frontend_constructor_init_list.append(" , ")
  1464. Generator.frontend_constructor_init_list.append("m_%s(inspectorFrontendChannel)\n" % domain_name_lower)
  1465. Generator.frontend_domain_class_lines.append(Templates.frontend_domain_class.substitute(None,
  1466. domainClassName=domain_name,
  1467. domainFieldName=domain_name_lower,
  1468. frontendDomainMethodDeclarations="".join(flatten_list(frontend_method_declaration_lines))))
  1469. agent_interface_name = Capitalizer.lower_camel_case_to_upper(domain_name) + "CommandHandler"
  1470. Generator.backend_agent_interface_list.append(" class %s {\n" % agent_interface_name)
  1471. Generator.backend_agent_interface_list.append(" public:\n")
  1472. if "commands" in json_domain:
  1473. for json_command in json_domain["commands"]:
  1474. Generator.process_command(json_command, domain_name, agent_field_name, agent_interface_name)
  1475. Generator.backend_agent_interface_list.append("\n protected:\n")
  1476. Generator.backend_agent_interface_list.append(" virtual ~%s() { }\n" % agent_interface_name)
  1477. Generator.backend_agent_interface_list.append(" };\n\n")
  1478. Generator.backend_constructor_init_list.append(" , m_%s(0)" % agent_field_name)
  1479. Generator.backend_virtual_setters_list.append(" virtual void registerAgent(%s* %s) = 0;" % (agent_interface_name, agent_field_name))
  1480. Generator.backend_setters_list.append(" virtual void registerAgent(%s* %s) { ASSERT(!m_%s); m_%s = %s; }" % (agent_interface_name, agent_field_name, agent_field_name, agent_field_name, agent_field_name))
  1481. Generator.backend_field_list.append(" %s* m_%s;" % (agent_interface_name, agent_field_name))
  1482. if domain_guard:
  1483. for l in reversed(first_cycle_guardable_list_list):
  1484. domain_guard.generate_close(l)
  1485. Generator.backend_js_domain_initializer_list.append("\n")
  1486. @staticmethod
  1487. def process_enum(json_enum, enum_name):
  1488. enum_members = []
  1489. for member in json_enum["enum"]:
  1490. enum_members.append("%s: \"%s\"" % (fix_camel_case(member), member))
  1491. Generator.backend_js_domain_initializer_list.append("InspectorBackend.registerEnum(\"%s\", {%s});\n" % (
  1492. enum_name, ", ".join(enum_members)))
  1493. @staticmethod
  1494. def process_event(json_event, domain_name, frontend_method_declaration_lines):
  1495. event_name = json_event["name"]
  1496. ad_hoc_type_output = []
  1497. frontend_method_declaration_lines.append(ad_hoc_type_output)
  1498. ad_hoc_type_writer = Writer(ad_hoc_type_output, " ")
  1499. decl_parameter_list = []
  1500. json_parameters = json_event.get("parameters")
  1501. Generator.generate_send_method(json_parameters, event_name, domain_name, ad_hoc_type_writer,
  1502. decl_parameter_list,
  1503. Generator.EventMethodStructTemplate,
  1504. Generator.frontend_method_list, Templates.frontend_method, {"eventName": event_name})
  1505. backend_js_event_param_list = []
  1506. if json_parameters:
  1507. for parameter in json_parameters:
  1508. parameter_name = parameter["name"]
  1509. backend_js_event_param_list.append("\"%s\"" % parameter_name)
  1510. frontend_method_declaration_lines.append(
  1511. " void %s(%s);\n" % (event_name, ", ".join(decl_parameter_list)))
  1512. Generator.backend_js_domain_initializer_list.append("InspectorBackend.registerEvent(\"%s.%s\", [%s]);\n" % (
  1513. domain_name, event_name, ", ".join(backend_js_event_param_list)))
  1514. class EventMethodStructTemplate:
  1515. @staticmethod
  1516. def append_prolog(line_list):
  1517. line_list.append(" RefPtr<InspectorObject> paramsObject = InspectorObject::create();\n")
  1518. @staticmethod
  1519. def append_epilog(line_list):
  1520. line_list.append(" jsonMessage->setObject(\"params\", paramsObject);\n")
  1521. container_name = "paramsObject"
  1522. @staticmethod
  1523. def process_command(json_command, domain_name, agent_field_name, agent_interface_name):
  1524. json_command_name = json_command["name"]
  1525. cmd_enum_name = "k%s_%sCmd" % (domain_name, json_command["name"])
  1526. Generator.method_name_enum_list.append(" %s," % cmd_enum_name)
  1527. Generator.method_handler_list.append(" &InspectorBackendDispatcherImpl::%s_%s," % (domain_name, json_command_name))
  1528. Generator.backend_method_declaration_list.append(" void %s_%s(long callId, InspectorObject* requestMessageObject);" % (domain_name, json_command_name))
  1529. ad_hoc_type_output = []
  1530. Generator.backend_agent_interface_list.append(ad_hoc_type_output)
  1531. ad_hoc_type_writer = Writer(ad_hoc_type_output, " ")
  1532. Generator.backend_agent_interface_list.append(" virtual void %s(ErrorString*" % json_command_name)
  1533. method_in_code = ""
  1534. method_out_code = ""
  1535. agent_call_param_list = []
  1536. response_cook_list = []
  1537. request_message_param = ""
  1538. js_parameters_text = ""
  1539. if "parameters" in json_command:
  1540. json_params = json_command["parameters"]
  1541. method_in_code += Templates.param_container_access_code
  1542. request_message_param = " requestMessageObject"
  1543. js_param_list = []
  1544. for json_parameter in json_params:
  1545. json_param_name = json_parameter["name"]
  1546. param_raw_type = resolve_param_raw_type(json_parameter, domain_name)
  1547. getter_name = param_raw_type.get_getter_name()
  1548. optional = json_parameter.get("optional")
  1549. non_optional_type_model = param_raw_type.get_raw_type_model()
  1550. if optional:
  1551. type_model = non_optional_type_model.get_optional()
  1552. else:
  1553. type_model = non_optional_type_model
  1554. if optional:
  1555. code = (" bool %s_valueFound = false;\n"
  1556. " %s in_%s = get%s(paramsContainerPtr, \"%s\", &%s_valueFound, protocolErrorsPtr);\n" %
  1557. (json_param_name, non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name, json_param_name))
  1558. param = ", %s_valueFound ? &in_%s : 0" % (json_param_name, json_param_name)
  1559. # FIXME: pass optional refptr-values as PassRefPtr
  1560. formal_param_type_pattern = "const %s*"
  1561. else:
  1562. code = (" %s in_%s = get%s(paramsContainerPtr, \"%s\", 0, protocolErrorsPtr);\n" %
  1563. (non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name, getter_name, json_param_name))
  1564. param = ", in_%s" % json_param_name
  1565. # FIXME: pass not-optional refptr-values as NonNullPassRefPtr
  1566. if param_raw_type.is_heavy_value():
  1567. formal_param_type_pattern = "const %s&"
  1568. else:
  1569. formal_param_type_pattern = "%s"
  1570. method_in_code += code
  1571. agent_call_param_list.append(param)
  1572. Generator.backend_agent_interface_list.append(", %s in_%s" % (formal_param_type_pattern % non_optional_type_model.get_command_return_pass_model().get_return_var_type(), json_param_name))
  1573. js_bind_type = param_raw_type.get_js_bind_type()
  1574. js_param_text = "{\"name\": \"%s\", \"type\": \"%s\", \"optional\": %s}" % (
  1575. json_param_name,
  1576. js_bind_type,
  1577. ("true" if ("optional" in json_parameter and json_parameter["optional"]) else "false"))
  1578. js_param_list.append(js_param_text)
  1579. js_parameters_text = ", ".join(js_param_list)
  1580. response_cook_text = ""
  1581. if json_command.get("async") == True:
  1582. callback_name = Capitalizer.lower_camel_case_to_upper(json_command_name) + "Callback"
  1583. callback_output = []
  1584. callback_writer = Writer(callback_output, ad_hoc_type_writer.get_indent())
  1585. decl_parameter_list = []
  1586. Generator.generate_send_method(json_command.get("returns"), json_command_name, domain_name, ad_hoc_type_writer,
  1587. decl_parameter_list,
  1588. Generator.CallbackMethodStructTemplate,
  1589. Generator.backend_method_implementation_list, Templates.callback_method,
  1590. {"callbackName": callback_name, "agentName": agent_interface_name})
  1591. callback_writer.newline("class " + callback_name + " : public CallbackBase {\n")
  1592. callback_writer.newline("public:\n")
  1593. callback_writer.newline(" " + callback_name + "(PassRefPtr<InspectorBackendDispatcherImpl>, int id);\n")
  1594. callback_writer.newline(" void sendSuccess(" + ", ".join(decl_parameter_list) + ");\n")
  1595. callback_writer.newline("};\n")
  1596. ad_hoc_type_output.append(callback_output)
  1597. method_out_code += " RefPtr<" + agent_interface_name + "::" + callback_name + "> callback = adoptRef(new " + agent_interface_name + "::" + callback_name + "(this, callId));\n"
  1598. agent_call_param_list.append(", callback")
  1599. response_cook_text += " if (!error.length()) \n"
  1600. response_cook_text += " return;\n"
  1601. response_cook_text += " callback->disable();\n"
  1602. Generator.backend_agent_interface_list.append(", PassRefPtr<%s> callback" % callback_name)
  1603. else:
  1604. if "returns" in json_command:
  1605. method_out_code += "\n"
  1606. for json_return in json_command["returns"]:
  1607. json_return_name = json_return["name"]
  1608. optional = bool(json_return.get("optional"))
  1609. return_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_return, json_command_name, domain_name, ad_hoc_type_writer, agent_interface_name + "::")
  1610. raw_type = return_type_binding.reduce_to_raw_type()
  1611. setter_type = raw_type.get_setter_name()
  1612. initializer = raw_type.get_c_initializer()
  1613. type_model = return_type_binding.get_type_model()
  1614. if optional:
  1615. type_model = type_model.get_optional()
  1616. code = " %s out_%s;\n" % (type_model.get_command_return_pass_model().get_return_var_type(), json_return_name)
  1617. param = ", %sout_%s" % (type_model.get_command_return_pass_model().get_output_argument_prefix(), json_return_name)
  1618. var_name = "out_%s" % json_return_name
  1619. setter_argument = type_model.get_command_return_pass_model().get_output_to_raw_expression() % var_name
  1620. if return_type_binding.get_setter_value_expression_pattern():
  1621. setter_argument = return_type_binding.get_setter_value_expression_pattern() % setter_argument
  1622. cook = " result->set%s(\"%s\", %s);\n" % (setter_type, json_return_name,
  1623. setter_argument)
  1624. set_condition_pattern = type_model.get_command_return_pass_model().get_set_return_condition()
  1625. if set_condition_pattern:
  1626. cook = (" if (%s)\n " % (set_condition_pattern % var_name)) + cook
  1627. annotated_type = type_model.get_command_return_pass_model().get_output_parameter_type()
  1628. param_name = "out_%s" % json_return_name
  1629. if optional:
  1630. param_name = "opt_" + param_name
  1631. Generator.backend_agent_interface_list.append(", %s %s" % (annotated_type, param_name))
  1632. response_cook_list.append(cook)
  1633. method_out_code += code
  1634. agent_call_param_list.append(param)
  1635. response_cook_text = "".join(response_cook_list)
  1636. if len(response_cook_text) != 0:
  1637. response_cook_text = " if (!error.length()) {\n" + response_cook_text + " }"
  1638. backend_js_reply_param_list = []
  1639. if "returns" in json_command:
  1640. for json_return in json_command["returns"]:
  1641. json_return_name = json_return["name"]
  1642. backend_js_reply_param_list.append("\"%s\"" % json_return_name)
  1643. js_reply_list = "[%s]" % ", ".join(backend_js_reply_param_list)
  1644. Generator.backend_method_implementation_list.append(Templates.backend_method.substitute(None,
  1645. domainName=domain_name, methodName=json_command_name,
  1646. agentField="m_" + agent_field_name,
  1647. methodInCode=method_in_code,
  1648. methodOutCode=method_out_code,
  1649. agentCallParams="".join(agent_call_param_list),
  1650. requestMessageObject=request_message_param,
  1651. responseCook=response_cook_text,
  1652. commandNameIndex=cmd_enum_name))
  1653. Generator.backend_method_name_declaration_list.append(" \"%s.%s\"," % (domain_name, json_command_name))
  1654. Generator.backend_js_domain_initializer_list.append("InspectorBackend.registerCommand(\"%s.%s\", [%s], %s);\n" % (domain_name, json_command_name, js_parameters_text, js_reply_list))
  1655. Generator.backend_agent_interface_list.append(") = 0;\n")
  1656. class CallbackMethodStructTemplate:
  1657. @staticmethod
  1658. def append_prolog(line_list):
  1659. pass
  1660. @staticmethod
  1661. def append_epilog(line_list):
  1662. pass
  1663. container_name = "jsonMessage"
  1664. # Generates common code for event sending and callback response data sending.
  1665. @staticmethod
  1666. def generate_send_method(parameters, event_name, domain_name, ad_hoc_type_writer, decl_parameter_list,
  1667. method_struct_template,
  1668. generator_method_list, method_template, template_params):
  1669. method_line_list = []
  1670. if parameters:
  1671. method_struct_template.append_prolog(method_line_list)
  1672. for json_parameter in parameters:
  1673. parameter_name = json_parameter["name"]
  1674. param_type_binding = Generator.resolve_type_and_generate_ad_hoc(json_parameter, event_name, domain_name, ad_hoc_type_writer, "")
  1675. raw_type = param_type_binding.reduce_to_raw_type()
  1676. raw_type_binding = RawTypeBinding(raw_type)
  1677. optional = bool(json_parameter.get("optional"))
  1678. setter_type = raw_type.get_setter_name()
  1679. type_model = param_type_binding.get_type_model()
  1680. raw_type_model = raw_type_binding.get_type_model()
  1681. if optional:
  1682. type_model = type_model.get_optional()
  1683. raw_type_model = raw_type_model.get_optional()
  1684. annotated_type = type_model.get_input_param_type_text()
  1685. mode_type_binding = param_type_binding
  1686. decl_parameter_list.append("%s %s" % (annotated_type, parameter_name))
  1687. setter_argument = raw_type_model.get_event_setter_expression_pattern() % parameter_name
  1688. if mode_type_binding.get_setter_value_expression_pattern():
  1689. setter_argument = mode_type_binding.get_setter_value_expression_pattern() % setter_argument
  1690. setter_code = " %s->set%s(\"%s\", %s);\n" % (method_struct_template.container_name, setter_type, parameter_name, setter_argument)
  1691. if optional:
  1692. setter_code = (" if (%s)\n " % parameter_name) + setter_code
  1693. method_line_list.append(setter_code)
  1694. method_struct_template.append_epilog(method_line_list)
  1695. generator_method_list.append(method_template.substitute(None,
  1696. domainName=domain_name,
  1697. parameters=", ".join(decl_parameter_list),
  1698. code="".join(method_line_list), **template_params))
  1699. @staticmethod
  1700. def resolve_type_and_generate_ad_hoc(json_param, method_name, domain_name, ad_hoc_type_writer, container_relative_name_prefix_param):
  1701. param_name = json_param["name"]
  1702. ad_hoc_type_list = []
  1703. class AdHocTypeContext:
  1704. container_full_name_prefix = "<not yet defined>"
  1705. container_relative_name_prefix = container_relative_name_prefix_param
  1706. @staticmethod
  1707. def get_type_name_fix():
  1708. class NameFix:
  1709. class_name = Capitalizer.lower_camel_case_to_upper(param_name)
  1710. @staticmethod
  1711. def output_comment(writer):
  1712. writer.newline("// Named after parameter '%s' while generating command/event %s.\n" % (param_name, method_name))
  1713. return NameFix
  1714. @staticmethod
  1715. def add_type(binding):
  1716. ad_hoc_type_list.append(binding)
  1717. type_binding = resolve_param_type(json_param, domain_name, AdHocTypeContext)
  1718. class InterfaceForwardListener:
  1719. @staticmethod
  1720. def add_type_data(type_data):
  1721. pass
  1722. class InterfaceResolveContext:
  1723. forward_listener = InterfaceForwardListener
  1724. for type in ad_hoc_type_list:
  1725. type.resolve_inner(InterfaceResolveContext)
  1726. class InterfaceGenerateContext:
  1727. validator_writer = "not supported in InterfaceGenerateContext"
  1728. cpp_writer = validator_writer
  1729. for type in ad_hoc_type_list:
  1730. generator = type.get_code_generator()
  1731. if generator:
  1732. generator.generate_type_builder(ad_hoc_type_writer, InterfaceGenerateContext)
  1733. return type_binding
  1734. @staticmethod
  1735. def process_types(type_map):
  1736. output = Generator.type_builder_fragments
  1737. class GenerateContext:
  1738. validator_writer = Writer(Generator.validator_impl_list, "")
  1739. cpp_writer = Writer(Generator.type_builder_impl_list, "")
  1740. def generate_all_domains_code(out, type_data_callback):
  1741. writer = Writer(out, "")
  1742. for domain_data in type_map.domains():
  1743. domain_fixes = DomainNameFixes.get_fixed_data(domain_data.name())
  1744. domain_guard = domain_fixes.get_guard()
  1745. namespace_declared = []
  1746. def namespace_lazy_generator():
  1747. if not namespace_declared:
  1748. if domain_guard:
  1749. domain_guard.generate_open(out)
  1750. writer.newline("namespace ")
  1751. writer.append(domain_data.name())
  1752. writer.append(" {\n")
  1753. # What is a better way to change value from outer scope?
  1754. namespace_declared.append(True)
  1755. return writer
  1756. for type_data in domain_data.types():
  1757. type_data_callback(type_data, namespace_lazy_generator)
  1758. if namespace_declared:
  1759. writer.append("} // ")
  1760. writer.append(domain_data.name())
  1761. writer.append("\n\n")
  1762. if domain_guard:
  1763. domain_guard.generate_close(out)
  1764. def create_type_builder_caller(generate_pass_id):
  1765. def call_type_builder(type_data, writer_getter):
  1766. code_generator = type_data.get_binding().get_code_generator()
  1767. if code_generator and generate_pass_id == code_generator.get_generate_pass_id():
  1768. writer = writer_getter()
  1769. code_generator.generate_type_builder(writer, GenerateContext)
  1770. return call_type_builder
  1771. generate_all_domains_code(output, create_type_builder_caller(TypeBuilderPass.MAIN))
  1772. Generator.type_builder_forwards.append("// Forward declarations.\n")
  1773. def generate_forward_callback(type_data, writer_getter):
  1774. if type_data in global_forward_listener.type_data_set:
  1775. binding = type_data.get_binding()
  1776. binding.get_code_generator().generate_forward_declaration(writer_getter())
  1777. generate_all_domains_code(Generator.type_builder_forwards, generate_forward_callback)
  1778. Generator.type_builder_forwards.append("// End of forward declarations.\n\n")
  1779. Generator.type_builder_forwards.append("// Typedefs.\n")
  1780. generate_all_domains_code(Generator.type_builder_forwards, create_type_builder_caller(TypeBuilderPass.TYPEDEF))
  1781. Generator.type_builder_forwards.append("// End of typedefs.\n\n")
  1782. def flatten_list(input):
  1783. res = []
  1784. def fill_recursive(l):
  1785. for item in l:
  1786. if isinstance(item, list):
  1787. fill_recursive(item)
  1788. else:
  1789. res.append(item)
  1790. fill_recursive(input)
  1791. return res
  1792. # A writer that only updates file if it actually changed to better support incremental build.
  1793. class SmartOutput:
  1794. def __init__(self, file_name):
  1795. self.file_name_ = file_name
  1796. self.output_ = ""
  1797. def write(self, text):
  1798. self.output_ += text
  1799. def close(self):
  1800. text_changed = True
  1801. try:
  1802. read_file = open(self.file_name_, "r")
  1803. old_text = read_file.read()
  1804. read_file.close()
  1805. text_changed = old_text != self.output_
  1806. except:
  1807. # Ignore, just overwrite by default
  1808. pass
  1809. if text_changed or write_always:
  1810. out_file = open(self.file_name_, "w")
  1811. out_file.write(self.output_)
  1812. out_file.close()
  1813. Generator.go()
  1814. backend_h_file = SmartOutput(output_header_dirname + "/InspectorBackendDispatcher.h")
  1815. backend_cpp_file = SmartOutput(output_cpp_dirname + "/InspectorBackendDispatcher.cpp")
  1816. frontend_h_file = SmartOutput(output_header_dirname + "/InspectorFrontend.h")
  1817. frontend_cpp_file = SmartOutput(output_cpp_dirname + "/InspectorFrontend.cpp")
  1818. typebuilder_h_file = SmartOutput(output_header_dirname + "/InspectorTypeBuilder.h")
  1819. typebuilder_cpp_file = SmartOutput(output_cpp_dirname + "/InspectorTypeBuilder.cpp")
  1820. backend_js_file = SmartOutput(output_cpp_dirname + "/InspectorBackendCommands.js")
  1821. backend_h_file.write(Templates.backend_h.substitute(None,
  1822. virtualSetters="\n".join(Generator.backend_virtual_setters_list),
  1823. agentInterfaces="".join(flatten_list(Generator.backend_agent_interface_list)),
  1824. methodNamesEnumContent="\n".join(Generator.method_name_enum_list)))
  1825. backend_cpp_file.write(Templates.backend_cpp.substitute(None,
  1826. constructorInit="\n".join(Generator.backend_constructor_init_list),
  1827. setters="\n".join(Generator.backend_setters_list),
  1828. fieldDeclarations="\n".join(Generator.backend_field_list),
  1829. methodNameDeclarations="\n".join(Generator.backend_method_name_declaration_list),
  1830. methods="\n".join(Generator.backend_method_implementation_list),
  1831. methodDeclarations="\n".join(Generator.backend_method_declaration_list),
  1832. messageHandlers="\n".join(Generator.method_handler_list)))
  1833. frontend_h_file.write(Templates.frontend_h.substitute(None,
  1834. fieldDeclarations="".join(Generator.frontend_class_field_lines),
  1835. domainClassList="".join(Generator.frontend_domain_class_lines)))
  1836. frontend_cpp_file.write(Templates.frontend_cpp.substitute(None,
  1837. constructorInit="".join(Generator.frontend_constructor_init_list),
  1838. methods="\n".join(Generator.frontend_method_list)))
  1839. typebuilder_h_file.write(Templates.typebuilder_h.substitute(None,
  1840. typeBuilders="".join(flatten_list(Generator.type_builder_fragments)),
  1841. forwards="".join(Generator.type_builder_forwards),
  1842. validatorIfdefName=VALIDATOR_IFDEF_NAME))
  1843. typebuilder_cpp_file.write(Templates.typebuilder_cpp.substitute(None,
  1844. enumConstantValues=EnumConstants.get_enum_constant_code(),
  1845. implCode="".join(flatten_list(Generator.type_builder_impl_list)),
  1846. validatorCode="".join(flatten_list(Generator.validator_impl_list)),
  1847. validatorIfdefName=VALIDATOR_IFDEF_NAME))
  1848. backend_js_file.write(Templates.backend_js.substitute(None,
  1849. domainInitializers="".join(Generator.backend_js_domain_initializer_list)))
  1850. backend_h_file.close()
  1851. backend_cpp_file.close()
  1852. frontend_h_file.close()
  1853. frontend_cpp_file.close()
  1854. typebuilder_h_file.close()
  1855. typebuilder_cpp_file.close()
  1856. backend_js_file.close()