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

Side by Side Diff: Source/bindings/scripts/interface_dependency_resolver.py

Issue 205873003: Refactor interface dependency resolution (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 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
« no previous file with comments | « Source/bindings/scripts/idl_reader.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (C) 2013 Google Inc. All rights reserved. 1 # Copyright (C) 2013 Google Inc. All rights reserved.
2 # 2 #
3 # Redistribution and use in source and binary forms, with or without 3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are 4 # modification, are permitted provided that the following conditions are
5 # met: 5 # met:
6 # 6 #
7 # * Redistributions of source code must retain the above copyright 7 # * Redistributions of source code must retain the above copyright
8 # notice, this list of conditions and the following disclaimer. 8 # notice, this list of conditions and the following disclaimer.
9 # * Redistributions in binary form must reproduce the above 9 # * Redistributions in binary form must reproduce the above
10 # copyright notice, this list of conditions and the following disclaimer 10 # copyright notice, this list of conditions and the following disclaimer
(...skipping 19 matching lines...) Expand all
30 30
31 This library computes interface dependencies (partial interfaces and 31 This library computes interface dependencies (partial interfaces and
32 implements), reads the dependency files, and merges them to the IdlDefinitions 32 implements), reads the dependency files, and merges them to the IdlDefinitions
33 for the main IDL file, producing an IdlDefinitions object representing the 33 for the main IDL file, producing an IdlDefinitions object representing the
34 entire interface. 34 entire interface.
35 35
36 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC -Dependency-resolution 36 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC -Dependency-resolution
37 """ 37 """
38 38
39 import os.path 39 import os.path
40 import cPickle as pickle
41 40
42 # The following extended attributes can be applied to a dependency interface, 41 # The following extended attributes can be applied to a dependency interface,
43 # and are then applied to the individual members when merging. 42 # and are then applied to the individual members when merging.
44 # Note that this moves the extended attribute from the interface to the member, 43 # Note that this moves the extended attribute from the interface to the member,
45 # which changes the semantics and yields different code than the same extended 44 # which changes the semantics and yields different code than the same extended
46 # attribute on the main interface. 45 # attribute on the main interface.
47 DEPENDENCY_EXTENDED_ATTRIBUTES = set([ 46 DEPENDENCY_EXTENDED_ATTRIBUTES = set([
48 'Conditional', 47 'Conditional',
49 'PerContextEnabled', 48 'PerContextEnabled',
50 'RuntimeEnabled', 49 'RuntimeEnabled',
51 ]) 50 ])
52 51
53 52
54 class InterfaceNotFoundError(Exception):
55 """Raised if (partial) interface not found in target IDL file."""
56 pass
57
58
59 class InvalidPartialInterfaceError(Exception):
60 """Raised if a file listed as a partial interface is not in fact so."""
61 pass
62
63
64 class InterfaceDependencyResolver(object): 53 class InterfaceDependencyResolver(object):
65 def __init__(self, interfaces_info, reader): 54 def __init__(self, interfaces_info, reader):
66 """Initialize dependency resolver. 55 """Initialize dependency resolver.
67 56
68 Args: 57 Args:
69 interfaces_info: 58 interfaces_info:
70 dict of interfaces information, from compute_dependencies.py 59 dict of interfaces information, from compute_dependencies.py
71 reader: 60 reader:
72 IdlReader, used for reading dependency files 61 IdlReader, used for reading dependency files
73 """ 62 """
74 self.interfaces_info = interfaces_info 63 self.interfaces_info = interfaces_info
75 self.reader = reader 64 self.reader = reader
76 65
77 def resolve_dependencies(self, definitions, interface_name): 66 def resolve_dependencies(self, definitions):
78 """Resolve dependencies, merging them into IDL definitions of main file. 67 """Resolve dependencies, merging them into IDL definitions of main file.
79 68
80 Dependencies consist of 'partial interface' for the same interface as 69 Dependencies consist of 'partial interface' for the same interface as
81 in the main file, and other interfaces that this interface 'implements'. 70 in the main file, and other interfaces that this interface 'implements'.
71 These are merged into the main IdlInterface, as the main IdlInterface
72 implements all these members.
73
74 Referenced interfaces are added to IdlDefinitions, but not merged into
75 the main IdlInterface, as these are only referenced (their members are
76 introspected, but not implemented in this interface).
77
78 Inherited extended attributes are also added to the main IdlInterface.
82 79
83 Modifies definitions in place by adding parsed dependencies. 80 Modifies definitions in place by adding parsed dependencies.
84 81
85 Args: 82 Args:
86 definitions: IdlDefinitions object, modified in place 83 definitions: IdlDefinitions object, modified in place
87 interface_name:
88 name of interface whose dependencies are being resolved
89 """ 84 """
90 # The Blink IDL filenaming convention is that the file 85 target_interface = next(definitions.interfaces.itervalues())
91 # <interface_name>.idl MUST contain the interface "interface_name" or 86 interface_name = target_interface.name
92 # exception "interface_name", unless it is a dependency (e.g., 87 interface_info = self.interfaces_info[interface_name]
93 # 'partial interface Foo' can be in FooBar.idl).
94 try:
95 target_interface = definitions.interfaces[interface_name]
96 except KeyError:
97 raise InterfaceNotFoundError('Could not find interface or exception "{0}" in {0}.idl'.format(interface_name))
98 88
99 if interface_name not in self.interfaces_info:
100 # No dependencies, nothing to do
101 return
102
103 interface_info = self.interfaces_info[interface_name]
104 if 'inherited_extended_attributes' in interface_info: 89 if 'inherited_extended_attributes' in interface_info:
105 target_interface.extended_attributes.update( 90 target_interface.extended_attributes.update(
106 interface_info['inherited_extended_attributes']) 91 interface_info['inherited_extended_attributes'])
107 92
108 merge_interface_dependencies(target_interface, 93 merge_interface_dependencies(definitions,
94 target_interface,
109 interface_info['dependencies_full_paths'], 95 interface_info['dependencies_full_paths'],
110 self.reader) 96 self.reader)
111 97
112 for referenced_interface_name in interface_info['referenced_interfaces'] : 98 for referenced_interface_name in interface_info['referenced_interfaces'] :
113 referenced_definitions = self.reader.read_idl_definitions( 99 referenced_definitions = self.reader.read_idl_definitions(
114 self.interfaces_info[referenced_interface_name]['full_path']) 100 self.interfaces_info[referenced_interface_name]['full_path'])
115 definitions.interfaces.update(referenced_definitions.interfaces) 101 definitions.update(referenced_definitions)
116 102
117 103
118 def merge_interface_dependencies(target_interface, dependency_idl_filenames, rea der): 104 def merge_interface_dependencies(definitions, target_interface, dependency_idl_f ilenames, reader):
119 """Merge dependencies ('partial interface' and 'implements') in dependency_i dl_filenames into target_interface. 105 """Merge dependencies ('partial interface' and 'implements') in dependency_i dl_filenames into target_interface.
120 106
121 No return: modifies target_interface in place. 107 No return: modifies target_interface in place.
122 """ 108 """
123 # Sort so order consistent, so can compare output from run to run. 109 # Sort so order consistent, so can compare output from run to run.
124 for dependency_idl_filename in sorted(dependency_idl_filenames): 110 for dependency_idl_filename in sorted(dependency_idl_filenames):
111 dependency_definitions = reader.read_idl_file(dependency_idl_filename)
112 dependency_interface = next(dependency_definitions.interfaces.itervalues ())
125 dependency_interface_basename, _ = os.path.splitext(os.path.basename(dep endency_idl_filename)) 113 dependency_interface_basename, _ = os.path.splitext(os.path.basename(dep endency_idl_filename))
126 definitions = reader.read_idl_file(dependency_idl_filename)
127 114
128 for dependency_interface in definitions.interfaces.itervalues(): 115 transfer_extended_attributes(dependency_interface, dependency_interface_ basename)
129 # Dependency files contain either partial interfaces for 116 definitions.update(dependency_definitions)
130 # the (single) target interface, in which case the interface names 117 if not dependency_interface.is_partial:
131 # must agree, or interfaces that are implemented by the target 118 # Implemented interfaces (non-partial dependencies) are merged
132 # interface, in which case the interface names differ. 119 # into the target interface, so Code Generator can just iterate
133 if (dependency_interface.is_partial and 120 # over one list (and not need to handle 'implements' itself).
134 dependency_interface.name != target_interface.name): 121 target_interface.merge(dependency_interface)
135 raise InvalidPartialInterfaceError('%s is not a partial interfac e of %s. There maybe a bug in the the dependency generator (compute_dependencies .py).' % (dependency_idl_filename, target_interface.name))
136 merge_dependency_interface(target_interface, dependency_interface, d ependency_interface_basename)
137 122
138 123
139 def merge_dependency_interface(target_interface, dependency_interface, dependenc y_interface_basename): 124 def transfer_extended_attributes(dependency_interface, dependency_interface_base name):
140 """Merge dependency_interface into target_interface. 125 """Transfer extended attributes from dependency interface onto members.
141 126
142 Merging consists of storing certain interface-level data in extended 127 Merging consists of storing certain interface-level data in extended
143 attributes of the *members* (because there is no separate dependency 128 attributes of the *members* (because there is no separate dependency
144 interface post-merging), then concatenating the lists. 129 interface post-merging).
145 130
146 The data storing consists of: 131 The data storing consists of:
147 * applying certain extended attributes from the dependency interface 132 * applying certain extended attributes from the dependency interface
148 to its members 133 to its members
149 * storing the C++ class of the implementation in an internal 134 * storing the C++ class of the implementation in an internal
150 extended attribute of each member, [ImplementedBy] 135 extended attribute of each member, [ImplementedBy]
151 136
152 No return: modifies target_interface in place. 137 No return: modifies dependency_interface in place.
153 """ 138 """
154 merged_extended_attributes = dict( 139 merged_extended_attributes = dict(
155 (key, value) 140 (key, value)
156 for key, value in dependency_interface.extended_attributes.iteritems() 141 for key, value in dependency_interface.extended_attributes.iteritems()
157 if key in DEPENDENCY_EXTENDED_ATTRIBUTES) 142 if key in DEPENDENCY_EXTENDED_ATTRIBUTES)
158 143
159 # C++ class name of the implementation, stored in [ImplementedBy], which 144 # C++ class name of the implementation, stored in [ImplementedBy], which
160 # defaults to the basename of dependency IDL file. 145 # defaults to the basename of dependency IDL file.
161 # This can be overridden by [ImplementedAs] on the dependency interface. 146 # This can be overridden by [ImplementedAs] on the dependency interface.
162 # Note that [ImplementedAs] is used with different meanings on interfaces 147 # Note that [ImplementedAs] is used with different meanings on interfaces
163 # and members: 148 # and members:
164 # for Blink class name and function name (or constant name), respectively. 149 # for Blink class name and function name (or constant name), respectively.
165 # Thus we do not want to copy this from the interface to the member, but 150 # Thus we do not want to copy this from the interface to the member, but
166 # instead extract it and handle it separately. 151 # instead extract it and handle it separately.
167 merged_extended_attributes['ImplementedBy'] = ( 152 merged_extended_attributes['ImplementedBy'] = (
168 dependency_interface.extended_attributes.get( 153 dependency_interface.extended_attributes.get(
169 'ImplementedAs', dependency_interface_basename)) 154 'ImplementedAs', dependency_interface_basename))
170 155
171 def merge_lists(source_list, target_list): 156 for attribute in dependency_interface.attributes:
172 for member in source_list: 157 attribute.extended_attributes.update(merged_extended_attributes)
173 member.extended_attributes.update(merged_extended_attributes) 158 for constant in dependency_interface.constants:
174 target_list.extend(source_list) 159 constant.extended_attributes.update(merged_extended_attributes)
175 160 for operation in dependency_interface.operations:
176 merge_lists(dependency_interface.attributes, target_interface.attributes) 161 operation.extended_attributes.update(merged_extended_attributes)
177 merge_lists(dependency_interface.constants, target_interface.constants)
178 merge_lists(dependency_interface.operations, target_interface.operations)
OLDNEW
« no previous file with comments | « Source/bindings/scripts/idl_reader.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698