| OLD | NEW |
| 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 provides shared functionality for the system to generate | 6 """This module provides shared functionality for the system to generate |
| 7 Dart:html APIs from the IDL database.""" | 7 Dart:html APIs from the IDL database.""" |
| 8 | 8 |
| 9 import emitter | 9 import emitter |
| 10 import os | 10 import os |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 'Url.revokeObjectURL', | 40 'Url.revokeObjectURL', |
| 41 'WheelEvent.wheelDeltaX', | 41 'WheelEvent.wheelDeltaX', |
| 42 'WheelEvent.wheelDeltaY', | 42 'WheelEvent.wheelDeltaY', |
| 43 ]) | 43 ]) |
| 44 | 44 |
| 45 | 45 |
| 46 # Classes that offer only static methods, and therefore we should suppress | 46 # Classes that offer only static methods, and therefore we should suppress |
| 47 # constructor creation. | 47 # constructor creation. |
| 48 _static_classes = set(['Url']) | 48 _static_classes = set(['Url']) |
| 49 | 49 |
| 50 # Types that are accessible cross-frame in a limited fashion. | |
| 51 # In these cases, the base type (e.g., Window) provides restricted access | |
| 52 # while the subtype (e.g., LocalWindow) provides full access to the | |
| 53 # corresponding objects if there are from the same frame. | |
| 54 _secure_base_types = { | |
| 55 'LocalWindow': 'Window', | |
| 56 'LocalLocation': 'Location', | |
| 57 'LocalHistory': 'History', | |
| 58 } | |
| 59 | |
| 60 def SecureOutputType(generator, type_name, is_dart_type=False): | |
| 61 if is_dart_type: | |
| 62 dart_name = type_name | |
| 63 else: | |
| 64 dart_name = generator._DartType(type_name) | |
| 65 # We only need to secure Window. Only local History and Location are returned | |
| 66 # in generated code. | |
| 67 if dart_name == 'LocalWindow': | |
| 68 return _secure_base_types[dart_name] | |
| 69 return dart_name | |
| 70 | |
| 71 # Information for generating element constructors. | 50 # Information for generating element constructors. |
| 72 # | 51 # |
| 73 # TODO(sra): maybe remove all the argument complexity and use cascades. | 52 # TODO(sra): maybe remove all the argument complexity and use cascades. |
| 74 # | 53 # |
| 75 # var c = new CanvasElement(width: 100, height: 70); | 54 # var c = new CanvasElement(width: 100, height: 70); |
| 76 # var c = new CanvasElement()..width = 100..height = 70; | 55 # var c = new CanvasElement()..width = 100..height = 70; |
| 77 # | 56 # |
| 78 class ElementConstructorInfo(object): | 57 class ElementConstructorInfo(object): |
| 79 def __init__(self, name=None, tag=None, | 58 def __init__(self, name=None, tag=None, |
| 80 params=[], opt_params=[], | 59 params=[], opt_params=[], |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 | 185 |
| 207 class HtmlDartInterfaceGenerator(object): | 186 class HtmlDartInterfaceGenerator(object): |
| 208 """Generates dart interface and implementation for the DOM IDL interface.""" | 187 """Generates dart interface and implementation for the DOM IDL interface.""" |
| 209 | 188 |
| 210 def __init__(self, options, library_emitter, event_generator, interface, | 189 def __init__(self, options, library_emitter, event_generator, interface, |
| 211 backend): | 190 backend): |
| 212 self._renamer = options.renamer | 191 self._renamer = options.renamer |
| 213 self._database = options.database | 192 self._database = options.database |
| 214 self._template_loader = options.templates | 193 self._template_loader = options.templates |
| 215 self._type_registry = options.type_registry | 194 self._type_registry = options.type_registry |
| 195 self._options = options |
| 216 self._library_emitter = library_emitter | 196 self._library_emitter = library_emitter |
| 217 self._event_generator = event_generator | 197 self._event_generator = event_generator |
| 218 self._interface = interface | 198 self._interface = interface |
| 219 self._backend = backend | 199 self._backend = backend |
| 220 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id) | 200 self._interface_type_info = self._type_registry.TypeInfo(self._interface.id) |
| 221 | 201 |
| 222 def Generate(self): | 202 def Generate(self): |
| 223 if 'Callback' in self._interface.ext_attrs: | 203 if 'Callback' in self._interface.ext_attrs: |
| 224 self.GenerateCallback() | 204 self.GenerateCallback() |
| 225 else: | 205 else: |
| 226 self.GenerateInterface() | 206 self.GenerateInterface() |
| 227 | 207 |
| 228 def GenerateCallback(self): | 208 def GenerateCallback(self): |
| 229 """Generates a typedef for the callback interface.""" | 209 """Generates a typedef for the callback interface.""" |
| 230 handlers = [operation for operation in self._interface.operations | 210 handlers = [operation for operation in self._interface.operations |
| 231 if operation.id == 'handleEvent'] | 211 if operation.id == 'handleEvent'] |
| 232 info = AnalyzeOperation(self._interface, handlers) | 212 info = AnalyzeOperation(self._interface, handlers) |
| 233 code = self._library_emitter.FileEmitter(self._interface.id) | 213 code = self._library_emitter.FileEmitter(self._interface.id) |
| 234 code.Emit(self._template_loader.Load('callback.darttemplate')) | 214 code.Emit(self._template_loader.Load('callback.darttemplate')) |
| 235 code.Emit('typedef void $NAME($PARAMS);\n', | 215 code.Emit('typedef void $NAME($PARAMS);\n', |
| 236 NAME=self._interface.id, | 216 NAME=self._interface.id, |
| 237 PARAMS=info.ParametersDeclaration(self._DartType)) | 217 PARAMS=info.ParametersDeclaration(self._DartType)) |
| 238 self._backend.GenerateCallback(info) | 218 self._backend.GenerateCallback(info) |
| 239 | 219 |
| 240 def GenerateInterface(self): | 220 def GenerateInterface(self): |
| 241 interface_name = self._interface_type_info.interface_name() | 221 interface_name = self._interface_type_info.interface_name() |
| 242 | 222 |
| 243 # TODO: this is just tossing the interface, need to skip it completely. | |
| 244 interface_emitter = emitter.Emitter() | |
| 245 | |
| 246 template_file = 'interface_%s.darttemplate' % interface_name | |
| 247 interface_template = (self._template_loader.TryLoad(template_file) or | |
| 248 self._template_loader.Load('interface.darttemplate')) | |
| 249 | |
| 250 implements = [] | |
| 251 for parent in self._interface.parents: | |
| 252 parent_type_info = self._type_registry.TypeInfo(parent.type.id) | |
| 253 implements.append(parent_type_info.interface_name()) | |
| 254 | |
| 255 if self._interface_type_info.list_item_type(): | |
| 256 item_type_info = self._type_registry.TypeInfo( | |
| 257 self._interface_type_info.list_item_type()) | |
| 258 implements.append('List<%s>' % item_type_info.dart_type()) | |
| 259 | |
| 260 if interface_name in _secure_base_types: | |
| 261 implements.append(_secure_base_types[interface_name]) | |
| 262 | |
| 263 comment = ' extends' | |
| 264 implements_str = '' | |
| 265 if implements: | |
| 266 implements_str += ' implements ' + ', '.join(implements) | |
| 267 comment = ',' | |
| 268 | |
| 269 factory_provider = None | 223 factory_provider = None |
| 270 if interface_name in interface_factories: | 224 if interface_name in interface_factories: |
| 271 factory_provider = interface_factories[interface_name] | 225 factory_provider = interface_factories[interface_name] |
| 272 | 226 |
| 273 constructors = [] | 227 constructors = [] |
| 274 if interface_name in _static_classes: | 228 if interface_name in _static_classes: |
| 275 constructor_info = None | 229 constructor_info = None |
| 276 else: | 230 else: |
| 277 constructor_info = AnalyzeConstructor(self._interface) | 231 constructor_info = AnalyzeConstructor(self._interface) |
| 278 if constructor_info: | 232 if constructor_info: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 294 self._interface_type_info.implementation_name(), | 248 self._interface_type_info.implementation_name(), |
| 295 self._DartType) | 249 self._DartType) |
| 296 | 250 |
| 297 for info in infos: | 251 for info in infos: |
| 298 constructors.append(info.ConstructorInfo(self._interface.id)) | 252 constructors.append(info.ConstructorInfo(self._interface.id)) |
| 299 if factory_provider: | 253 if factory_provider: |
| 300 assert factory_provider == info.factory_provider_name | 254 assert factory_provider == info.factory_provider_name |
| 301 else: | 255 else: |
| 302 factory_provider = info.factory_provider_name | 256 factory_provider = info.factory_provider_name |
| 303 | 257 |
| 304 # TODO(vsm): Add appropriate package / namespace syntax. | |
| 305 (self._type_comment_emitter, | |
| 306 self._members_emitter, | |
| 307 self._top_level_emitter) = interface_emitter.Emit( | |
| 308 interface_template + '$!TOP_LEVEL', | |
| 309 ID='_I%s' % interface_name, | |
| 310 EXTENDS=implements_str) | |
| 311 | |
| 312 implementation_emitter = self._ImplementationEmitter() | 258 implementation_emitter = self._ImplementationEmitter() |
| 313 | 259 |
| 314 base_type_info = None | 260 base_type_info = None |
| 315 if self._interface.parents: | 261 if self._interface.parents: |
| 316 supertype = self._interface.parents[0].type.id | 262 supertype = self._interface.parents[0].type.id |
| 317 if not IsDartCollectionType(supertype) and not IsPureInterface(supertype): | 263 if not IsDartCollectionType(supertype) and not IsPureInterface(supertype): |
| 318 base_type_info = self._type_registry.TypeInfo(supertype) | 264 base_type_info = self._type_registry.TypeInfo(supertype) |
| 319 if base_type_info.merged_into() \ | 265 if base_type_info.merged_into() \ |
| 320 and self._backend.ImplementsMergedMembers(): | 266 and self._backend.ImplementsMergedMembers(): |
| 321 base_type_info = self._type_registry.TypeInfo( | 267 base_type_info = self._type_registry.TypeInfo( |
| 322 base_type_info.merged_into()) | 268 base_type_info.merged_into()) |
| 323 | 269 |
| 324 if base_type_info: | 270 if base_type_info: |
| 325 base_class = base_type_info.implementation_name() | 271 base_class = base_type_info.implementation_name() |
| 326 else: | 272 else: |
| 327 base_class = self._backend.RootClassName() | 273 base_class = self._backend.RootClassName() |
| 328 | 274 |
| 329 implements = self._backend.AdditionalImplementedInterfaces() | 275 implements = self._backend.AdditionalImplementedInterfaces() |
| 330 for parent in self._interface.parents: | 276 for parent in self._interface.parents: |
| 331 parent_type_info = self._type_registry.TypeInfo(parent.type.id) | 277 parent_type_info = self._type_registry.TypeInfo(parent.type.id) |
| 332 if parent_type_info != base_type_info: | 278 if parent_type_info != base_type_info: |
| 333 implements.append(parent_type_info.interface_name()) | 279 implements.append(parent_type_info.interface_name()) |
| 334 | 280 |
| 335 if interface_name in _secure_base_types: | 281 secure_base_name = self._backend.SecureBaseName(interface_name) |
| 336 implements.append(_secure_base_types[interface_name]) | 282 if secure_base_name: |
| 283 implements.append(secure_base_name) |
| 337 | 284 |
| 338 implements_str = '' | 285 implements_str = '' |
| 339 if implements: | 286 if implements: |
| 340 implements_str = ' implements ' + ', '.join(set(implements)) | 287 implements_str = ' implements ' + ', '.join(set(implements)) |
| 341 | 288 |
| 342 self._implementation_members_emitter = implementation_emitter.Emit( | 289 self._implementation_members_emitter = implementation_emitter.Emit( |
| 343 self._backend.ImplementationTemplate(), | 290 self._backend.ImplementationTemplate(), |
| 344 CLASSNAME=self._interface_type_info.implementation_name(), | 291 CLASSNAME=self._interface_type_info.implementation_name(), |
| 345 EXTENDS=' extends %s' % base_class if base_class else '', | 292 EXTENDS=' extends %s' % base_class if base_class else '', |
| 346 IMPLEMENTS=implements_str, | 293 IMPLEMENTS=implements_str, |
| 347 DOMNAME=self._interface.doc_js_name, | 294 DOMNAME=self._interface.doc_js_name, |
| 348 NATIVESPEC=self._backend.NativeSpec()) | 295 NATIVESPEC=self._backend.NativeSpec()) |
| 349 self._backend.StartInterface(self._implementation_members_emitter) | 296 self._backend.StartInterface(self._implementation_members_emitter) |
| 350 | 297 |
| 351 for constructor_info in constructors: | |
| 352 constructor_info.GenerateFactoryInvocation( | |
| 353 self._DartType, self._members_emitter, factory_provider) | |
| 354 | |
| 355 self._backend.AddConstructors(constructors, factory_provider, | 298 self._backend.AddConstructors(constructors, factory_provider, |
| 356 self._interface_type_info.implementation_name(), | 299 self._interface_type_info.implementation_name(), |
| 357 base_class) | 300 base_class) |
| 358 | 301 |
| 359 typed_array_type = None | 302 events_class_name = self._event_generator.ProcessInterface( |
| 360 for interface in self._database.Hierarchy(self._interface): | |
| 361 type_info = self._type_registry.TypeInfo(interface.id) | |
| 362 if type_info.is_typed_array(): | |
| 363 typed_array_type = type_info.list_item_type() | |
| 364 break | |
| 365 if typed_array_type: | |
| 366 self._members_emitter.Emit( | |
| 367 '\n' | |
| 368 ' factory $CTOR(int length) =>\n' | |
| 369 ' $FACTORY.create$(CTOR)(length);\n' | |
| 370 '\n' | |
| 371 ' factory $CTOR.fromList(List<$TYPE> list) =>\n' | |
| 372 ' $FACTORY.create$(CTOR)_fromList(list);\n' | |
| 373 '\n' | |
| 374 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, [int byteOffset, int l
ength]) => \n' | |
| 375 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n'
, | |
| 376 CTOR=self._interface.id, | |
| 377 TYPE=self._DartType(typed_array_type), | |
| 378 FACTORY=factory_provider) | |
| 379 | |
| 380 events_interface = self._event_generator.ProcessInterface( | |
| 381 self._interface, interface_name, | 303 self._interface, interface_name, |
| 382 self._backend.CustomJSMembers(), | 304 self._backend.CustomJSMembers(), |
| 383 interface_emitter, implementation_emitter) | 305 implementation_emitter) |
| 384 if events_interface: | 306 if events_class_name: |
| 385 self._EmitEventGetter(events_interface, events_interface) | 307 self._backend.EmitEventGetter(events_class_name) |
| 386 | 308 |
| 387 old_backend = self._backend | |
| 388 if not self._backend.ImplementsMergedMembers(): | |
| 389 self._backend = HtmlGeneratorDummyBackend() | |
| 390 merged_interface = self._interface_type_info.merged_interface() | 309 merged_interface = self._interface_type_info.merged_interface() |
| 391 if merged_interface: | 310 if merged_interface: |
| 392 self.AddMembers(self._database.GetInterface(merged_interface)) | 311 self._backend.AddMembers(self._database.GetInterface(merged_interface), |
| 393 self._backend = old_backend | 312 not self._backend.ImplementsMergedMembers()) |
| 394 | 313 |
| 395 self.AddMembers(self._interface) | 314 self._backend.AddMembers(self._interface) |
| 396 if merged_interface and not self._backend.ImplementsMergedMembers(): | 315 self._backend.AddSecondaryMembers(self._interface) |
| 397 self.AddMembers(self._database.GetInterface(merged_interface), True) | |
| 398 | |
| 399 self.AddSecondaryMembers(self._interface) | |
| 400 self._backend.FinishInterface() | 316 self._backend.FinishInterface() |
| 401 | 317 |
| 402 def AddMembers(self, interface, declare_only=False): | |
| 403 for const in sorted(interface.constants, ConstantOutputOrder): | |
| 404 self.AddConstant(const) | |
| 405 | |
| 406 for attr in sorted(interface.attributes, ConstantOutputOrder): | |
| 407 if attr.type.id != 'EventListener': | |
| 408 self.AddAttribute(attr, False, declare_only) | |
| 409 | |
| 410 # The implementation should define an indexer if the interface directly | |
| 411 # extends List. | |
| 412 element_type = None | |
| 413 requires_indexer = False | |
| 414 if self._interface_type_info.list_item_type(): | |
| 415 self.AddIndexer(self._interface_type_info.list_item_type()) | |
| 416 else: | |
| 417 for parent in self._database.Hierarchy(self._interface): | |
| 418 if parent == self._interface: | |
| 419 continue | |
| 420 parent_type_info = self._type_registry.TypeInfo(parent.id) | |
| 421 if parent_type_info.list_item_type(): | |
| 422 self.AmendIndexer(parent_type_info.list_item_type()) | |
| 423 break | |
| 424 | |
| 425 # Group overloaded operations by id | |
| 426 operationsById = {} | |
| 427 for operation in interface.operations: | |
| 428 if operation.id not in operationsById: | |
| 429 operationsById[operation.id] = [] | |
| 430 operationsById[operation.id].append(operation) | |
| 431 | |
| 432 # Generate operations | |
| 433 for id in sorted(operationsById.keys()): | |
| 434 operations = operationsById[id] | |
| 435 info = AnalyzeOperation(interface, operations) | |
| 436 self.AddOperation(info, False, declare_only) | |
| 437 | |
| 438 def AddSecondaryMembers(self, interface): | |
| 439 # With multiple inheritance, attributes and operations of non-first | |
| 440 # interfaces need to be added. Sometimes the attribute or operation is | |
| 441 # defined in the current interface as well as a parent. In that case we | |
| 442 # avoid making a duplicate definition and pray that the signatures match. | |
| 443 secondary_parents = self._TransitiveSecondaryParents(interface) | |
| 444 for parent_interface in sorted(secondary_parents): | |
| 445 if isinstance(parent_interface, str): # IsDartCollectionType(parent_inter
face) | |
| 446 continue | |
| 447 for attr in sorted(parent_interface.attributes, ConstantOutputOrder): | |
| 448 if not FindMatchingAttribute(interface, attr): | |
| 449 self.AddSecondaryAttribute(parent_interface, attr) | |
| 450 | |
| 451 # Group overloaded operations by id | |
| 452 operationsById = {} | |
| 453 for operation in parent_interface.operations: | |
| 454 if operation.id not in operationsById: | |
| 455 operationsById[operation.id] = [] | |
| 456 operationsById[operation.id].append(operation) | |
| 457 | |
| 458 # Generate operations | |
| 459 for id in sorted(operationsById.keys()): | |
| 460 if not any(op.id == id for op in interface.operations): | |
| 461 operations = operationsById[id] | |
| 462 info = AnalyzeOperation(interface, operations) | |
| 463 self.AddSecondaryOperation(parent_interface, info) | |
| 464 | |
| 465 def AddIndexer(self, element_type): | |
| 466 self._backend.AddIndexer(element_type) | |
| 467 | |
| 468 def AmendIndexer(self, element_type): | |
| 469 self._backend.AmendIndexer(element_type) | |
| 470 | |
| 471 def AddAttribute(self, attribute, is_secondary=False, declare_only=False): | |
| 472 dom_name = DartDomNameOfAttribute(attribute) | |
| 473 html_name = self._renamer.RenameMember( | |
| 474 self._interface.id, attribute, dom_name, 'get:') | |
| 475 if not html_name or self._IsPrivate(html_name): | |
| 476 return | |
| 477 | |
| 478 | |
| 479 html_setter_name = self._renamer.RenameMember( | |
| 480 self._interface.id, attribute, dom_name, 'set:') | |
| 481 read_only = (attribute.is_read_only or 'Replaceable' in attribute.ext_attrs | |
| 482 or not html_setter_name) | |
| 483 | |
| 484 # We don't yet handle inconsistent renames of the getter and setter yet. | |
| 485 assert(not html_setter_name or html_name == html_setter_name) | |
| 486 | |
| 487 if not is_secondary: | |
| 488 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', | |
| 489 DOMINTERFACE=attribute.doc_js_interface_name, | |
| 490 DOMNAME=dom_name) | |
| 491 if read_only: | |
| 492 template = '\n $TYPE get $NAME;\n' | |
| 493 else: | |
| 494 template = '\n $TYPE $NAME;\n' | |
| 495 | |
| 496 self._members_emitter.Emit(template, | |
| 497 NAME=html_name, | |
| 498 TYPE=SecureOutputType(self, attribute.type.id)) | |
| 499 | |
| 500 if declare_only: | |
| 501 self._backend.DeclareAttribute(attribute, | |
| 502 SecureOutputType(self, attribute.type.id), html_name, read_only) | |
| 503 else: | |
| 504 self._backend.AddAttribute(attribute, html_name, read_only) | |
| 505 | |
| 506 def AddSecondaryAttribute(self, interface, attribute): | |
| 507 self._backend.SecondaryContext(interface) | |
| 508 self.AddAttribute(attribute, True) | |
| 509 | |
| 510 def AddOperation(self, info, skip_declaration=False, declare_only=False): | |
| 511 """ | |
| 512 Arguments: | |
| 513 operations - contains the overloads, one or more operations with the same | |
| 514 name. | |
| 515 """ | |
| 516 # FIXME: When we pass in operations[0] below, we're assuming all | |
| 517 # overloaded operations have the same security attributes. This | |
| 518 # is currently true, but we should consider filtering earlier or | |
| 519 # merging the relevant data into info itself. | |
| 520 html_name = self._renamer.RenameMember(self._interface.id, | |
| 521 info.operations[0], | |
| 522 info.name) | |
| 523 if not html_name: | |
| 524 if info.name == 'item': | |
| 525 # FIXME: item should be renamed to operator[], not removed. | |
| 526 self._backend.AddOperation(info, '_item') | |
| 527 return | |
| 528 | |
| 529 if not self._IsPrivate(html_name) and not skip_declaration: | |
| 530 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', | |
| 531 DOMINTERFACE=info.overloads[0].doc_js_interface_name, | |
| 532 DOMNAME=info.name) | |
| 533 | |
| 534 if info.IsStatic(): | |
| 535 # FIXME: provide a type. | |
| 536 self._members_emitter.Emit( | |
| 537 '\n' | |
| 538 ' static final $NAME = $IMPL_CLASS_NAME.$NAME;\n', | |
| 539 IMPL_CLASS_NAME=self._interface_type_info.implementation_name(), | |
| 540 NAME=html_name) | |
| 541 else: | |
| 542 self._members_emitter.Emit( | |
| 543 '\n' | |
| 544 ' $TYPE $NAME($PARAMS);\n', | |
| 545 TYPE=SecureOutputType(self, info.type_name), | |
| 546 NAME=html_name, | |
| 547 PARAMS=info.ParametersDeclaration(self._DartType)) | |
| 548 if declare_only: | |
| 549 self._backend.DeclareOperation(info, | |
| 550 SecureOutputType(self, info.type_name), html_name) | |
| 551 else: | |
| 552 self._backend.AddOperation(info, html_name) | |
| 553 | |
| 554 def AddSecondaryOperation(self, interface, info): | |
| 555 self._backend.SecondaryContext(interface) | |
| 556 self.AddOperation(info) | |
| 557 | |
| 558 def AddConstant(self, constant): | |
| 559 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) | |
| 560 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', | |
| 561 NAME=constant.id, | |
| 562 TYPE=type, | |
| 563 VALUE=constant.value) | |
| 564 | |
| 565 self._backend.AddConstant(constant) | |
| 566 | |
| 567 def _ImplementationEmitter(self): | 318 def _ImplementationEmitter(self): |
| 568 basename = self._interface_type_info.implementation_name() | 319 basename = self._interface_type_info.implementation_name() |
| 569 if (self._interface_type_info.merged_into() and | 320 if (self._interface_type_info.merged_into() and |
| 570 self._backend.ImplementsMergedMembers()): | 321 self._backend.ImplementsMergedMembers()): |
| 571 # Merged members are implemented in target interface implementation. | 322 # Merged members are implemented in target interface implementation. |
| 572 return emitter.Emitter() | 323 return emitter.Emitter() |
| 573 return self._library_emitter.FileEmitter(basename) | 324 return self._library_emitter.FileEmitter(basename) |
| 574 | 325 |
| 575 def _EmitEventGetter(self, events_interface, events_class): | |
| 576 self._members_emitter.Emit( | |
| 577 '\n /**' | |
| 578 '\n * @domName EventTarget.addEventListener, ' | |
| 579 'EventTarget.removeEventListener, EventTarget.dispatchEvent' | |
| 580 '\n */' | |
| 581 '\n $TYPE get on;\n', | |
| 582 TYPE=events_interface) | |
| 583 | |
| 584 self._implementation_members_emitter.Emit( | |
| 585 '\n /**' | |
| 586 '\n * @domName EventTarget.addEventListener, ' | |
| 587 'EventTarget.removeEventListener, EventTarget.dispatchEvent' | |
| 588 '\n */' | |
| 589 '\n $TYPE get on =>\n new $TYPE(this);\n', | |
| 590 TYPE=events_class) | |
| 591 | |
| 592 def _TransitiveSecondaryParents(self, interface): | |
| 593 """Returns a list of all non-primary parents. | |
| 594 | |
| 595 The list contains the interface objects for interfaces defined in the | |
| 596 database, and the name for undefined interfaces. | |
| 597 """ | |
| 598 def walk(parents): | |
| 599 for parent in parents: | |
| 600 parent_name = parent.type.id | |
| 601 if parent_name == 'EventTarget': | |
| 602 # Currently EventTarget is implemented as a mixin, not a proper | |
| 603 # super interface---ignore its members. | |
| 604 continue | |
| 605 if IsDartCollectionType(parent_name): | |
| 606 result.append(parent_name) | |
| 607 continue | |
| 608 if self._database.HasInterface(parent_name): | |
| 609 parent_interface = self._database.GetInterface(parent_name) | |
| 610 result.append(parent_interface) | |
| 611 walk(parent_interface.parents) | |
| 612 | |
| 613 result = [] | |
| 614 if interface.parents: | |
| 615 parent = interface.parents[0] | |
| 616 if IsPureInterface(parent.type.id): | |
| 617 walk(interface.parents) | |
| 618 else: | |
| 619 walk(interface.parents[1:]) | |
| 620 return result | |
| 621 | |
| 622 def _DartType(self, type_name): | 326 def _DartType(self, type_name): |
| 623 return self._type_registry.DartType(type_name) | 327 return self._type_registry.DartType(type_name) |
| 624 | 328 |
| 625 def _IsPrivate(self, name): | |
| 626 return name.startswith('_') | |
| 627 | |
| 628 | |
| 629 class HtmlGeneratorDummyBackend(object): | |
| 630 def AddAttribute(self, attribute, html_name, read_only): | |
| 631 pass | |
| 632 | |
| 633 def AddOperation(self, info, html_name): | |
| 634 pass | |
| 635 | |
| 636 | 329 |
| 637 # ------------------------------------------------------------------------------ | 330 # ------------------------------------------------------------------------------ |
| 638 | 331 |
| 639 class Dart2JSBackend(HtmlDartGenerator): | 332 class Dart2JSBackend(HtmlDartGenerator): |
| 640 """Generates a dart2js class for the dart:html library from a DOM IDL | 333 """Generates a dart2js class for the dart:html library from a DOM IDL |
| 641 interface. | 334 interface. |
| 642 """ | 335 """ |
| 643 | 336 |
| 644 def __init__(self, interface, options): | 337 def __init__(self, interface, options): |
| 645 super(Dart2JSBackend, self).__init__(interface, options) | 338 super(Dart2JSBackend, self).__init__(interface, options) |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 # | 418 # |
| 726 # class YImpl extends XImpl { add List<T> methods; } | 419 # class YImpl extends XImpl { add List<T> methods; } |
| 727 # | 420 # |
| 728 # and | 421 # and |
| 729 # | 422 # |
| 730 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } | 423 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
| 731 # | 424 # |
| 732 self._members_emitter.Emit( | 425 self._members_emitter.Emit( |
| 733 '\n' | 426 '\n' |
| 734 ' $TYPE operator[](int index) => JS("$TYPE", "#[#]", this, index);\n', | 427 ' $TYPE operator[](int index) => JS("$TYPE", "#[#]", this, index);\n', |
| 735 TYPE=self._NarrowOutputType(element_type)) | 428 TYPE=self.SecureOutputType(element_type)) |
| 736 | 429 |
| 737 if 'CustomIndexedSetter' in self._interface.ext_attrs: | 430 if 'CustomIndexedSetter' in self._interface.ext_attrs: |
| 738 self._members_emitter.Emit( | 431 self._members_emitter.Emit( |
| 739 '\n' | 432 '\n' |
| 740 ' void operator[]=(int index, $TYPE value) =>' | 433 ' void operator[]=(int index, $TYPE value) =>' |
| 741 ' JS("void", "#[#] = #", this, index, value);\n', | 434 ' JS("void", "#[#] = #", this, index, value);\n', |
| 742 TYPE=self._NarrowInputType(element_type)) | 435 TYPE=self._NarrowInputType(element_type)) |
| 743 else: | 436 else: |
| 744 # The HTML library implementation of NodeList has a custom indexed setter | 437 # The HTML library implementation of NodeList has a custom indexed setter |
| 745 # implementation that uses the parent node the NodeList is associated | 438 # implementation that uses the parent node the NodeList is associated |
| 746 # with if one is available. | 439 # with if one is available. |
| 747 if self._interface.id != 'NodeList': | 440 if self._interface.id != 'NodeList': |
| 748 self._members_emitter.Emit( | 441 self._members_emitter.Emit( |
| 749 '\n' | 442 '\n' |
| 750 ' void operator[]=(int index, $TYPE value) {\n' | 443 ' void operator[]=(int index, $TYPE value) {\n' |
| 751 ' throw new UnsupportedError("Cannot assign element of immutable
List.");\n' | 444 ' throw new UnsupportedError("Cannot assign element of immutable
List.");\n' |
| 752 ' }\n', | 445 ' }\n', |
| 753 TYPE=self._NarrowInputType(element_type)) | 446 TYPE=self._NarrowInputType(element_type)) |
| 754 | 447 |
| 755 # TODO(sra): Use separate mixins for mutable implementations of List<T>. | 448 # TODO(sra): Use separate mixins for mutable implementations of List<T>. |
| 756 # TODO(sra): Use separate mixins for typed array implementations of List<T>. | 449 # TODO(sra): Use separate mixins for typed array implementations of List<T>. |
| 757 if self._interface.id != 'NodeList': | 450 if self._interface.id != 'NodeList': |
| 758 template_file = 'immutable_list_mixin.darttemplate' | 451 template_file = 'immutable_list_mixin.darttemplate' |
| 759 has_contains = any(op.id == 'contains' for op in self._interface.operation
s) | 452 has_contains = any(op.id == 'contains' for op in self._interface.operation
s) |
| 760 template = self._template_loader.Load( | 453 template = self._template_loader.Load( |
| 761 template_file, | 454 template_file, |
| 762 {'DEFINE_CONTAINS': not has_contains}) | 455 {'DEFINE_CONTAINS': not has_contains}) |
| 763 self._members_emitter.Emit(template, E=self._DartType(element_type)) | 456 self._members_emitter.Emit(template, E=self._DartType(element_type)) |
| 764 | 457 |
| 765 def AddAttribute(self, attribute, html_name, read_only): | 458 def EmitAttribute(self, attribute, html_name, read_only): |
| 766 if self._HasCustomImplementation(attribute.id): | 459 if self._HasCustomImplementation(attribute.id): |
| 767 return | 460 return |
| 768 | 461 |
| 769 if IsPureInterface(self._interface.id): | 462 if IsPureInterface(self._interface.id): |
| 770 self._AddInterfaceAttribute(attribute) | 463 self._AddInterfaceAttribute(attribute) |
| 771 return | 464 return |
| 772 | 465 |
| 773 if attribute.id != html_name: | 466 if attribute.id != html_name: |
| 774 self._AddAttributeUsingProperties(attribute, html_name, read_only) | 467 self._AddAttributeUsingProperties(attribute, html_name, read_only) |
| 775 return | 468 return |
| (...skipping 10 matching lines...) Expand all Loading... |
| 786 if read_only: | 479 if read_only: |
| 787 if attribute.type.id == super_attribute.type.id: | 480 if attribute.type.id == super_attribute.type.id: |
| 788 # Compatible attribute, use the superclass property. This works | 481 # Compatible attribute, use the superclass property. This works |
| 789 # because JavaScript will do its own dynamic dispatch. | 482 # because JavaScript will do its own dynamic dispatch. |
| 790 self._members_emitter.Emit( | 483 self._members_emitter.Emit( |
| 791 '\n' | 484 '\n' |
| 792 ' // Use implementation from $SUPER.\n' | 485 ' // Use implementation from $SUPER.\n' |
| 793 ' // final $TYPE $NAME;\n', | 486 ' // final $TYPE $NAME;\n', |
| 794 SUPER=super_attribute_interface, | 487 SUPER=super_attribute_interface, |
| 795 NAME=DartDomNameOfAttribute(attribute), | 488 NAME=DartDomNameOfAttribute(attribute), |
| 796 TYPE=self._NarrowOutputType(attribute.type.id)) | 489 TYPE=self.SecureOutputType(attribute.type.id)) |
| 797 return | 490 return |
| 798 self._members_emitter.Emit('\n // Shadowing definition.') | 491 self._members_emitter.Emit('\n // Shadowing definition.') |
| 799 self._AddAttributeUsingProperties(attribute, html_name, read_only) | 492 self._AddAttributeUsingProperties(attribute, html_name, read_only) |
| 800 return | 493 return |
| 801 | 494 |
| 802 # If the type has a conversion we need a getter or setter to contain the | 495 # If the type has a conversion we need a getter or setter to contain the |
| 803 # conversion code. | 496 # conversion code. |
| 804 if (self._OutputConversion(attribute.type.id, attribute.id) or | 497 if (self._OutputConversion(attribute.type.id, attribute.id) or |
| 805 self._InputConversion(attribute.type.id, attribute.id)): | 498 self._InputConversion(attribute.type.id, attribute.id)): |
| 806 self._AddAttributeUsingProperties(attribute, html_name, read_only) | 499 self._AddAttributeUsingProperties(attribute, html_name, read_only) |
| 807 return | 500 return |
| 808 | 501 |
| 809 output_type = self._NarrowOutputType(attribute.type.id) | 502 output_type = self.SecureOutputType(attribute.type.id) |
| 810 input_type = self._NarrowInputType(attribute.type.id) | 503 input_type = self._NarrowInputType(attribute.type.id) |
| 811 self.EmitAttributeDocumentation(attribute) | 504 self.EmitAttributeDocumentation(attribute) |
| 812 if not read_only: | 505 if not read_only: |
| 813 self._members_emitter.Emit( | 506 self._members_emitter.Emit( |
| 814 '\n $TYPE $NAME;' | 507 '\n $TYPE $NAME;' |
| 815 '\n', | 508 '\n', |
| 816 NAME=DartDomNameOfAttribute(attribute), | 509 NAME=DartDomNameOfAttribute(attribute), |
| 817 TYPE=output_type) | 510 TYPE=output_type) |
| 818 else: | 511 else: |
| 819 self._members_emitter.Emit( | 512 self._members_emitter.Emit( |
| 820 '\n final $TYPE $NAME;' | 513 '\n final $TYPE $NAME;' |
| 821 '\n', | 514 '\n', |
| 822 NAME=DartDomNameOfAttribute(attribute), | 515 NAME=DartDomNameOfAttribute(attribute), |
| 823 TYPE=output_type) | 516 TYPE=output_type) |
| 824 | 517 |
| 825 def _AddAttributeUsingProperties(self, attribute, html_name, read_only): | 518 def _AddAttributeUsingProperties(self, attribute, html_name, read_only): |
| 826 self._AddRenamingGetter(attribute, html_name) | 519 self._AddRenamingGetter(attribute, html_name) |
| 827 if not read_only: | 520 if not read_only: |
| 828 self._AddRenamingSetter(attribute, html_name) | 521 self._AddRenamingSetter(attribute, html_name) |
| 829 | 522 |
| 830 def _AddInterfaceAttribute(self, attribute): | 523 def _AddInterfaceAttribute(self, attribute): |
| 831 self._members_emitter.Emit( | 524 self._members_emitter.Emit( |
| 832 '\n $TYPE $NAME;' | 525 '\n $TYPE $NAME;' |
| 833 '\n', | 526 '\n', |
| 834 NAME=DartDomNameOfAttribute(attribute), | 527 NAME=DartDomNameOfAttribute(attribute), |
| 835 TYPE=self._NarrowOutputType(attribute.type.id)) | 528 TYPE=self.SecureOutputType(attribute.type.id)) |
| 836 | 529 |
| 837 def _AddRenamingGetter(self, attr, html_name): | 530 def _AddRenamingGetter(self, attr, html_name): |
| 838 self.EmitAttributeDocumentation(attr) | 531 self.EmitAttributeDocumentation(attr) |
| 839 | 532 |
| 840 conversion = self._OutputConversion(attr.type.id, attr.id) | 533 conversion = self._OutputConversion(attr.type.id, attr.id) |
| 841 if conversion: | 534 if conversion: |
| 842 return self._AddConvertingGetter(attr, html_name, conversion) | 535 return self._AddConvertingGetter(attr, html_name, conversion) |
| 843 return_type = self._NarrowOutputType(attr.type.id) | 536 return_type = self.SecureOutputType(attr.type.id) |
| 844 self._members_emitter.Emit( | 537 self._members_emitter.Emit( |
| 845 # TODO(sra): Use metadata to provide native name. | 538 # TODO(sra): Use metadata to provide native name. |
| 846 '\n $TYPE get $HTML_NAME => JS("$TYPE", "#.$NAME", this);' | 539 '\n $TYPE get $HTML_NAME => JS("$TYPE", "#.$NAME", this);' |
| 847 '\n', | 540 '\n', |
| 848 HTML_NAME=html_name, | 541 HTML_NAME=html_name, |
| 849 NAME=attr.id, | 542 NAME=attr.id, |
| 850 TYPE=return_type) | 543 TYPE=return_type) |
| 851 | 544 |
| 852 def _AddRenamingSetter(self, attr, html_name): | 545 def _AddRenamingSetter(self, attr, html_name): |
| 853 self.EmitAttributeDocumentation(attr) | 546 self.EmitAttributeDocumentation(attr) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 '\n', | 583 '\n', |
| 891 CONVERT=conversion.function_name, | 584 CONVERT=conversion.function_name, |
| 892 HTML_NAME=html_name, | 585 HTML_NAME=html_name, |
| 893 NAME=attr.id, | 586 NAME=attr.id, |
| 894 INPUT_TYPE=conversion.input_type, | 587 INPUT_TYPE=conversion.input_type, |
| 895 NATIVE_TYPE=conversion.output_type) | 588 NATIVE_TYPE=conversion.output_type) |
| 896 | 589 |
| 897 def AmendIndexer(self, element_type): | 590 def AmendIndexer(self, element_type): |
| 898 pass | 591 pass |
| 899 | 592 |
| 900 def AddOperation(self, info, html_name): | 593 def EmitOperation(self, info, html_name): |
| 901 """ | 594 """ |
| 902 Arguments: | 595 Arguments: |
| 903 info: An OperationInfo object. | 596 info: An OperationInfo object. |
| 904 """ | 597 """ |
| 905 if self._HasCustomImplementation(info.name): | 598 if self._HasCustomImplementation(info.name): |
| 906 return | 599 return |
| 907 | 600 |
| 908 self.EmitOperationDocumentation(info) | 601 self.EmitOperationDocumentation(info) |
| 909 | 602 |
| 910 if IsPureInterface(self._interface.id): | 603 if IsPureInterface(self._interface.id): |
| 911 self._AddInterfaceOperation(info, html_name) | 604 self._AddInterfaceOperation(info, html_name) |
| 912 elif any(self._OperationRequiresConversions(op) for op in info.overloads): | 605 elif any(self._OperationRequiresConversions(op) for op in info.overloads): |
| 913 # Any conversions needed? | 606 # Any conversions needed? |
| 914 self._AddOperationWithConversions(info, html_name) | 607 self._AddOperationWithConversions(info, html_name) |
| 915 else: | 608 else: |
| 916 self._AddDirectNativeOperation(info, html_name) | 609 self._AddDirectNativeOperation(info, html_name) |
| 917 | 610 |
| 918 def _AddDirectNativeOperation(self, info, html_name): | 611 def _AddDirectNativeOperation(self, info, html_name): |
| 919 # Do we need a native body? | 612 # Do we need a native body? |
| 920 if html_name != info.declared_name: | 613 if html_name != info.declared_name: |
| 921 return_type = self._NarrowOutputType(info.type_name) | 614 return_type = self.SecureOutputType(info.type_name) |
| 922 | 615 |
| 923 operation_emitter = self._members_emitter.Emit('$!SCOPE', | 616 operation_emitter = self._members_emitter.Emit('$!SCOPE', |
| 924 MODIFIERS='static ' if info.IsStatic() else '', | 617 MODIFIERS='static ' if info.IsStatic() else '', |
| 925 TYPE=return_type, | 618 TYPE=return_type, |
| 926 HTML_NAME=html_name, | 619 HTML_NAME=html_name, |
| 927 NAME=info.declared_name, | 620 NAME=info.declared_name, |
| 928 PARAMS=info.ParametersDeclaration(self._NarrowInputType)) | 621 PARAMS=info.ParametersDeclaration(self._NarrowInputType)) |
| 929 | 622 |
| 930 operation_emitter.Emit( | 623 operation_emitter.Emit( |
| 931 '\n' | 624 '\n' |
| 932 #' // @native("$NAME")\n;' | 625 #' // @native("$NAME")\n;' |
| 933 ' $MODIFIERS$TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n') | 626 ' $MODIFIERS$TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n') |
| 934 else: | 627 else: |
| 935 self._members_emitter.Emit( | 628 self._members_emitter.Emit( |
| 936 '\n' | 629 '\n' |
| 937 ' $MODIFIERS$TYPE $NAME($PARAMS) native;\n', | 630 ' $MODIFIERS$TYPE $NAME($PARAMS) native;\n', |
| 938 MODIFIERS='static ' if info.IsStatic() else '', | 631 MODIFIERS='static ' if info.IsStatic() else '', |
| 939 TYPE=self._NarrowOutputType(info.type_name), | 632 TYPE=self.SecureOutputType(info.type_name), |
| 940 NAME=info.name, | 633 NAME=info.name, |
| 941 PARAMS=info.ParametersDeclaration(self._NarrowInputType)) | 634 PARAMS=info.ParametersDeclaration(self._NarrowInputType)) |
| 942 | 635 |
| 943 def _AddOperationWithConversions(self, info, html_name): | 636 def _AddOperationWithConversions(self, info, html_name): |
| 944 # Assert all operations have same return type. | 637 # Assert all operations have same return type. |
| 945 assert len(set([op.type.id for op in info.operations])) == 1 | 638 assert len(set([op.type.id for op in info.operations])) == 1 |
| 946 info = info.CopyAndWidenDefaultParameters() | 639 info = info.CopyAndWidenDefaultParameters() |
| 947 output_conversion = self._OutputConversion(info.type_name, | 640 output_conversion = self._OutputConversion(info.type_name, |
| 948 info.declared_name) | 641 info.declared_name) |
| 949 if output_conversion: | 642 if output_conversion: |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1076 if self._IsOptional(operation, argument): | 769 if self._IsOptional(operation, argument): |
| 1077 check = '?%s' % parameter_names[position] | 770 check = '?%s' % parameter_names[position] |
| 1078 GenerateCall(operation, position + 1, [check]) | 771 GenerateCall(operation, position + 1, [check]) |
| 1079 argument_count = position | 772 argument_count = position |
| 1080 GenerateCall(operation, argument_count, []) | 773 GenerateCall(operation, argument_count, []) |
| 1081 | 774 |
| 1082 def _AddInterfaceOperation(self, info, html_name): | 775 def _AddInterfaceOperation(self, info, html_name): |
| 1083 self._members_emitter.Emit( | 776 self._members_emitter.Emit( |
| 1084 '\n' | 777 '\n' |
| 1085 ' $TYPE $NAME($PARAMS);\n', | 778 ' $TYPE $NAME($PARAMS);\n', |
| 1086 TYPE=self._NarrowOutputType(info.type_name), | 779 TYPE=self.SecureOutputType(info.type_name), |
| 1087 NAME=info.name, | 780 NAME=info.name, |
| 1088 PARAMS=info.ParametersDeclaration(self._NarrowInputType)) | 781 PARAMS=info.ParametersDeclaration(self._NarrowInputType)) |
| 1089 | 782 |
| 1090 def AddConstant(self, constant): | 783 def AddConstant(self, constant): |
| 1091 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) | 784 type = TypeOrNothing(self._DartType(constant.type.id), constant.type.id) |
| 1092 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', | 785 self._members_emitter.Emit('\n static const $TYPE$NAME = $VALUE;\n', |
| 1093 NAME=constant.id, | 786 NAME=constant.id, |
| 1094 TYPE=type, | 787 TYPE=type, |
| 1095 VALUE=constant.value) | 788 VALUE=constant.value) |
| 1096 | 789 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1122 | 815 |
| 1123 def CustomJSMembers(self): | 816 def CustomJSMembers(self): |
| 1124 return _js_custom_members | 817 return _js_custom_members |
| 1125 | 818 |
| 1126 def _NarrowToImplementationType(self, type_name): | 819 def _NarrowToImplementationType(self, type_name): |
| 1127 return self._type_registry.TypeInfo(type_name).narrow_dart_type() | 820 return self._type_registry.TypeInfo(type_name).narrow_dart_type() |
| 1128 | 821 |
| 1129 def _NarrowInputType(self, type_name): | 822 def _NarrowInputType(self, type_name): |
| 1130 return self._NarrowToImplementationType(type_name) | 823 return self._NarrowToImplementationType(type_name) |
| 1131 | 824 |
| 1132 def _NarrowOutputType(self, type_name): | |
| 1133 return SecureOutputType(self, type_name) | |
| 1134 | |
| 1135 def _FindShadowedAttribute(self, attr): | 825 def _FindShadowedAttribute(self, attr): |
| 1136 """Returns (attribute, superinterface) or (None, None).""" | 826 """Returns (attribute, superinterface) or (None, None).""" |
| 1137 def FindInParent(interface): | 827 def FindInParent(interface): |
| 1138 """Returns matching attribute in parent, or None.""" | 828 """Returns matching attribute in parent, or None.""" |
| 1139 if interface.parents: | 829 if interface.parents: |
| 1140 parent = interface.parents[0] | 830 parent = interface.parents[0] |
| 1141 if IsDartCollectionType(parent.type.id): | 831 if IsDartCollectionType(parent.type.id): |
| 1142 return (None, None) | 832 return (None, None) |
| 1143 if IsPureInterface(parent.type.id): | 833 if IsPureInterface(parent.type.id): |
| 1144 return (None, None) | 834 return (None, None) |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 | 886 |
| 1197 library_emitter = self._multiemitter.FileEmitter(library_file_path) | 887 library_emitter = self._multiemitter.FileEmitter(library_file_path) |
| 1198 library_file_dir = os.path.dirname(library_file_path) | 888 library_file_dir = os.path.dirname(library_file_path) |
| 1199 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) | 889 auxiliary_dir = os.path.relpath(auxiliary_dir, library_file_dir) |
| 1200 imports_emitter = library_emitter.Emit( | 890 imports_emitter = library_emitter.Emit( |
| 1201 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) | 891 self._template, AUXILIARY_DIR=massage_path(auxiliary_dir)) |
| 1202 for path in sorted(self._path_to_emitter.keys()): | 892 for path in sorted(self._path_to_emitter.keys()): |
| 1203 relpath = os.path.relpath(path, library_file_dir) | 893 relpath = os.path.relpath(path, library_file_dir) |
| 1204 imports_emitter.Emit( | 894 imports_emitter.Emit( |
| 1205 "part '$PATH';\n", PATH=massage_path(relpath)) | 895 "part '$PATH';\n", PATH=massage_path(relpath)) |
| OLD | NEW |