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

Side by Side Diff: mojo/public/tools/bindings/pylib/mojom/generate/generator.py

Issue 2250183003: Make the fuchsia mojo/public repo the source of truth. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 4 years, 4 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
OLDNEW
(Empty)
1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Code shared by the various language-specific code generators."""
6
7 from functools import partial
8 from itertools import chain
9 import os.path
10 import re
11
12 import module as mojom
13 import mojom.fileutil as fileutil
14 import pack
15
16 def ExpectedArraySize(kind):
17 if mojom.IsArrayKind(kind):
18 return kind.length
19 return None
20
21 def StudlyCapsToCamel(studly):
22 return studly[0].lower() + studly[1:]
23
24 def CamelCaseToAllCaps(camel_case):
25 return '_'.join(
26 word for word in re.split(r'([A-Z][^A-Z]+)', camel_case) if word).upper()
27
28 def UnderToCamel(under):
29 """Converts underscore_separated strings to CamelCase strings."""
30 return ''.join(word.capitalize() for word in under.split('_'))
31
32 def WriteFile(contents, full_path):
33 # Make sure the containing directory exists.
34 full_dir = os.path.dirname(full_path)
35 fileutil.EnsureDirectoryExists(full_dir)
36
37 # Dump the data to disk.
38 with open(full_path, "w+") as f:
39 f.write(contents)
40
41 class Generator(object):
42 # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all
43 # files to stdout.
44 def __init__(self, module, output_dir=None):
45 self.module = module
46 self.output_dir = output_dir
47
48 def GetStructsFromMethods(self):
49 result = []
50 for interface in self.module.interfaces:
51 for method in interface.methods:
52 result.append(self._GetStructFromMethod(method))
53 if method.response_parameters != None:
54 result.append(self._GetResponseStructFromMethod(method))
55 return result
56
57 def GetStructs(self):
58 return map(partial(self._AddStructComputedData, True), self.module.structs)
59
60 def GetUnions(self):
61 return self.module.unions
62
63 def GetInterfaces(self):
64 return map(self._AddInterfaceComputedData, self.module.interfaces)
65
66 def GetUsedImports(self, module):
67 """GetUsedImports computes the imports that are used in the provided module.
68
69 An import being used means that a type or constant defined in the import is
70 referenced in the provided module.
71
72 Args:
73 module: {module.Module} The module whose used imports are to be computed.
74
75 Returns:
76 {dict<str, dict>} A dictionary of the used imports. The key is the file
77 name as defined in the import's Module.path. The value is a dictionary.
78 The contents of the dictionary is identical to that found in the
79 imported_from field of mojom elements.
80 """
81 used = {}
82
83 def AddImport(element):
84 """AddImport is a utility function that adds the import of the provided
85 element to the used dictionary defined above.
86 """
87 # Only named values or kinds could be imported.
88 if (not isinstance(element, mojom.Kind) and
89 not isinstance(element, mojom.NamedValue)):
90 return
91
92 if mojom.IsArrayKind(element) or mojom.IsInterfaceRequestKind(element):
93 AddImport(element.kind)
94 return
95 if mojom.IsMapKind(element):
96 AddImport(element.key_kind)
97 AddImport(element.value_kind)
98 return
99 if not hasattr(element, 'imported_from') or not element.imported_from:
100 return
101
102 imported_from = element.imported_from
103 used[imported_from['module'].path] = imported_from
104
105 # We want to collect the structs that represent method input and output
106 # parameters.
107 all_structs = list(module.structs)
108 for interface in module.interfaces:
109 for method in interface.methods:
110 all_structs.append(self._GetStructFromMethod(method))
111 if method.response_parameters:
112 all_structs.append(self._GetResponseStructFromMethod(method))
113
114 for struct in all_structs:
115 for field in struct.fields:
116 AddImport(field.kind)
117 if field.default:
118 AddImport(field.default)
119
120 # Enums can be defined in the module, in structs or in interfaces.
121 enum_containers = [module] + module.structs + module.interfaces
122 enums = [c.enums for c in enum_containers]
123 for enum in chain.from_iterable(enums):
124 for field in enum.fields:
125 if field.value:
126 AddImport(field.value)
127
128 for union in module.unions:
129 for field in union.fields:
130 AddImport(field.kind)
131
132 for constant in module.constants:
133 AddImport(constant.value)
134
135 return used
136
137 # Prepend the filename with a directory that matches the directory of the
138 # original .mojom file, relative to the import root.
139 def MatchMojomFilePath(self, filename):
140 return os.path.join(os.path.dirname(self.module.path), filename)
141
142 def Write(self, contents, filename):
143 if self.output_dir is None:
144 print contents
145 return
146 full_path = os.path.join(self.output_dir, filename)
147 WriteFile(contents, full_path)
148
149 def GenerateFiles(self, args):
150 raise NotImplementedError("Subclasses must override/implement this method")
151
152 def GetJinjaParameters(self):
153 """Returns default constructor parameters for the jinja environment."""
154 return {}
155
156 def GetGlobals(self):
157 """Returns global mappings for the template generation."""
158 return {}
159
160 def _AddStructComputedData(self, exported, struct):
161 """Adds computed data to the given struct. The data is computed once and
162 used repeatedly in the generation process."""
163 if not hasattr(struct, 'packed') or struct.packed is None:
164 struct.packed = pack.PackedStruct(struct)
165 struct.bytes = pack.GetByteLayout(struct.packed)
166 struct.exported = exported
167 return struct
168
169 def _AddInterfaceComputedData(self, interface):
170 """Adds computed data to the given interface. The data is computed once and
171 used repeatedly in the generation process."""
172 for method in interface.methods:
173 method.param_struct = self._GetStructFromMethod(method)
174 if method.response_parameters is not None:
175 method.response_param_struct = self._GetResponseStructFromMethod(method)
176 else:
177 method.response_param_struct = None
178 return interface
179
180 def _GetStructFromMethod(self, method):
181 """Returns a method's parameters as a struct."""
182 return self._AddStructComputedData(False, method.param_struct)
183
184 def _GetResponseStructFromMethod(self, method):
185 """Returns a method's response_parameters as a struct."""
186 return self._AddStructComputedData(False, method.response_param_struct)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698