Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(640)

Side by Side Diff: lib/dom/scripts/dartgenerator.py

Issue 10392147: Move systems creation to dartdomgenerator.py. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix performance issue. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
3 # for details. All rights reserved. Use of this source code is governed by a 3 # for details. All rights reserved. Use of this source code is governed by a
4 # BSD-style license that can be found in the LICENSE file. 4 # BSD-style license that can be found in the LICENSE file.
5 5
6 """This module generates Dart APIs from the IDL database.""" 6 """This module generates Dart APIs from the IDL database."""
7 7
8 import emitter 8 import emitter
9 import idlnode 9 import idlnode
10 import logging 10 import logging
11 import multiemitter
12 import os 11 import os
13 import re 12 import re
14 import shutil 13 import shutil
15 from generator import * 14 from generator import *
16 from systembase import * 15 from systembase import *
17 from systemfrog import *
18 from systemhtml import *
19 from systeminterface import *
20 from systemnative import *
21 from templateloader import TemplateLoader
22 16
23 _logger = logging.getLogger('dartgenerator') 17 _logger = logging.getLogger('dartgenerator')
24 18
25 def MergeNodes(node, other): 19 def MergeNodes(node, other):
26 node.operations.extend(other.operations) 20 node.operations.extend(other.operations)
27 for attribute in other.attributes: 21 for attribute in other.attributes:
28 if not node.has_attribute(attribute): 22 if not node.has_attribute(attribute):
29 node.attributes.append(attribute) 23 node.attributes.append(attribute)
30 24
31 node.constants.extend(other.constants) 25 node.constants.extend(other.constants)
32 26
33 class DartGenerator(object): 27 class DartGenerator(object):
34 """Utilities to generate Dart APIs and corresponding JavaScript.""" 28 """Utilities to generate Dart APIs and corresponding JavaScript."""
35 29
36 def __init__(self, auxiliary_dir, template_dir, base_package): 30 def __init__(self):
37 """Constructor for the DartGenerator.
38
39 Args:
40 auxiliary_dir -- location of auxiliary handwritten classes
41 template_dir -- location of template files
42 base_package -- the base package name for the generated code.
43 """
44 self._auxiliary_dir = auxiliary_dir
45 self._template_dir = template_dir
46 self._base_package = base_package
47 self._auxiliary_files = {} 31 self._auxiliary_files = {}
48 self._dart_templates_re = re.compile(r'[\w.:]+<([\w\.<>:]+)>') 32 self._dart_templates_re = re.compile(r'[\w.:]+<([\w\.<>:]+)>')
49 33
50 self._emitters = None # set later
51
52
53 def _StripModules(self, type_name): 34 def _StripModules(self, type_name):
54 return type_name.split('::')[-1] 35 return type_name.split('::')[-1]
55 36
56 def _IsCompoundType(self, database, type_name): 37 def _IsCompoundType(self, database, type_name):
57 if IsPrimitiveType(type_name): 38 if IsPrimitiveType(type_name):
58 return True 39 return True
59 40
60 striped_type_name = self._StripModules(type_name) 41 striped_type_name = self._StripModules(type_name)
61 if database.HasInterface(striped_type_name): 42 if database.HasInterface(striped_type_name):
62 return True 43 return True
63 44
64 dart_template_match = self._dart_templates_re.match(type_name) 45 dart_template_match = self._dart_templates_re.match(type_name)
65 if dart_template_match: 46 if dart_template_match:
66 # Dart templates 47 # Dart templates
67 parent_type_name = type_name[0 : dart_template_match.start(1) - 1] 48 parent_type_name = type_name[0 : dart_template_match.start(1) - 1]
68 sub_type_name = dart_template_match.group(1) 49 sub_type_name = dart_template_match.group(1)
69 return (self._IsCompoundType(database, parent_type_name) and 50 return (self._IsCompoundType(database, parent_type_name) and
70 self._IsCompoundType(database, sub_type_name)) 51 self._IsCompoundType(database, sub_type_name))
71 return False 52 return False
72 53
73 def _IsDartType(self, type_name): 54 def _IsDartType(self, type_name):
74 return '.' in type_name 55 return '.' in type_name
75 56
76 def LoadAuxiliary(self): 57 def LoadAuxiliary(self, auxiliary_dir):
77 def Visitor(_, dirname, names): 58 def Visitor(_, dirname, names):
78 for name in names: 59 for name in names:
79 if name.endswith('.dart'): 60 if name.endswith('.dart'):
80 name = name[0:-5] # strip off ".dart" 61 name = name[0:-5] # strip off ".dart"
81 self._auxiliary_files[name] = os.path.join(dirname, name) 62 self._auxiliary_files[name] = os.path.join(dirname, name)
82 os.path.walk(self._auxiliary_dir, Visitor, None) 63 os.path.walk(auxiliary_dir, Visitor, None)
83 64
84 def RenameTypes(self, database, conversion_table, rename_javascript_binding_na mes): 65 def RenameTypes(self, database, conversion_table, rename_javascript_binding_na mes):
85 """Renames interfaces using the given conversion table. 66 """Renames interfaces using the given conversion table.
86 67
87 References through all interfaces will be renamed as well. 68 References through all interfaces will be renamed as well.
88 69
89 Args: 70 Args:
90 database: the database to apply the renames to. 71 database: the database to apply the renames to.
91 conversion_table: maps old names to new names. 72 conversion_table: maps old names to new names.
92 """ 73 """
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 if HasAnnotations(interface): 179 if HasAnnotations(interface):
199 interface.constants = filter(HasAnnotations, interface.constants) 180 interface.constants = filter(HasAnnotations, interface.constants)
200 interface.attributes = filter(HasAnnotations, interface.attributes) 181 interface.attributes = filter(HasAnnotations, interface.attributes)
201 interface.operations = filter(HasAnnotations, interface.operations) 182 interface.operations = filter(HasAnnotations, interface.operations)
202 interface.parents = filter(HasAnnotations, interface.parents) 183 interface.parents = filter(HasAnnotations, interface.parents)
203 else: 184 else:
204 database.DeleteInterface(interface.id) 185 database.DeleteInterface(interface.id)
205 186
206 self.FilterMembersWithUnidentifiedTypes(database) 187 self.FilterMembersWithUnidentifiedTypes(database)
207 188
208 189 def Generate(self, database, system, source_filter=None, super_database=None,
209 def Generate(self, database, output_dir, 190 common_prefix=None, webkit_renames={}, html_renames={}):
210 module_source_preference=[], source_filter=None,
211 super_database=None, common_prefix=None,
212 webkit_renames={},
213 html_renames={},
214 lib_dir=None,
215 systems=[]):
216 """Generates Dart and JS files for the loaded interfaces.
217
218 Args:
219 database -- database containing interfaces to generate code for.
220 output_dir -- directory to write generated files to.
221 module_source_preference -- priority order list of source annotations to
222 use when choosing a module name, if none specified uses the module name
223 from the database.
224 source_filter -- if specified, only outputs interfaces that have one of
225 these source annotation and rewrites the names of superclasses not
226 marked with this source to use the common prefix.
227 super_database -- database containing super interfaces that the generated
228 interfaces should extend.
229 common_prefix -- prefix for the common library, if any.
230 lib_file_path -- filename for generated .lib file, None if not required.
231 lib_template -- template file in this directory for generated lib file.
232 """
233
234 self._emitters = multiemitter.MultiEmitter()
235 self._database = database 191 self._database = database
236 self._output_dir = output_dir
237
238 self._FixEventTargets()
239 self._ComputeInheritanceClosure()
240
241 self._systems = []
242
243 # TODO(jmesserly): only create these if needed
244 if ('htmlfrog' in systems) or ('htmldartium' in systems):
245 html_interface_system = HtmlInterfacesSystem(
246 TemplateLoader(self._template_dir, ['html/interface', 'html', '']),
247 self._database, self._emitters, self._output_dir, self)
248 self._systems.append(html_interface_system)
249 else:
250 interface_system = InterfacesSystem(
251 TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']),
252 self._database, self._emitters, self._output_dir)
253 self._systems.append(interface_system)
254
255 if 'native' in systems:
256 native_system = NativeImplementationSystem(
257 TemplateLoader(self._template_dir, ['dom/native', 'dom', '']),
258 self._database, html_renames, self._emitters, self._auxiliary_dir,
259 self._output_dir)
260
261 self._systems.append(native_system)
262
263 if 'dummy' in systems:
264 dummy_system = DummyImplementationSystem(
265 TemplateLoader(self._template_dir, ['dom/dummy', 'dom', '']),
266 self._database, self._emitters, self._output_dir)
267
268 # Makes interface files available for listing in the library for the
269 # dummy implementation.
270 dummy_system._interface_system = interface_system
271 self._systems.append(dummy_system)
272
273 if 'frog' in systems:
274 frog_system = FrogSystem(
275 TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']),
276 self._database, self._emitters, self._output_dir)
277
278 frog_system._interface_system = interface_system
279 self._systems.append(frog_system)
280
281 if 'htmlfrog' in systems:
282 html_system = HtmlFrogSystem(
283 TemplateLoader(self._template_dir,
284 ['html/frog', 'html/impl', 'html', ''],
285 {'DARTIUM': False, 'FROG': True}),
286 self._database, self._emitters, self._output_dir, self)
287
288 html_system._interface_system = html_interface_system
289 self._systems.append(html_system)
290
291 if 'htmldartium' in systems:
292 html_system = HtmlDartiumSystem(
293 TemplateLoader(self._template_dir,
294 ['html/dartium', 'html/impl', 'html', ''],
295 {'DARTIUM': True, 'FROG': False}),
296 self._database, self._emitters, self._auxiliary_dir,
297 self._output_dir, self)
298
299 html_system._interface_system = html_interface_system
300 self._systems.append(html_system)
301 192
302 # Collect interfaces 193 # Collect interfaces
303 interfaces = [] 194 interfaces = []
304 for interface in database.GetInterfaces(): 195 for interface in database.GetInterfaces():
305 if not MatchSourceFilter(source_filter, interface): 196 if not MatchSourceFilter(source_filter, interface):
306 # Skip this interface since it's not present in the required source 197 # Skip this interface since it's not present in the required source
307 _logger.info('Omitting interface - %s' % interface.id) 198 _logger.info('Omitting interface - %s' % interface.id)
308 continue 199 continue
309 interfaces.append(interface) 200 interfaces.append(interface)
310 201
(...skipping 18 matching lines...) Expand all
329 220
330 interface_name = interface.id 221 interface_name = interface.id
331 auxiliary_file = self._auxiliary_files.get(interface_name) 222 auxiliary_file = self._auxiliary_files.get(interface_name)
332 if auxiliary_file is not None: 223 if auxiliary_file is not None:
333 _logger.info('Skipping %s because %s exists' % ( 224 _logger.info('Skipping %s because %s exists' % (
334 interface_name, auxiliary_file)) 225 interface_name, auxiliary_file))
335 continue 226 continue
336 227
337 info = RecognizeCallback(interface) 228 info = RecognizeCallback(interface)
338 if info: 229 if info:
339 for system in self._systems: 230 system.ProcessCallback(interface, info)
340 system.ProcessCallback(interface, info)
341 else: 231 else:
342 if 'Callback' in interface.ext_attrs: 232 if 'Callback' in interface.ext_attrs:
343 _logger.info('Malformed callback: %s' % interface.id) 233 _logger.info('Malformed callback: %s' % interface.id)
344 self._ProcessInterface(interface, super_interface, 234 self._ProcessInterface(system, interface, super_interface,
345 source_filter, common_prefix) 235 source_filter, common_prefix)
346 236
347 # Libraries 237 system.GenerateLibraries()
348 if lib_dir: 238 system.Finish()
349 for system in self._systems:
350 system.GenerateLibraries(lib_dir)
351
352 for system in self._systems:
353 system.Finish()
354 239
355 def _PreOrderInterfaces(self, interfaces): 240 def _PreOrderInterfaces(self, interfaces):
356 """Returns the interfaces in pre-order, i.e. parents first.""" 241 """Returns the interfaces in pre-order, i.e. parents first."""
357 seen = set() 242 seen = set()
358 ordered = [] 243 ordered = []
359 def visit(interface): 244 def visit(interface):
360 if interface.id in seen: 245 if interface.id in seen:
361 return 246 return
362 seen.add(interface.id) 247 seen.add(interface.id)
363 for parent in interface.parents: 248 for parent in interface.parents:
364 if IsDartCollectionType(parent.type.id): 249 if IsDartCollectionType(parent.type.id):
365 continue 250 continue
366 if self._database.HasInterface(parent.type.id): 251 if self._database.HasInterface(parent.type.id):
367 parent_interface = self._database.GetInterface(parent.type.id) 252 parent_interface = self._database.GetInterface(parent.type.id)
368 visit(parent_interface) 253 visit(parent_interface)
369 ordered.append(interface) 254 ordered.append(interface)
370 255
371 for interface in interfaces: 256 for interface in interfaces:
372 visit(interface) 257 visit(interface)
373 return ordered 258 return ordered
374 259
375 260
376 def _ProcessInterface(self, interface, super_interface_name, 261 def _ProcessInterface(self, system, interface, super_interface_name,
377 source_filter, 262 source_filter,
378 common_prefix): 263 common_prefix):
379 """.""" 264 """."""
380 _logger.info('Generating %s' % interface.id) 265 _logger.info('Generating %s' % interface.id)
381 266
382 generators = [system.InterfaceGenerator(interface, 267 generator = system.InterfaceGenerator(interface,
383 common_prefix, 268 common_prefix,
384 super_interface_name, 269 super_interface_name,
385 source_filter) 270 source_filter)
386 for system in self._systems] 271 if not generator:
387 generators = filter(None, generators) 272 return
388 273
389 for generator in generators: 274 generator.StartInterface()
390 generator.StartInterface()
391 275
392 for const in sorted(interface.constants, ConstantOutputOrder): 276 for const in sorted(interface.constants, ConstantOutputOrder):
393 for generator in generators: 277 generator.AddConstant(const)
394 generator.AddConstant(const)
395 278
396 attributes = [attr for attr in interface.attributes 279 attributes = [attr for attr in interface.attributes
397 if attr.type.id != 'EventListener'] 280 if attr.type.id != 'EventListener']
398 for (getter, setter) in _PairUpAttributes(attributes): 281 for (getter, setter) in _PairUpAttributes(attributes):
399 for generator in generators: 282 generator.AddAttribute(getter, setter)
400 generator.AddAttribute(getter, setter)
401 283
402 # The implementation should define an indexer if the interface directly 284 # The implementation should define an indexer if the interface directly
403 # extends List. 285 # extends List.
404 (element_type, requires_indexer) = ListImplementationInfo( 286 (element_type, requires_indexer) = ListImplementationInfo(
405 interface, self._database) 287 interface, self._database)
406 if element_type: 288 if element_type:
407 for generator in generators: 289 if requires_indexer:
408 if requires_indexer: 290 generator.AddIndexer(element_type)
409 generator.AddIndexer(element_type) 291 else:
410 else: 292 generator.AmendIndexer(element_type)
411 generator.AmendIndexer(element_type)
412 # Group overloaded operations by id 293 # Group overloaded operations by id
413 operationsById = {} 294 operationsById = {}
414 for operation in interface.operations: 295 for operation in interface.operations:
415 if operation.id not in operationsById: 296 if operation.id not in operationsById:
416 operationsById[operation.id] = [] 297 operationsById[operation.id] = []
417 operationsById[operation.id].append(operation) 298 operationsById[operation.id].append(operation)
418 299
419 # Generate operations 300 # Generate operations
420 for id in sorted(operationsById.keys()): 301 for id in sorted(operationsById.keys()):
421 operations = operationsById[id] 302 operations = operationsById[id]
422 info = AnalyzeOperation(interface, operations) 303 info = AnalyzeOperation(interface, operations)
423 for generator in generators: 304 if info.IsStatic():
424 if info.IsStatic(): 305 generator.AddStaticOperation(info)
425 generator.AddStaticOperation(info) 306 else:
426 else: 307 generator.AddOperation(info)
427 generator.AddOperation(info)
428 308
429 # With multiple inheritance, attributes and operations of non-first 309 # With multiple inheritance, attributes and operations of non-first
430 # interfaces need to be added. Sometimes the attribute or operation is 310 # interfaces need to be added. Sometimes the attribute or operation is
431 # defined in the current interface as well as a parent. In that case we 311 # defined in the current interface as well as a parent. In that case we
432 # avoid making a duplicate definition and pray that the signatures match. 312 # avoid making a duplicate definition and pray that the signatures match.
433 313
434 for parent_interface in self._TransitiveSecondaryParents(interface): 314 for parent_interface in self._TransitiveSecondaryParents(interface):
435 if isinstance(parent_interface, str): # IsDartCollectionType(parent_inter face) 315 if isinstance(parent_interface, str): # IsDartCollectionType(parent_inter face)
436 continue 316 continue
437 attributes = [attr for attr in parent_interface.attributes 317 attributes = [attr for attr in parent_interface.attributes
438 if not FindMatchingAttribute(interface, attr)] 318 if not FindMatchingAttribute(interface, attr)]
439 for (getter, setter) in _PairUpAttributes(attributes): 319 for (getter, setter) in _PairUpAttributes(attributes):
440 for generator in generators: 320 generator.AddSecondaryAttribute(parent_interface, getter, setter)
441 generator.AddSecondaryAttribute(parent_interface, getter, setter)
442 321
443 # Group overloaded operations by id 322 # Group overloaded operations by id
444 operationsById = {} 323 operationsById = {}
445 for operation in parent_interface.operations: 324 for operation in parent_interface.operations:
446 if operation.id not in operationsById: 325 if operation.id not in operationsById:
447 operationsById[operation.id] = [] 326 operationsById[operation.id] = []
448 operationsById[operation.id].append(operation) 327 operationsById[operation.id].append(operation)
449 328
450 # Generate operations 329 # Generate operations
451 for id in sorted(operationsById.keys()): 330 for id in sorted(operationsById.keys()):
452 if not any(op.id == id for op in interface.operations): 331 if not any(op.id == id for op in interface.operations):
453 operations = operationsById[id] 332 operations = operationsById[id]
454 info = AnalyzeOperation(interface, operations) 333 info = AnalyzeOperation(interface, operations)
455 for generator in generators: 334 generator.AddSecondaryOperation(parent_interface, info)
456 generator.AddSecondaryOperation(parent_interface, info)
457 335
458 for generator in generators: 336 generator.FinishInterface()
459 generator.FinishInterface()
460 return
461 337
462 def _TransitiveSecondaryParents(self, interface): 338 def _TransitiveSecondaryParents(self, interface):
463 """Returns a list of all non-primary parents. 339 """Returns a list of all non-primary parents.
464 340
465 The list contains the interface objects for interfaces defined in the 341 The list contains the interface objects for interfaces defined in the
466 database, and the name for undefined interfaces. 342 database, and the name for undefined interfaces.
467 """ 343 """
468 def walk(parents): 344 def walk(parents):
469 for parent in parents: 345 for parent in parents:
470 if IsDartCollectionType(parent.type.id): 346 if IsDartCollectionType(parent.type.id):
(...skipping 17 matching lines...) Expand all
488 if attribute.get_raises: 364 if attribute.get_raises:
489 exceptions.add(attribute.get_raises.id) 365 exceptions.add(attribute.get_raises.id)
490 if attribute.set_raises: 366 if attribute.set_raises:
491 exceptions.add(attribute.set_raises.id) 367 exceptions.add(attribute.set_raises.id)
492 for operation in interface.operations: 368 for operation in interface.operations:
493 if operation.raises: 369 if operation.raises:
494 exceptions.add(operation.raises.id) 370 exceptions.add(operation.raises.id)
495 return exceptions 371 return exceptions
496 372
497 373
498 def Flush(self): 374 def FixEventTargets(self, database):
499 """Write out all pending files.""" 375 for interface in database.GetInterfaces():
500 _logger.info('Flush...')
501 self._emitters.Flush()
502
503 def _FixEventTargets(self):
504 for interface in self._database.GetInterfaces():
505 # Create fake EventTarget parent interface for interfaces that have 376 # Create fake EventTarget parent interface for interfaces that have
506 # 'EventTarget' extended attribute. 377 # 'EventTarget' extended attribute.
507 if 'EventTarget' in interface.ext_attrs: 378 if 'EventTarget' in interface.ext_attrs:
508 ast = [('Annotation', [('Id', 'WebKit')]), 379 ast = [('Annotation', [('Id', 'WebKit')]),
509 ('InterfaceType', ('ScopedName', 'EventTarget'))] 380 ('InterfaceType', ('ScopedName', 'EventTarget'))]
510 interface.parents.append(idlnode.IDLParentInterface(ast)) 381 interface.parents.append(idlnode.IDLParentInterface(ast))
511 382
512 def _ComputeInheritanceClosure(self):
513 def Collect(interface, seen, collected):
514 name = interface.id
515 if '<' in name:
516 # TODO(sra): Handle parameterized types.
517 return
518 if not name in seen:
519 seen.add(name)
520 collected.append(name)
521 for parent in interface.parents:
522 # TODO(sra): Handle parameterized types.
523 if not '<' in parent.type.id:
524 if self._database.HasInterface(parent.type.id):
525 Collect(self._database.GetInterface(parent.type.id),
526 seen, collected)
527
528 self._inheritance_closure = {}
529 for interface in self._database.GetInterfaces():
530 seen = set()
531 collected = []
532 Collect(interface, seen, collected)
533 self._inheritance_closure[interface.id] = collected
534
535 def _AllImplementedInterfaces(self, interface):
536 """Returns a list of the names of all interfaces implemented by 'interface'.
537 List includes the name of 'interface'.
538 """
539 return self._inheritance_closure[interface.id]
540
541 def _PairUpAttributes(attributes): 383 def _PairUpAttributes(attributes):
542 """Returns a list of (getter, setter) pairs sorted by name. 384 """Returns a list of (getter, setter) pairs sorted by name.
543 385
544 One element of the pair may be None. 386 One element of the pair may be None.
545 """ 387 """
546 names = sorted(set(attr.id for attr in attributes)) 388 names = sorted(set(attr.id for attr in attributes))
547 getters = {} 389 getters = {}
548 setters = {} 390 setters = {}
549 for attr in attributes: 391 for attr in attributes:
550 if attr.is_fc_getter: 392 if attr.is_fc_getter:
(...skipping 22 matching lines...) Expand all
573 def InterfaceGenerator(self, 415 def InterfaceGenerator(self,
574 interface, 416 interface,
575 common_prefix, 417 common_prefix,
576 super_interface_name, 418 super_interface_name,
577 source_filter): 419 source_filter):
578 return DummyInterfaceGenerator(self, interface) 420 return DummyInterfaceGenerator(self, interface)
579 421
580 def ProcessCallback(self, interface, info): 422 def ProcessCallback(self, interface, info):
581 pass 423 pass
582 424
583 def GenerateLibraries(self, lib_dir): 425 def GenerateLibraries(self):
584 # Library generated for implementation. 426 # Library generated for implementation.
585 self._GenerateLibFile( 427 self._GenerateLibFile(
586 'dom_dummy.darttemplate', 428 'dom_dummy.darttemplate',
587 os.path.join(lib_dir, 'dom_dummy.dart'), 429 os.path.join(self._output_dir, 'dom_dummy.dart'),
588 (self._interface_system._dart_interface_file_paths + 430 (self._interface_system._dart_interface_file_paths +
589 self._interface_system._dart_callback_file_paths + 431 self._interface_system._dart_callback_file_paths +
590 self._impl_file_paths)) 432 self._impl_file_paths))
591 433
592 434
593 # ------------------------------------------------------------------------------ 435 # ------------------------------------------------------------------------------
594 436
595 class DummyInterfaceGenerator(object): 437 class DummyInterfaceGenerator(object):
596 """Generates dummy implementation.""" 438 """Generates dummy implementation."""
597 439
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 pass 482 pass
641 483
642 def AddOperation(self, info): 484 def AddOperation(self, info):
643 pass 485 pass
644 486
645 def AddStaticOperation(self, info): 487 def AddStaticOperation(self, info):
646 pass 488 pass
647 489
648 def AddEventAttributes(self, event_attrs): 490 def AddEventAttributes(self, event_attrs):
649 pass 491 pass
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698