| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2013 Google Inc. All rights reserved. | 2 # Copyright (c) 2013 Google Inc. All rights reserved. |
| 3 # | 3 # |
| 4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
| 6 # met: | 6 # met: |
| 7 # | 7 # |
| 8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 import optparse | 30 import optparse |
| 31 import re | 31 import re |
| 32 import string | 32 import string |
| 33 import sys | 33 import sys |
| 34 | 34 |
| 35 template_h = string.Template("""// Code generated from InspectorInstrumentation.
idl | 35 template_h = string.Template("""// Code generated from InspectorInstrumentation.
idl |
| 36 | 36 |
| 37 #ifndef InspectorInstrumentationInl_h | 37 #ifndef ${file_name}_h |
| 38 #define InspectorInstrumentationInl_h | 38 #define ${file_name}_h |
| 39 |
| 40 ${includes} |
| 39 | 41 |
| 40 namespace WebCore { | 42 namespace WebCore { |
| 41 | 43 |
| 42 namespace InspectorInstrumentation { | 44 namespace InspectorInstrumentation { |
| 43 | 45 |
| 44 $impl_declarations | 46 $methods |
| 45 $inline_methods | |
| 46 } // namespace InspectorInstrumentation | 47 } // namespace InspectorInstrumentation |
| 47 | 48 |
| 48 } // namespace WebCore | 49 } // namespace WebCore |
| 49 | 50 |
| 50 #endif // !defined(InspectorInstrumentationInl_h) | 51 #endif // !defined(${file_name}_h) |
| 51 """) | 52 """) |
| 52 | 53 |
| 53 template_inline = string.Template(""" | 54 template_inline = string.Template(""" |
| 54 inline void ${name}(${params_public}) | 55 inline void ${name}(${params_public}) |
| 55 { ${fast_return} | 56 { ${fast_return} |
| 56 if (InstrumentingAgents* instrumentingAgents = ${agents_getter}) | 57 if (${condition}) |
| 57 ${name}Impl(${params_impl}); | 58 ${name}Impl(${params_impl}); |
| 58 } | 59 } |
| 59 """) | 60 """) |
| 60 | 61 |
| 61 template_inline_forward = string.Template(""" | 62 template_inline_forward = string.Template(""" |
| 62 inline void ${name}(${params_public}) | 63 inline void ${name}(${params_public}) |
| 63 { ${fast_return} | 64 { ${fast_return} |
| 64 ${name}Impl(${params_impl}); | 65 ${name}Impl(${params_impl}); |
| 65 } | 66 } |
| 66 """) | 67 """) |
| 67 | 68 |
| 68 template_inline_accepts_cookie = string.Template(""" | 69 template_inline_returns_value = string.Template(""" |
| 69 inline void ${name}(${params_public}) | 70 inline ${return_type} ${name}(${params_public}) |
| 70 { ${fast_return} | 71 { ${fast_return} |
| 71 if (${cookie}.isValid()) | 72 if (${condition}) |
| 72 ${name}Impl(${params_impl}); | 73 return ${name}Impl(${params_impl}); |
| 74 return ${default_return_value}; |
| 73 } | 75 } |
| 74 """) | 76 """) |
| 75 | 77 |
| 76 template_inline_returns_cookie = string.Template(""" | |
| 77 inline InspectorInstrumentationCookie ${name}(${params_public}) | |
| 78 { ${fast_return} | |
| 79 if (InstrumentingAgents* instrumentingAgents = ${agents_getter}) | |
| 80 return ${name}Impl(${params_impl}); | |
| 81 return InspectorInstrumentationCookie(); | |
| 82 } | |
| 83 """) | |
| 84 | |
| 85 | 78 |
| 86 template_cpp = string.Template("""// Code generated from InspectorInstrumentatio
n.idl | 79 template_cpp = string.Template("""// Code generated from InspectorInstrumentatio
n.idl |
| 87 | 80 |
| 88 #include "config.h" | 81 #include "config.h" |
| 89 #include "core/inspector/InspectorInstrumentation.h" | |
| 90 | 82 |
| 91 #include "core/inspector/InspectorAgent.h" | 83 ${includes} |
| 92 #include "core/inspector/InspectorApplicationCacheAgent.h" | |
| 93 #include "core/inspector/InspectorCSSAgent.h" | |
| 94 #include "core/inspector/InspectorCanvasAgent.h" | |
| 95 #include "core/inspector/InspectorConsoleAgent.h" | |
| 96 #include "core/inspector/InspectorConsoleInstrumentation.h" | |
| 97 #include "core/inspector/InspectorDOMAgent.h" | |
| 98 #include "core/inspector/InspectorDOMDebuggerAgent.h" | |
| 99 #include "core/inspector/InspectorDOMStorageAgent.h" | |
| 100 #include "core/inspector/InspectorDatabaseAgent.h" | |
| 101 #include "core/inspector/InspectorDatabaseInstrumentation.h" | |
| 102 #include "core/inspector/InspectorDebuggerAgent.h" | |
| 103 #include "core/inspector/InspectorHeapProfilerAgent.h" | |
| 104 #include "core/inspector/InspectorLayerTreeAgent.h" | |
| 105 #include "core/inspector/InspectorPageAgent.h" | |
| 106 #include "core/inspector/InspectorProfilerAgent.h" | |
| 107 #include "core/inspector/InspectorResourceAgent.h" | |
| 108 #include "core/inspector/InspectorTimelineAgent.h" | |
| 109 #include "core/inspector/InspectorWorkerAgent.h" | |
| 110 #include "core/inspector/InstrumentingAgents.h" | |
| 111 #include "core/inspector/PageDebuggerAgent.h" | |
| 112 #include "core/inspector/PageRuntimeAgent.h" | |
| 113 #include "core/inspector/WorkerRuntimeAgent.h" | |
| 114 | 84 |
| 115 namespace WebCore { | 85 namespace WebCore { |
| 86 ${extra_definitions} |
| 116 | 87 |
| 117 namespace InspectorInstrumentation { | 88 namespace InspectorInstrumentation { |
| 118 $out_of_line_methods | 89 $methods |
| 119 | 90 |
| 120 } // namespace InspectorInstrumentation | 91 } // namespace InspectorInstrumentation |
| 121 | 92 |
| 122 } // namespace WebCore | 93 } // namespace WebCore |
| 123 """) | 94 """) |
| 124 | 95 |
| 125 template_outofline = string.Template(""" | 96 template_outofline = string.Template(""" |
| 126 void ${name}Impl(${params_impl}) | 97 ${return_type} ${name}Impl(${params_impl}) |
| 127 {${agent_calls} | 98 {${impl_lines} |
| 128 }""") | 99 }""") |
| 129 | 100 |
| 130 template_agent_call = string.Template(""" | 101 template_agent_call = string.Template(""" |
| 131 if (${agent_class}* ${agent}Agent = ${agent_fetch}) | 102 if (${agent_class}* agent = ${agent_fetch}) |
| 132 ${agent}Agent->${name}(${params_agent});""") | 103 ${maybe_return}agent->${name}(${params_agent});""") |
| 133 | 104 |
| 134 template_timeline_agent_call = string.Template(""" | 105 template_agent_call_timeline_returns_cookie = string.Template(""" |
| 135 int timelineAgentId = 0; | 106 int timelineAgentId = 0; |
| 136 if (InspectorTimelineAgent* timelineAgent = instrumentingAgents->inspectorTi
melineAgent()) { | 107 if (InspectorTimelineAgent* agent = agents->inspectorTimelineAgent()) { |
| 137 if (timelineAgent->${name}(${params_agent})) | 108 if (agent->${name}(${params_agent})) |
| 138 timelineAgentId = timelineAgent->id(); | 109 timelineAgentId = agent->id(); |
| 139 }""") | 110 }""") |
| 140 | 111 |
| 141 template_outofline_returns_cookie = string.Template(""" | 112 |
| 142 ${return_type} ${name}Impl(${params_impl}) | 113 template_instrumenting_agents_h = string.Template("""// Code generated from Insp
ectorInstrumentation.idl |
| 143 {${agent_calls} | 114 |
| 144 return InspectorInstrumentationCookie(instrumentingAgents, ${timeline_agent_
id}); | 115 #ifndef InstrumentingAgentsInl_h |
| 116 #define InstrumentingAgentsInl_h |
| 117 |
| 118 #include <wtf/FastAllocBase.h> |
| 119 #include <wtf/Noncopyable.h> |
| 120 #include <wtf/PassRefPtr.h> |
| 121 #include <wtf/RefCounted.h> |
| 122 |
| 123 namespace WebCore { |
| 124 |
| 125 ${forward_list} |
| 126 |
| 127 class InstrumentingAgents : public RefCounted<InstrumentingAgents> { |
| 128 WTF_MAKE_NONCOPYABLE(InstrumentingAgents); |
| 129 WTF_MAKE_FAST_ALLOCATED; |
| 130 public: |
| 131 static PassRefPtr<InstrumentingAgents> create() |
| 132 { |
| 133 return adoptRef(new InstrumentingAgents()); |
| 134 } |
| 135 ~InstrumentingAgents() { } |
| 136 void reset(); |
| 137 |
| 138 ${accessor_list} |
| 139 |
| 140 private: |
| 141 InstrumentingAgents(); |
| 142 |
| 143 ${member_list} |
| 144 }; |
| 145 |
| 146 } |
| 147 |
| 148 #endif // !defined(InstrumentingAgentsInl_h) |
| 149 """) |
| 150 |
| 151 template_instrumenting_agent_accessor = string.Template(""" |
| 152 ${class_name}* ${getter_name}() const { return ${member_name}; } |
| 153 void set${class_name}(${class_name}* agent) { ${member_name} = agent; }""") |
| 154 |
| 155 template_instrumenting_agents_cpp = string.Template(""" |
| 156 InstrumentingAgents::InstrumentingAgents() |
| 157 : $init_list |
| 158 { |
| 159 } |
| 160 |
| 161 void InstrumentingAgents::reset() |
| 162 { |
| 163 $reset_list |
| 145 }""") | 164 }""") |
| 146 | 165 |
| 147 | 166 |
| 167 |
| 168 def match_and_consume(pattern, source): |
| 169 match = re.match(pattern, source) |
| 170 if match: |
| 171 return match, source[len(match.group(0)):].strip() |
| 172 return None, source |
| 173 |
| 174 |
| 148 def load_model_from_idl(source): | 175 def load_model_from_idl(source): |
| 149 source = re.sub("//.*\n", "", source) # Remove line comments | 176 source = re.sub("//.*", "", source) # Remove line comments |
| 150 source = re.sub("\n", " ", source) # Remove newlines | 177 source = re.sub("/\*(.|\n)*?\*/", "", source, re.MULTILINE) # Remove block
comments |
| 151 source = re.sub("/\*.*\*/", "", source) # Remove block comments | 178 source = re.sub("\]\s*?\n\s*", "] ", source) # Merge the method annotation
with the next line |
| 152 source = re.sub("\s\s+", " ", source) # Collapse whitespace | |
| 153 source = source.strip() | 179 source = source.strip() |
| 154 | 180 |
| 155 match = re.match("interface\s\w*\s?\{(.*)\}", source) | 181 model = [] |
| 156 if not match: | 182 |
| 157 sys.stderr.write("Cannot parse the file") | 183 while len(source): |
| 158 sys.exit(1) | 184 match, source = match_and_consume("interface\s(\w*)\s?\{([^\{]*)\}", sou
rce) |
| 159 lines = match.group(1) | 185 if not match: |
| 160 | 186 sys.stderr.write("Cannot parse %s\n" % source[:100]) |
| 161 methods = [] | 187 sys.exit(1) |
| 162 for line in map(str.strip, lines.split(";")): | 188 model.append(File(match.group(1), match.group(2))) |
| 163 if len(line) == 0: | 189 |
| 164 continue | 190 return model |
| 165 methods.append(Method(line)) | 191 |
| 166 return methods | 192 |
| 193 class File: |
| 194 def __init__(self, name, source): |
| 195 self.name = name |
| 196 self.header_name = self.name + "Inl" |
| 197 self.includes = [include_inspector_header("InspectorInstrumentation")] |
| 198 self.declarations = [] |
| 199 for line in map(str.strip, source.split("\n")): |
| 200 line = re.sub("\s{2,}", " ", line).strip() # Collapse whitespace |
| 201 if len(line) == 0: |
| 202 continue |
| 203 if line[0] == "#": |
| 204 self.includes.append(line) |
| 205 else: |
| 206 self.declarations.append(Method(line)) |
| 207 self.includes.sort() |
| 208 |
| 209 def generate(self, cpp_lines, used_agents): |
| 210 header_lines = [] |
| 211 for declaration in self.declarations: |
| 212 for agent in set(declaration.agents): |
| 213 used_agents.add(agent) |
| 214 declaration.generate_header(header_lines) |
| 215 declaration.generate_cpp(cpp_lines) |
| 216 |
| 217 return template_h.substitute(None, |
| 218 file_name=self.header_name, |
| 219 includes="\n".join(self.includes), |
| 220 methods="\n".join(header_lines)) |
| 167 | 221 |
| 168 | 222 |
| 169 class Method: | 223 class Method: |
| 170 def __init__(self, source): | 224 def __init__(self, source): |
| 171 match = re.match("(\[[\w|,|=|\s]*\])?\s?(\w*) (\w*)\((.*)\)", source) | 225 match = re.match("(\[[\w|,|=|\s]*\])?\s?(\w*\*?) (\w*)\((.*)\)\s?;", sou
rce) |
| 172 if not match: | 226 if not match: |
| 173 sys.stderr.write("Cannot parse %s\n" % source) | 227 sys.stderr.write("Cannot parse %s\n" % source) |
| 174 sys.exit(1) | 228 sys.exit(1) |
| 175 | 229 |
| 176 self.method_options = [] | 230 self.options = [] |
| 177 if match.group(1): | 231 if match.group(1): |
| 178 method_options_str = re.sub("\s", "", match.group(1)[1:-1]) | 232 options_str = re.sub("\s", "", match.group(1)[1:-1]) |
| 179 if len(method_options_str) != 0: | 233 if len(options_str) != 0: |
| 180 self.method_options = method_options_str.split(",") | 234 self.options = options_str.split(",") |
| 181 | 235 |
| 182 self.return_type = match.group(2) | 236 self.return_type = match.group(2) |
| 183 | 237 |
| 184 self.name = match.group(3) | 238 self.name = match.group(3) |
| 185 | 239 |
| 186 param_string = match.group(4) | 240 # Splitting parameters by a comma, assuming that attribute lists contain
no more than one attribute. |
| 187 | 241 self.params = map(Parameter, map(str.strip, match.group(4).split(","))) |
| 188 self.param_options = [] | 242 |
| 189 options_match = re.match("\[(.*)\]\s?(.*)", param_string) | 243 self.accepts_cookie = len(self.params) and self.params[0].type == "const
InspectorInstrumentationCookie&" |
| 190 if options_match: | 244 self.returns_cookie = self.return_type == "InspectorInstrumentationCooki
e" |
| 191 param_string = options_match.group(2) | 245 |
| 192 self.param_options = map(str.strip, options_match.group(1).split(","
)) | 246 self.returns_value = self.return_type != "void" |
| 193 | 247 |
| 194 self.params = map(Parameter, map(str.strip, param_string.split(","))) | 248 if self.return_type == "bool": |
| 249 self.default_return_value = "false" |
| 250 elif self.return_type == "String": |
| 251 self.default_return_value = "\"\"" |
| 252 else: |
| 253 self.default_return_value = self.return_type + "()" |
| 254 |
| 255 for param in self.params: |
| 256 if "DefaultReturn" in param.options: |
| 257 self.default_return_value = param.name |
| 258 |
| 259 self.params_impl = self.params |
| 260 if not self.accepts_cookie and not "Inline=Forward" in self.options: |
| 261 if not "Keep" in self.params_impl[0].options: |
| 262 self.params_impl = self.params_impl[1:] |
| 263 self.params_impl = [Parameter("InstrumentingAgents* agents")] + self
.params_impl |
| 264 self.agents_selector_class = re.match("(\w*)", self.params[0].type).
group(1) |
| 265 |
| 266 self.agents = filter(lambda option: not "=" in option, self.options) |
| 267 |
| 268 def generate_header(self, header_lines): |
| 269 if "Inline=Custom" in self.options: |
| 270 return |
| 271 |
| 272 header_lines.append("%s %sImpl(%s);" % ( |
| 273 self.return_type, self.name, ", ".join(map(Parameter.to_str_class, s
elf.params_impl)))) |
| 274 |
| 275 if "Inline=FastReturn" in self.options or "Inline=Forward" in self.optio
ns: |
| 276 fast_return = "\n FAST_RETURN_IF_NO_FRONTENDS(%s);" % self.defaul
t_return_value |
| 277 else: |
| 278 fast_return = "" |
| 279 |
| 280 for param in self.params: |
| 281 if "FastReturn" in param.options: |
| 282 fast_return += "\n if (!%s)\n return %s;" % (param.nam
e, self.default_return_value) |
| 283 |
| 284 if self.accepts_cookie: |
| 285 condition = "%s.isValid()" % self.params_impl[0].name |
| 286 template = template_inline |
| 287 elif "Inline=Forward" in self.options: |
| 288 condition = "" |
| 289 template = template_inline_forward |
| 290 else: |
| 291 condition = "InstrumentingAgents* agents = instrumentingAgentsFor%s(
%s)" % ( |
| 292 self.agents_selector_class, self.params[0].name) |
| 293 |
| 294 if self.returns_value: |
| 295 template = template_inline_returns_value |
| 296 else: |
| 297 template = template_inline |
| 298 |
| 299 header_lines.append(template.substitute( |
| 300 None, |
| 301 name=self.name, |
| 302 fast_return=fast_return, |
| 303 return_type=self.return_type, |
| 304 default_return_value=self.default_return_value, |
| 305 params_public=", ".join(map(Parameter.to_str_full, self.params)), |
| 306 params_impl=", ".join(map(Parameter.to_str_name, self.params_impl)), |
| 307 condition=condition)) |
| 308 |
| 309 def generate_cpp(self, cpp_lines): |
| 310 if len(self.agents) == 0: |
| 311 return |
| 312 |
| 313 body_lines = map(self.generate_agent_call, self.agents) |
| 314 |
| 315 if self.returns_cookie: |
| 316 if "Timeline" in self.agents: |
| 317 timeline_agent_id = "timelineAgentId" |
| 318 else: |
| 319 timeline_agent_id = "0" |
| 320 body_lines.append("\n return InspectorInstrumentationCookie(agent
s, %s);" % timeline_agent_id) |
| 321 elif self.returns_value: |
| 322 body_lines.append("\n return %s;" % self.default_return_value) |
| 323 |
| 324 cpp_lines.append(template_outofline.substitute( |
| 325 None, |
| 326 return_type=self.return_type, |
| 327 name=self.name, |
| 328 params_impl=", ".join(map(Parameter.to_str_class_and_name, self.para
ms_impl)), |
| 329 impl_lines="".join(body_lines))) |
| 330 |
| 331 def generate_agent_call(self, agent): |
| 332 agent_class, agent_getter = agent_getter_signature(agent) |
| 333 |
| 334 leading_param_name = self.params_impl[0].name |
| 335 if not self.accepts_cookie: |
| 336 agent_fetch = "%s->%s()" % (leading_param_name, agent_getter) |
| 337 elif agent == "Timeline": |
| 338 agent_fetch = "retrieveTimelineAgent(%s)" % leading_param_name |
| 339 else: |
| 340 agent_fetch = "%s.instrumentingAgents()->%s()" % (leading_param_name
, agent_getter) |
| 341 |
| 342 if agent == "Timeline" and self.returns_cookie: |
| 343 template = template_agent_call_timeline_returns_cookie |
| 344 else: |
| 345 template = template_agent_call |
| 346 |
| 347 if not self.returns_value or self.returns_cookie: |
| 348 maybe_return = "" |
| 349 else: |
| 350 maybe_return = "return " |
| 351 |
| 352 return template.substitute( |
| 353 None, |
| 354 name=self.name, |
| 355 agent_class=agent_class, |
| 356 agent_fetch=agent_fetch, |
| 357 maybe_return=maybe_return, |
| 358 params_agent=", ".join(map(Parameter.to_str_name, self.params_impl)[
1:])) |
| 195 | 359 |
| 196 | 360 |
| 197 class Parameter: | 361 class Parameter: |
| 198 def __init__(self, source): | 362 def __init__(self, source): |
| 363 self.options = [] |
| 364 match, source = match_and_consume("\[(\w*)\]", source) |
| 365 if match: |
| 366 self.options.append(match.group(1)) |
| 367 |
| 199 parts = map(str.strip, source.split("=")) | 368 parts = map(str.strip, source.split("=")) |
| 200 if len(parts) == 1: | 369 if len(parts) == 1: |
| 201 self.default_value = None | 370 self.default_value = None |
| 202 else: | 371 else: |
| 203 self.default_value = parts[1] | 372 self.default_value = parts[1] |
| 204 | 373 |
| 205 param_decl = parts[0] | 374 param_decl = parts[0] |
| 206 | 375 |
| 207 if re.match("(const|unsigned long) ", param_decl): | 376 if re.match("(const|unsigned long) ", param_decl): |
| 208 min_type_tokens = 2 | 377 min_type_tokens = 2 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 225 def to_str_class_and_name(self): | 394 def to_str_class_and_name(self): |
| 226 return "%s %s" % (self.type, self.name) | 395 return "%s %s" % (self.type, self.name) |
| 227 | 396 |
| 228 def to_str_class(self): | 397 def to_str_class(self): |
| 229 return self.type | 398 return self.type |
| 230 | 399 |
| 231 def to_str_name(self): | 400 def to_str_name(self): |
| 232 return self.name | 401 return self.name |
| 233 | 402 |
| 234 | 403 |
| 235 # This function is only needed to minimize the diff with the handwritten code. | |
| 236 # In fact it is sufficient to return a globally unique string. | |
| 237 def generate_param_name(param_type): | 404 def generate_param_name(param_type): |
| 238 base_name = re.match("(const |RefPtr<|PassRefPtr<)?(\w*)", param_type).group
(2) | 405 base_name = re.match("(const |PassRefPtr<)?(\w*)", param_type).group(2) |
| 239 | 406 return "param" + base_name |
| 240 custom_param_types = { | |
| 241 "CharacterData": "characterData", | |
| 242 "CSSSelector": "pseudoState", | |
| 243 "DocumentStyleSheetCollection": "styleSheetCollection", | |
| 244 "EventPath": "eventPath", | |
| 245 "FormData": "formData", | |
| 246 "InspectorCSSOMWrappers": "inspectorCSSOMWrappers", | |
| 247 "InstrumentingAgents": "instrumentingAgents", | |
| 248 "NamedFlow": "namedFlow", | |
| 249 "RenderObject": "renderer", | |
| 250 "RenderLayer": "renderLayer", | |
| 251 "ResourceLoader": "resourceLoader", | |
| 252 "PseudoElement": "pseudoElement", | |
| 253 "ScriptState": "scriptState"} | |
| 254 if base_name in custom_param_types: | |
| 255 return custom_param_types[base_name] | |
| 256 | |
| 257 match = re.match("(.*)([A-Z][a-z]+)", base_name) | |
| 258 if match: | |
| 259 return match.group(2).lower() # CamelCaseWord -> word | |
| 260 | |
| 261 if base_name.lower() == base_name: | |
| 262 return base_name + "_" | |
| 263 return base_name.lower() | |
| 264 | |
| 265 | |
| 266 # This function is only needed to minimize the diff with the handwritten code. | |
| 267 # In fact is is sufficient to hardcode a constant string (e.g. "agent") into the
template. | |
| 268 def agent_variable_name(agent): | |
| 269 if re.match("DOM", agent): | |
| 270 return re.sub("DOM", "dom", agent) | |
| 271 if agent.upper() == agent: | |
| 272 return agent.lower() | |
| 273 return agent[0].lower() + agent[1:] | |
| 274 | 407 |
| 275 | 408 |
| 276 def agent_class_name(agent): | 409 def agent_class_name(agent): |
| 277 custom_agent_names = ["Inspector", "PageDebugger", "PageRuntime", "WorkerRun
time"] | 410 custom_agent_names = ["Inspector", "PageDebugger", "PageRuntime", "WorkerRun
time"] |
| 278 if agent in custom_agent_names: | 411 if agent in custom_agent_names: |
| 279 return "%sAgent" % agent | 412 return "%sAgent" % agent |
| 280 return "Inspector%sAgent" % agent | 413 return "Inspector%sAgent" % agent |
| 281 | 414 |
| 282 | 415 |
| 283 def agent_getter_name(agent): | 416 def agent_getter_signature(agent): |
| 284 name = agent_class_name(agent) | 417 agent_class = agent_class_name(agent) |
| 285 return name[0].lower() + name[1:] | 418 return agent_class, agent_class[0].lower() + agent_class[1:] |
| 419 |
| 420 |
| 421 def include_header(name): |
| 422 return "#include \"%s.h\"" % name |
| 423 |
| 424 |
| 425 def include_inspector_header(name): |
| 426 return include_header("core/inspector/" + name) |
| 427 |
| 428 |
| 429 def generate_instrumenting_agents(used_agents): |
| 430 agents = list(used_agents) |
| 431 |
| 432 forward_list = [] |
| 433 accessor_list = [] |
| 434 member_list = [] |
| 435 init_list = [] |
| 436 reset_list = [] |
| 437 |
| 438 for agent in agents: |
| 439 class_name, getter_name = agent_getter_signature(agent) |
| 440 member_name = "m_" + getter_name |
| 441 |
| 442 forward_list.append("class %s;" % class_name) |
| 443 accessor_list.append(template_instrumenting_agent_accessor.substitute( |
| 444 None, |
| 445 class_name=class_name, |
| 446 getter_name=getter_name, |
| 447 member_name=member_name)) |
| 448 member_list.append(" %s* %s;" % (class_name, member_name)) |
| 449 init_list.append("%s(0)" % member_name) |
| 450 reset_list.append("%s = 0;" % member_name) |
| 451 |
| 452 forward_list.sort() |
| 453 accessor_list.sort() |
| 454 member_list.sort() |
| 455 init_list.sort() |
| 456 reset_list.sort() |
| 457 |
| 458 header_lines = template_instrumenting_agents_h.substitute( |
| 459 None, |
| 460 forward_list="\n".join(forward_list), |
| 461 accessor_list="\n".join(accessor_list), |
| 462 member_list="\n".join(member_list)) |
| 463 |
| 464 cpp_lines = template_instrumenting_agents_cpp.substitute( |
| 465 None, |
| 466 init_list="\n , ".join(init_list), |
| 467 reset_list="\n ".join(reset_list)) |
| 468 |
| 469 return header_lines, cpp_lines |
| 286 | 470 |
| 287 | 471 |
| 288 def generate(input_path, output_h_dir, output_cpp_dir): | 472 def generate(input_path, output_h_dir, output_cpp_dir): |
| 289 fin = open(input_path, "r") | 473 fin = open(input_path, "r") |
| 290 declarations = load_model_from_idl(fin.read()) | 474 files = load_model_from_idl(fin.read()) |
| 291 fin.close() | 475 fin.close() |
| 292 | 476 |
| 293 impl_declarations = [] | 477 cpp_includes = [] |
| 294 inline_methods = [] | 478 cpp_lines = [] |
| 295 out_of_line_methods = [] | 479 used_agents = set() |
| 480 for f in files: |
| 481 cpp_includes.append(include_header(f.header_name)) |
| 296 | 482 |
| 297 for declaration in declarations: | 483 fout = open(output_h_dir + "/" + f.header_name + ".h", "w") |
| 298 param_string_public = ", ".join(map(Parameter.to_str_full, declaration.p
arams)) | 484 fout.write(f.generate(cpp_lines, used_agents)) |
| 485 fout.close() |
| 299 | 486 |
| 300 param_list_impl_parsed = declaration.params[:] | 487 for agent in used_agents: |
| 488 cpp_includes.append(include_inspector_header(agent_class_name(agent))) |
| 489 cpp_includes.append(include_header("InstrumentingAgentsInl")) |
| 490 cpp_includes.sort() |
| 301 | 491 |
| 302 accepts_cookie = (declaration.params[0].type == "const InspectorInstrume
ntationCookie&") | 492 instrumenting_agents_header, instrumenting_agents_cpp = generate_instrumenti
ng_agents(used_agents) |
| 303 if not accepts_cookie and not "Inline=Forward" in declaration.method_opt
ions: | |
| 304 if not "Keep" in declaration.param_options: | |
| 305 param_list_impl_parsed = param_list_impl_parsed[1:] | |
| 306 param_list_impl_parsed = [Parameter("InstrumentingAgents*")] + param
_list_impl_parsed | |
| 307 | 493 |
| 308 generate_inline = not "Inline=Custom" in declaration.method_options | 494 fout = open(output_h_dir + "/" + "InstrumentingAgentsInl.h", "w") |
| 309 if generate_inline: | 495 fout.write(instrumenting_agents_header) |
| 310 impl_declarations.append("%s %sImpl(%s);" % ( | |
| 311 declaration.return_type, declaration.name, ", ".join(map(Paramet
er.to_str_class, param_list_impl_parsed)))) | |
| 312 | |
| 313 leading_impl_param_name = param_list_impl_parsed[0].name | |
| 314 param_string_impl_full = ", ".join(map(Parameter.to_str_class_and_name,
param_list_impl_parsed)) | |
| 315 | |
| 316 param_list_impl_names_only = map(Parameter.to_str_name, param_list_impl_
parsed) | |
| 317 param_string_impl_names_only = ", ".join(param_list_impl_names_only) | |
| 318 param_string_agent = ", ".join(param_list_impl_names_only[1:]) | |
| 319 | |
| 320 def is_agent_name(name): | |
| 321 return not "=" in name | |
| 322 | |
| 323 agents = filter(is_agent_name, declaration.method_options) | |
| 324 | |
| 325 if "Inline=FastReturn" in declaration.method_options or "Inline=Forward"
in declaration.method_options: | |
| 326 fast_return = "\n FAST_RETURN_IF_NO_FRONTENDS(%s());" % declarati
on.return_type | |
| 327 else: | |
| 328 fast_return = "" | |
| 329 | |
| 330 if accepts_cookie: | |
| 331 if generate_inline: | |
| 332 inline_methods.append( | |
| 333 template_inline_accepts_cookie.substitute( | |
| 334 None, | |
| 335 name=declaration.name, | |
| 336 fast_return=fast_return, | |
| 337 params_public=param_string_public, | |
| 338 params_impl=param_string_impl_names_only, | |
| 339 cookie=leading_impl_param_name)) | |
| 340 if len(agents): | |
| 341 agent_calls = [] | |
| 342 for agent in agents: | |
| 343 if agent == "Timeline": | |
| 344 agent_fetch = "retrieveTimelineAgent(%s)" % leading_impl
_param_name | |
| 345 else: | |
| 346 agent_fetch = "%s.instrumentingAgents()->%s()" % (leadin
g_impl_param_name, agent_getter_name(agent)) | |
| 347 agent_calls.append( | |
| 348 template_agent_call.substitute( | |
| 349 None, | |
| 350 name=declaration.name, | |
| 351 agent_fetch=agent_fetch, | |
| 352 params_agent=param_string_agent, | |
| 353 agent_class=agent_class_name(agent), | |
| 354 agent=agent_variable_name(agent))) | |
| 355 out_of_line_methods.append( | |
| 356 template_outofline.substitute( | |
| 357 None, | |
| 358 name=declaration.name, | |
| 359 params_impl=param_string_impl_full, | |
| 360 agent_calls="".join(agent_calls))) | |
| 361 else: | |
| 362 leading_public_param = declaration.params[0] | |
| 363 selector_class = re.match("(\w*)", leading_public_param.type).group(
1) | |
| 364 agents_getter = "instrumentingAgentsFor%s(%s)" % (selector_class, le
ading_public_param.name) | |
| 365 if declaration.return_type == "void": | |
| 366 if generate_inline: | |
| 367 if "Inline=Forward" in declaration.method_options: | |
| 368 inline_methods.append( | |
| 369 template_inline_forward.substitute( | |
| 370 None, | |
| 371 name=declaration.name, | |
| 372 fast_return=fast_return, | |
| 373 params_public=param_string_public, | |
| 374 params_impl=param_string_impl_names_only)) | |
| 375 else: | |
| 376 inline_methods.append( | |
| 377 template_inline.substitute( | |
| 378 None, | |
| 379 name=declaration.name, | |
| 380 fast_return=fast_return, | |
| 381 params_public=param_string_public, | |
| 382 params_impl=param_string_impl_names_only, | |
| 383 agents_getter=agents_getter)) | |
| 384 if len(agents): | |
| 385 agent_calls = [] | |
| 386 for agent in agents: | |
| 387 agent_fetch = "%s->%s()" % (leading_impl_param_name, age
nt_getter_name(agent)) | |
| 388 agent_call = template_agent_call.substitute( | |
| 389 None, | |
| 390 name=declaration.name, | |
| 391 agent_fetch=agent_fetch, | |
| 392 params_agent=param_string_agent, | |
| 393 agent_class=agent_class_name(agent), | |
| 394 agent=agent_variable_name(agent)) | |
| 395 agent_calls.append(agent_call) | |
| 396 out_of_line_methods.append( | |
| 397 template_outofline.substitute( | |
| 398 None, | |
| 399 name=declaration.name, | |
| 400 params_impl=param_string_impl_full, | |
| 401 agent_calls="".join(agent_calls))) | |
| 402 elif declaration.return_type == "InspectorInstrumentationCookie": | |
| 403 if generate_inline: | |
| 404 inline_methods.append( | |
| 405 template_inline_returns_cookie.substitute( | |
| 406 None, | |
| 407 name=declaration.name, | |
| 408 fast_return=fast_return, | |
| 409 params_public=param_string_public, | |
| 410 params_impl=param_string_impl_names_only, | |
| 411 agents_getter=agents_getter)) | |
| 412 | |
| 413 if len(agents): | |
| 414 timeline_agent_id = "0" | |
| 415 agent_calls = [] | |
| 416 for agent in agents: | |
| 417 if agent == "Timeline": | |
| 418 agent_call = template_timeline_agent_call.substitute
( | |
| 419 None, | |
| 420 name=declaration.name, | |
| 421 params_agent=param_string_agent) | |
| 422 timeline_agent_id = "timelineAgentId" | |
| 423 else: | |
| 424 agent_fetch = "%s->%s()" % (leading_impl_param_name,
agent_getter_name(agent)) | |
| 425 agent_call = template_agent_call.substitute( | |
| 426 None, | |
| 427 name=declaration.name, | |
| 428 agent_fetch=agent_fetch, | |
| 429 params_agent=param_string_agent, | |
| 430 agent_class=agent_class_name(agent), | |
| 431 agent=agent_variable_name(agent)) | |
| 432 agent_calls.append(agent_call) | |
| 433 | |
| 434 out_of_line_methods.append( | |
| 435 template_outofline_returns_cookie.substitute( | |
| 436 None, | |
| 437 return_type=declaration.return_type, | |
| 438 name=declaration.name, | |
| 439 params_impl=param_string_impl_full, | |
| 440 agent_calls="".join(agent_calls), | |
| 441 timeline_agent_id=timeline_agent_id)) | |
| 442 else: | |
| 443 sys.stderr.write("Unsupported return type %s" % declaration.retu
rn_type) | |
| 444 sys.exit(1) | |
| 445 | |
| 446 fout = open(output_h_dir + "/InspectorInstrumentationInl.h", "w") | |
| 447 fout.write(template_h.substitute(None, | |
| 448 impl_declarations="\n".join(impl_declaratio
ns), | |
| 449 inline_methods="".join(inline_methods))) | |
| 450 fout.close() | 496 fout.close() |
| 451 | 497 |
| 452 fout = open(output_cpp_dir + "/InspectorInstrumentationImpl.cpp", "w") | 498 fout = open(output_cpp_dir + "/InspectorInstrumentationImpl.cpp", "w") |
| 453 fout.write(template_cpp.substitute(None, | 499 fout.write(template_cpp.substitute(None, |
| 454 out_of_line_methods="\n".join(out_of_line
_methods))) | 500 includes="\n".join(cpp_includes), |
| 501 extra_definitions=instrumenting_agents_cp
p, |
| 502 methods="\n".join(cpp_lines))) |
| 455 fout.close() | 503 fout.close() |
| 456 | 504 |
| 457 | 505 |
| 458 cmdline_parser = optparse.OptionParser() | 506 cmdline_parser = optparse.OptionParser() |
| 459 cmdline_parser.add_option("--output_h_dir") | 507 cmdline_parser.add_option("--output_h_dir") |
| 460 cmdline_parser.add_option("--output_cpp_dir") | 508 cmdline_parser.add_option("--output_cpp_dir") |
| 461 | 509 |
| 462 try: | 510 try: |
| 463 arg_options, arg_values = cmdline_parser.parse_args() | 511 arg_options, arg_values = cmdline_parser.parse_args() |
| 464 if (len(arg_values) != 1): | 512 if (len(arg_values) != 1): |
| 465 raise Exception("Exactly one plain argument expected (found %s)" % len(a
rg_values)) | 513 raise Exception("Exactly one plain argument expected (found %s)" % len(a
rg_values)) |
| 466 input_path = arg_values[0] | 514 input_path = arg_values[0] |
| 467 output_header_dirpath = arg_options.output_h_dir | 515 output_header_dirpath = arg_options.output_h_dir |
| 468 output_cpp_dirpath = arg_options.output_cpp_dir | 516 output_cpp_dirpath = arg_options.output_cpp_dir |
| 469 if not output_header_dirpath: | 517 if not output_header_dirpath: |
| 470 raise Exception("Output .h directory must be specified") | 518 raise Exception("Output .h directory must be specified") |
| 471 if not output_cpp_dirpath: | 519 if not output_cpp_dirpath: |
| 472 raise Exception("Output .cpp directory must be specified") | 520 raise Exception("Output .cpp directory must be specified") |
| 473 except Exception: | 521 except Exception: |
| 474 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html | 522 # Work with python 2 and 3 http://docs.python.org/py3k/howto/pyporting.html |
| 475 exc = sys.exc_info()[1] | 523 exc = sys.exc_info()[1] |
| 476 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) | 524 sys.stderr.write("Failed to parse command-line arguments: %s\n\n" % exc) |
| 477 sys.stderr.write("Usage: <script> InspectorInstrumentation.idl --output_h_di
r <output_header_dir> --output_cpp_dir <output_cpp_dir>\n") | 525 sys.stderr.write("Usage: <script> InspectorInstrumentation.idl --output_h_di
r <output_header_dir> --output_cpp_dir <output_cpp_dir>\n") |
| 478 exit(1) | 526 exit(1) |
| 479 | 527 |
| 480 generate(input_path, output_header_dirpath, output_cpp_dirpath) | 528 generate(input_path, output_header_dirpath, output_cpp_dirpath) |
| OLD | NEW |