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

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

Issue 2863353002: Mojo code generator: change where to add computed data to mojom definitions (Closed)
Patch Set: . Created 3 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
OLDNEW
1 # Copyright 2013 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 """Code shared by the various language-specific code generators.""" 5 """Code shared by the various language-specific code generators."""
6 6
7 from functools import partial 7 from functools import partial
8 import os.path 8 import os.path
9 import re 9 import re
10 10
11 import module as mojom 11 import module as mojom
12 import mojom.fileutil as fileutil 12 import mojom.fileutil as fileutil
13 import pack 13 import pack
14 14
15
15 def ExpectedArraySize(kind): 16 def ExpectedArraySize(kind):
16 if mojom.IsArrayKind(kind): 17 if mojom.IsArrayKind(kind):
17 return kind.length 18 return kind.length
18 return None 19 return None
19 20
20 def StudlyCapsToCamel(studly):
21 return studly[0].lower() + studly[1:]
22 21
23 def UnderToCamel(under): 22 def ToCamel(identifier, lower_initial=False, dilimiter='_'):
24 """Converts underscore_separated strings to CamelCase strings.""" 23 """Splits |identifier| using |dilimiter|, makes the first character of each
25 return ''.join(word.capitalize() for word in under.split('_')) 24 word uppercased (but makes the first character of the first word lowercased
25 if |lower_initial| is set to True), and joins the words. Please note that for
26 each word, all the characters except the first one are untouched.
27 """
28 result = ''.join(
29 word[0].upper() + word[1:] for word in identifier.split(dilimiter))
30 if lower_initial:
31 result = result[0].lower() + result[1:]
32 return result
33
26 34
27 def WriteFile(contents, full_path): 35 def WriteFile(contents, full_path):
28 # Make sure the containing directory exists. 36 # Make sure the containing directory exists.
29 full_dir = os.path.dirname(full_path) 37 full_dir = os.path.dirname(full_path)
30 fileutil.EnsureDirectoryExists(full_dir) 38 fileutil.EnsureDirectoryExists(full_dir)
31 39
32 # Dump the data to disk. 40 # Dump the data to disk.
33 with open(full_path, "w+") as f: 41 with open(full_path, "w+") as f:
34 f.write(contents) 42 f.write(contents)
35 43
44
45 def AddComputedData(module):
46 """Adds computed data to the given module. The data is computed once and
47 used repeatedly in the generation process."""
48
49 def _AddStructComputedData(exported, struct):
50 struct.packed = pack.PackedStruct(struct)
51 struct.bytes = pack.GetByteLayout(struct.packed)
52 struct.versions = pack.GetVersionInfo(struct.packed)
53 struct.exported = exported
54
55 def _AddUnionComputedData(union):
56 ordinal = 0
57 for field in union.fields:
58 if field.ordinal is not None:
59 ordinal = field.ordinal
60 field.ordinal = ordinal
61 ordinal += 1
62
63 def _AddInterfaceComputedData(interface):
64 next_ordinal = 0
65 interface.version = 0
66 for method in interface.methods:
67 if method.ordinal is None:
68 method.ordinal = next_ordinal
69 next_ordinal = method.ordinal + 1
70
71 if method.min_version is not None:
72 interface.version = max(interface.version, method.min_version)
73
74 method.param_struct = _GetStructFromMethod(method)
75 interface.version = max(interface.version,
76 method.param_struct.versions[-1].version)
77
78 if method.response_parameters is not None:
79 method.response_param_struct = _GetResponseStructFromMethod(method)
80 interface.version = max(
81 interface.version,
82 method.response_param_struct.versions[-1].version)
83 else:
84 method.response_param_struct = None
85
86 def _GetStructFromMethod(method):
87 """Converts a method's parameters into the fields of a struct."""
88 params_class = "%s_%s_Params" % (method.interface.name, method.name)
89 struct = mojom.Struct(params_class, module=method.interface.module)
90 for param in method.parameters:
91 struct.AddField(param.name, param.kind, param.ordinal,
92 attributes=param.attributes)
93 _AddStructComputedData(False, struct)
94 return struct
95
96 def _GetResponseStructFromMethod(method):
97 """Converts a method's response_parameters into the fields of a struct."""
98 params_class = "%s_%s_ResponseParams" % (method.interface.name, method.name)
99 struct = mojom.Struct(params_class, module=method.interface.module)
100 for param in method.response_parameters:
101 struct.AddField(param.name, param.kind, param.ordinal,
102 attributes=param.attributes)
103 _AddStructComputedData(False, struct)
104 return struct
105
106 for struct in module.structs:
107 _AddStructComputedData(True, struct)
108 for union in module.unions:
109 _AddUnionComputedData(union)
110 for interface in module.interfaces:
111 _AddInterfaceComputedData(interface)
112
113
36 class Generator(object): 114 class Generator(object):
37 # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all 115 # Pass |output_dir| to emit files to disk. Omit |output_dir| to echo all
38 # files to stdout. 116 # files to stdout.
39 def __init__(self, module, output_dir=None, typemap=None, variant=None, 117 def __init__(self, module, output_dir=None, typemap=None, variant=None,
40 bytecode_path=None, for_blink=False, use_once_callback=False, 118 bytecode_path=None, for_blink=False, use_once_callback=False,
41 use_new_js_bindings=False, export_attribute=None, 119 use_new_js_bindings=False, export_attribute=None,
42 export_header=None, generate_non_variant_code=False): 120 export_header=None, generate_non_variant_code=False):
43 self.module = module 121 self.module = module
44 self.output_dir = output_dir 122 self.output_dir = output_dir
45 self.typemap = typemap or {} 123 self.typemap = typemap or {}
46 self.variant = variant 124 self.variant = variant
47 self.bytecode_path = bytecode_path 125 self.bytecode_path = bytecode_path
48 self.for_blink = for_blink 126 self.for_blink = for_blink
49 self.use_once_callback = use_once_callback 127 self.use_once_callback = use_once_callback
50 self.use_new_js_bindings = use_new_js_bindings 128 self.use_new_js_bindings = use_new_js_bindings
51 self.export_attribute = export_attribute 129 self.export_attribute = export_attribute
52 self.export_header = export_header 130 self.export_header = export_header
53 self.generate_non_variant_code = generate_non_variant_code 131 self.generate_non_variant_code = generate_non_variant_code
54 132
55 def GetStructsFromMethods(self):
56 result = []
57 for interface in self.module.interfaces:
58 for method in interface.methods:
59 result.append(self._GetStructFromMethod(method))
60 if method.response_parameters != None:
61 result.append(self._GetResponseStructFromMethod(method))
62 return result
63
64 def GetStructs(self):
65 return map(partial(self._AddStructComputedData, True), self.module.structs)
66
67 def GetUnions(self):
68 return map(self._AddUnionComputedData, self.module.unions)
69
70 def GetInterfaces(self):
71 return map(self._AddInterfaceComputedData, self.module.interfaces)
72
73 # Prepend the filename with a directory that matches the directory of the 133 # Prepend the filename with a directory that matches the directory of the
74 # original .mojom file, relative to the import root. 134 # original .mojom file, relative to the import root.
75 def MatchMojomFilePath(self, filename): 135 def MatchMojomFilePath(self, filename):
76 return os.path.join(os.path.dirname(self.module.path), filename) 136 return os.path.join(os.path.dirname(self.module.path), filename)
77 137
78 def Write(self, contents, filename): 138 def Write(self, contents, filename):
79 if self.output_dir is None: 139 if self.output_dir is None:
80 print contents 140 print contents
81 return 141 return
82 full_path = os.path.join(self.output_dir, filename) 142 full_path = os.path.join(self.output_dir, filename)
83 WriteFile(contents, full_path) 143 WriteFile(contents, full_path)
84 144
85 def GenerateFiles(self, args): 145 def GenerateFiles(self, args):
86 raise NotImplementedError("Subclasses must override/implement this method") 146 raise NotImplementedError("Subclasses must override/implement this method")
87 147
88 def GetJinjaParameters(self): 148 def GetJinjaParameters(self):
89 """Returns default constructor parameters for the jinja environment.""" 149 """Returns default constructor parameters for the jinja environment."""
90 return {} 150 return {}
91 151
92 def GetGlobals(self): 152 def GetGlobals(self):
93 """Returns global mappings for the template generation.""" 153 """Returns global mappings for the template generation."""
94 return {} 154 return {}
95 155
96 def _AddStructComputedData(self, exported, struct):
97 """Adds computed data to the given struct. The data is computed once and
98 used repeatedly in the generation process."""
99 struct.packed = pack.PackedStruct(struct)
100 struct.bytes = pack.GetByteLayout(struct.packed)
101 struct.versions = pack.GetVersionInfo(struct.packed)
102 struct.exported = exported
103 return struct
104
105 def _AddUnionComputedData(self, union):
106 """Adds computed data to the given union. The data is computed once and
107 used repeatedly in the generation process."""
108 ordinal = 0
109 for field in union.fields:
110 if field.ordinal is not None:
111 ordinal = field.ordinal
112 field.ordinal = ordinal
113 ordinal += 1
114 return union
115
116 def _AddInterfaceComputedData(self, interface):
117 """Adds computed data to the given interface. The data is computed once and
118 used repeatedly in the generation process."""
119 interface.version = 0
120 for method in interface.methods:
121 if method.min_version is not None:
122 interface.version = max(interface.version, method.min_version)
123
124 method.param_struct = self._GetStructFromMethod(method)
125 interface.version = max(interface.version,
126 method.param_struct.versions[-1].version)
127
128 if method.response_parameters is not None:
129 method.response_param_struct = self._GetResponseStructFromMethod(method)
130 interface.version = max(
131 interface.version,
132 method.response_param_struct.versions[-1].version)
133 else:
134 method.response_param_struct = None
135 return interface
136
137 def _GetStructFromMethod(self, method):
138 """Converts a method's parameters into the fields of a struct."""
139 params_class = "%s_%s_Params" % (method.interface.name, method.name)
140 struct = mojom.Struct(params_class, module=method.interface.module)
141 for param in method.parameters:
142 struct.AddField(param.name, param.kind, param.ordinal,
143 attributes=param.attributes)
144 return self._AddStructComputedData(False, struct)
145
146 def _GetResponseStructFromMethod(self, method):
147 """Converts a method's response_parameters into the fields of a struct."""
148 params_class = "%s_%s_ResponseParams" % (method.interface.name, method.name)
149 struct = mojom.Struct(params_class, module=method.interface.module)
150 for param in method.response_parameters:
151 struct.AddField(param.name, param.kind, param.ordinal,
152 attributes=param.attributes)
153 return self._AddStructComputedData(False, struct)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698