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

Side by Side Diff: mojo/public/tools/bindings/generators/mojom_java_generator.py

Issue 291903003: Generate java bindings for constants. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add private constructor to constants class. Created 6 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
(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 """Generates java source files from a mojom.Module."""
6
7 import argparse
8 import os
9
10 import mojom.generate.generator as generator
11 import mojom.generate.module as mojom
12 import mojom.generate.pack as pack
13 from mojom.generate.template_expander import UseJinja
14
15
16 GENERATOR_PREFIX = 'java'
rmcilroy 2014/05/25 22:55:10 Is this needed - it doesn't seem to be referenced.
qsr 2014/05/26 08:41:20 It is used by mojo/public/tools/bindings/mojom_bin
17
18 _HEADER_SIZE = 8
19
20 _spec_to_java_type = {
21 'b': "boolean",
22 'd': "double",
23 'f': "float",
24 'h:d:c': "org.chromium.mojo.system.DataPipe.ConsumerHandle",
25 'h:d:p': "org.chromium.mojo.system.DataPipe.ProducerHandle",
26 'h:m': "org.chromium.mojo.system.MessagePipeHandle",
27 'h': "org.chromium.mojo.system.UntypedHandle",
28 'h:s': "org.chromium.mojo.system.SharedBufferHandle",
29 'i16': "short",
30 'i32': "int",
31 'i64': "long",
32 'i8': "byte",
33 's': "String",
34 'u16': "short",
35 'u32': "int",
36 'u64': "long",
37 'u8': "byte",
38 }
39
40 _spec_to_decode_method = {
41 'b': "readBoolean",
42 'd': "readDouble",
43 'f': "readFloat",
44 'h:d:c': "readConsumerHandle",
45 'h:d:p': "readProducerHandle",
46 'h:m': "readMessagePipeHandle",
47 'h': "readUntypedHandle",
48 'h:s': "readSharedBufferHandle",
49 'i16': "readShort",
50 'i32': "readInt",
51 'i64': "readLong",
52 'i8': "readByte",
53 's': "readString",
54 'u16': "readShort",
55 'u32': "readInt",
56 'u64': "readLong",
57 'u8': "readByte",
58 }
59
60
61 def DecodeMethod(kind):
62 if isinstance(kind, mojom.Array):
63 return DecodeMethod(kind.kind) + 's'
64 if isinstance(kind, mojom.Enum):
65 return DecodeMethod(mojom.INT32)
66 if isinstance(kind, mojom.Interface):
67 return "readServiceInterface"
68 return _spec_to_decode_method[kind.spec]
69
70 def NamespaceToArray(namespace):
rmcilroy 2014/05/25 22:55:10 I think this should be called PackageToArray(packa
qsr 2014/05/26 08:41:20 Removed.
71 return namespace.split('.')
72
73 def GetNameFromString(string):
rmcilroy 2014/05/25 22:55:10 I would call this "UpperCamelCase" and move it wit
qsr 2014/05/26 08:41:20 Refactored naming function. This method doesn't ex
74 return CapitalizeFirst(CamelCase(string))
75
76 def GetName(kind):
rmcilroy 2014/05/25 22:55:10 I would get rid of this method - the name is confu
qsr 2014/05/26 08:41:20 Done.
77 return GetNameFromString(kind.name)
78
79 def GetPackage(module):
80 if 'JavaPackage' in module.attributes:
81 package = module.attributes['JavaPackage']
82 if isinstance(package, basestring):
83 return package
84 assert package[0] == 'EXPRESSION'
rmcilroy 2014/05/25 22:55:10 It's probably clearer to include "else" branches e
qsr 2014/05/26 08:41:20 That's not the style other python file use. Revers
85 assert len(package[1]) == 1
86 return package[1][0][1:-1].encode('string_escape')
87 return "org.chromium.mojom." + module.namespace
88
89 def GetSuperClass(method):
90 if method:
91 if method.response_parameters:
92 return "org.chromium.mojo.bindings.MessageWithRequestId"
93 return "org.chromium.mojo.bindings.Message"
94 return "org.chromium.mojo.bindings.Struct"
rmcilroy 2014/05/25 22:55:10 I think this would be clearer as: if not method:
qsr 2014/05/26 08:41:20 Method removed until further CL.
95
96 def GetFlags(method, is_parameter):
rmcilroy 2014/05/25 22:55:10 Could you remove this until it's used in a later C
qsr 2014/05/26 08:41:20 Done.
97 if method.response_parameters:
98 if is_parameter:
99 return "MESSAGE_EXPECTS_RESPONSE_FLAG"
100 return "MESSAGE_IS_RESPONSE_FLAG"
101 return "0"
102
103 def NewArray(kind, size):
rmcilroy 2014/05/25 22:55:10 nit - move below GetMethodName
qsr 2014/05/26 08:41:20 Removed.
104 if isinstance(kind.kind, mojom.Array):
105 return NewArray(kind.kind, size) + '[]'
106 return 'new %s[%s]' % (GetJavaType(kind.kind), size)
107
108 def GetNameHierachy(kind):
rmcilroy 2014/05/25 22:55:10 Could you make GetNameHierarchy an inner function
qsr 2014/05/26 08:41:20 Done.
109 hierachy = []
110 if kind.parent_kind:
111 hierachy = GetNameHierachy(kind.parent_kind)
112 hierachy.append(kind.name)
113 return hierachy
114
115 def GetNameForKind(kind):
116 elements = [GetPackage(kind.module)]
117 elements += GetNameHierachy(kind)
118 return '.'.join(elements)
119
120 def GetJavaGetterPrefix(kind):
121 if kind == mojom.BOOL:
122 return "is"
123 return "get"
124
125 def GetJavaType(kind):
126 if isinstance(kind, mojom.Struct):
127 return GetNameForKind(kind)
128 if isinstance(kind, mojom.Array):
129 return "%s[]" % GetJavaType(kind.kind)
130 if isinstance(kind, mojom.Interface):
131 return "org.chromium.mojo.bindings.ServiceHandle<%s>" % GetNameForKind(kind)
132 if isinstance(kind, mojom.Enum):
133 return "int"
134 return _spec_to_java_type[kind.spec]
135
136 def TranslateConstants(token, module):
137 if isinstance(token, (mojom.NamedValue, mojom.EnumValue)):
138 if isinstance(token, mojom.EnumValue):
139 entity_value = token.enum_name + '.' + token.name
140 else:
141 entity_value = ConstantName(token)
142 if not token.parent_kind:
143 entity_value = (GetConstantsMainEntityName(token.module) +
144 '.' + entity_value)
145 if token.parent_kind:
146 return GetJavaType(token.parent_kind) + '.' + entity_value
147 return GetPackage(token.module) + '.' + entity_value
rmcilroy 2014/05/25 22:55:10 Could you please reduce this method to the bare mi
qsr 2014/05/26 08:41:20 This is mostly the bare minimum. A constant can re
148 return token
149
150 def ExpressionToText(value, module):
rmcilroy 2014/05/25 22:55:10 This looks the same as the method in the CPP bindi
qsr 2014/05/26 08:41:20 We can do this in a further CL if you do not mind.
rmcilroy 2014/05/26 11:13:48 Doing this in a separate cl is fine. BTW, I was on
151 if value[0] != "EXPRESSION":
152 raise Exception("Expected EXPRESSION, got" + value)
153 return "".join(generator.ExpressionMapper(value,
154 lambda token: TranslateConstants(token, module)))
155
156 def CapitalizeFirst(string):
157 return string[0].upper() + string[1:]
158
159 def CamelCase(string):
160 elements = string.split('_')
161 return elements[0] + ''.join([x.capitalize() for x in elements[1:]])
162
163 def UpperCaseConstant(name):
164 def _IsCut(i):
165 if i == 0 or i == len(name):
166 return True
167 if name[i].islower():
168 return False
169 if name[i-1].isupper() and (i == len(name) -1 or name[i+1].isupper()):
170 return False
171 return True
172 pos = [i for i in xrange(len(name) + 1) if _IsCut(i)]
173 parts = [name[pos[j]:pos[j+1]] for j in xrange(len(pos)-1)]
174 return '_'.join([x.upper() for x in parts])
rmcilroy 2014/05/25 22:55:10 I think you could do this more easily with a regex
qsr 2014/05/26 08:41:20 This has been completely refactored.
175
176 def DefaultValueConstant(field):
177 return 'DEFAULT_' + UpperCaseConstant(GetName(field))
rmcilroy 2014/05/25 22:55:10 Please remove this until the CL where it is used.
qsr 2014/05/26 08:41:20 Done.
178
179 def FieldName(field):
180 return 'm' + GetName(field)
181
182 def ConstantName(constant):
183 main_name = constant.name
184 if main_name[0] == 'k':
185 main_name = main_name[1:]
186 return UpperCaseConstant(main_name)
187
188 def IsPointerArrayKind(kind):
rmcilroy 2014/05/25 22:55:10 Please remove IsPointerArrayKind, GetResponseStruc
qsr 2014/05/26 08:41:20 Done.
189 if not isinstance(kind, mojom.Array):
190 return False
191 sub_kind = kind.kind
192 return generator.IsObjectKind(sub_kind)
193
194 def GetResponseStructFromMethod(method):
195 return generator.GetDataHeader(
196 False, generator.GetResponseStructFromMethod(method))
197
198 def GetStructFromMethod(method):
199 return generator.GetDataHeader(
200 False, generator.GetStructFromMethod(method))
201
202 def GetMethodName(method):
203 return (UpperCaseConstant(method.interface.name) + "_" +
204 UpperCaseConstant(method.name) + "_NAME")
205
206 def GetConstantsMainEntityFullyQualifiedName(module):
rmcilroy 2014/05/25 22:55:10 This doesn't seem to be used - can it be removed (
qsr 2014/05/26 08:41:20 This is now used.
207 package = GetPackage(module)
208 return GetPackage(module) + '.' + GetConstantsMainEntityName(module)
209
210 def GetConstantsMainEntityName(module):
211 return (GetNameFromString(module.path.split('/')[-1].rsplit('.', 1)[0]) +
rmcilroy 2014/05/25 22:55:10 Please add a comment describing that this is build
qsr 2014/05/26 08:41:20 Added the comment. I'd rather do the annotation in
212 'Constants')
213
214 class Generator(generator.Generator):
215
216 java_filters = {
217 "camelcase": CamelCase,
218 "capitalize_first": CapitalizeFirst,
219 "default_value_constant": DefaultValueConstant,
220 "decode_method": DecodeMethod,
221 "expression_to_text": ExpressionToText,
222 "field_name": FieldName,
223 "flags": GetFlags,
224 "is_bool": lambda kind: kind == mojom.BOOL,
225 "is_array_kind": lambda kind: isinstance(kind, mojom.Array),
226 "is_object_kind": generator.IsObjectKind,
227 "is_pointer_array_kind": IsPointerArrayKind,
228 "is_string_kind": generator.IsStringKind,
229 "is_struct_kind": lambda kind: isinstance(kind, mojom.Struct),
230 "java_getter_prefix": GetJavaGetterPrefix,
231 "java_type": GetJavaType,
232 "method_name": GetMethodName,
233 "new_array": NewArray,
234 "response_struct_from_method": GetResponseStructFromMethod,
235 "struct_from_method": GetStructFromMethod,
236 "struct_size": lambda ps: ps.GetTotalSize() + _HEADER_SIZE,
237 "super_class": GetSuperClass,
238 "constant_name": ConstantName,
239 "verify_token_type": generator.VerifyTokenType,
240 }
241
242 def GetJinjaExports(self):
243 return {
244 "interfaces": self.module.interfaces,
245 "kinds": self.module.kinds,
246 "method_structs": self.GetStructsFromMethods(),
rmcilroy 2014/05/25 22:55:10 I can't see any uses of "method_structs" either he
qsr 2014/05/26 08:41:20 Done.
247 "module": self.module,
248 "namespace": self.module.namespace,
249 "package": GetPackage(self.module),
250 }
251
252 @UseJinja("java_templates/constants.java.tmpl", filters=java_filters,
253 lstrip_blocks=True, trim_blocks=True)
254 def GenerateConstantsSource(self, module):
255 exports = self.GetJinjaExports()
256 exports.update({"main_entity": GetConstantsMainEntityName(module),
257 "constants": module.constants})
258 return exports
259
260 def GenerateFiles(self, unparsed_args):
261 parser = argparse.ArgumentParser()
262 parser.add_argument("--java_output_directory", dest="java_output_directory")
263 args = parser.parse_args(unparsed_args)
264 if self.output_dir and args.java_output_directory:
265 self.output_dir = os.path.join(args.java_output_directory,
266 GetPackage(self.module).replace('.', '/'))
267 if not os.path.exists(self.output_dir):
268 os.makedirs(self.output_dir)
269
270 if self.module.constants:
271 self.Write(self.GenerateConstantsSource(self.module),
272 "%s.java" % GetConstantsMainEntityName(self.module))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698