OLD | NEW |
---|---|
(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 import re | |
10 | |
11 import mojom.generate.generator as generator | |
12 import mojom.generate.module as mojom | |
13 from mojom.generate.template_expander import UseJinja | |
14 | |
15 | |
16 GENERATOR_PREFIX = 'java' | |
17 | |
18 _spec_to_java_type = { | |
19 'b': 'boolean', | |
20 'd': 'double', | |
21 'f': 'float', | |
22 'h:d:c': 'org.chromium.mojo.system.DataPipe.ConsumerHandle', | |
23 'h:d:p': 'org.chromium.mojo.system.DataPipe.ProducerHandle', | |
24 'h:m': 'org.chromium.mojo.system.MessagePipeHandle', | |
25 'h': 'org.chromium.mojo.system.UntypedHandle', | |
26 'h:s': 'org.chromium.mojo.system.SharedBufferHandle', | |
27 'i16': 'short', | |
28 'i32': 'int', | |
29 'i64': 'long', | |
30 'i8': 'byte', | |
31 's': 'String', | |
32 'u16': 'short', | |
33 'u32': 'int', | |
34 'u64': 'long', | |
35 'u8': 'byte', | |
36 } | |
37 | |
38 | |
39 def NameToComponent(name): | |
40 def _IsCut(i): | |
41 if i == 0 or i == len(name): | |
42 return True | |
43 if name[i].islower(): | |
44 return False | |
45 if name[i-1].isupper() and (i == len(name) -1 or name[i+1].isupper()): | |
46 return False | |
47 return True | |
rmcilroy
2014/05/26 11:13:48
How about using the regex's I suggested in the las
qsr
2014/05/26 12:05:42
Done, but I do not find that clearer. Also didn't
| |
48 if '_' in name: | |
49 return [item for sublist in [NameToComponent(y) for y in name.split('_')] | |
50 for item in sublist] | |
51 pos = [i for i in xrange(len(name) + 1) if _IsCut(i)] | |
52 return [name[pos[j]:pos[j+1]].lower() for j in xrange(len(pos)-1)] | |
53 | |
54 def CapitalizeFirst(string): | |
55 return string[0].upper() + string[1:] | |
56 | |
57 def UpperCamelCase(name): | |
58 return ''.join([CapitalizeFirst(x) for x in NameToComponent(name)]) | |
59 | |
60 def CamelCase(name): | |
61 uccc = UpperCamelCase(name) | |
62 return uccc[0].lower() + uccc[1:] | |
63 | |
64 def UpperCaseHackerStyle(name): | |
rmcilroy
2014/05/26 11:13:48
I've never heard of hacker style and can't find it
qsr
2014/05/26 12:05:42
Done. Don't remember where I found it was called h
| |
65 components = NameToComponent(name) | |
66 if components[0] == 'k': | |
67 components = components[1:] | |
68 return '_'.join([x.upper() for x in components]) | |
69 | |
70 def GetNameForElement(element): | |
71 if (isinstance(element, mojom.Enum) or | |
72 isinstance(element, mojom.Interface) or | |
73 isinstance(element, mojom.Struct)): | |
74 return UpperCamelCase(element.name) | |
75 if (isinstance(element, mojom.Method) or | |
76 isinstance(element, mojom.Parameter) or | |
77 isinstance(element, mojom.Field)): | |
78 return CamelCase(element.name) | |
79 if isinstance(element, mojom.EnumValue): | |
80 return (UpperCamelCase(element.enum_name) + '.' + | |
81 UpperCaseHackerStyle(element.name)) | |
82 if (isinstance(element, mojom.NamedValue) or | |
83 isinstance(element, mojom.Constant)): | |
84 return UpperCaseHackerStyle(element.name) | |
85 raise Exception("Unexpected element: " % element) | |
86 | |
87 def GetPackage(module): | |
88 if 'JavaPackage' not in module.attributes: | |
rmcilroy
2014/05/26 11:13:48
In the case of this function, I still think if/els
qsr
2014/05/26 12:05:42
Move the conditional back. But I really don't like
rmcilroy
2014/05/27 09:44:34
OK, we disagree on this, but I'm not going to bike
| |
89 return "org.chromium.mojom." + module.namespace | |
90 package = module.attributes['JavaPackage'] | |
91 if isinstance(package, basestring): | |
92 return package | |
93 assert package[0] == 'EXPRESSION' | |
94 assert len(package[1]) == 1 | |
95 return package[1][0][1:-1].encode('string_escape') | |
96 | |
97 def GetNameForKind(kind): | |
98 def _GetNameHierachy(kind): | |
99 hierachy = [] | |
100 if kind.parent_kind: | |
101 hierachy = _GetNameHierachy(kind.parent_kind) | |
102 hierachy.append(kind.name) | |
103 return hierachy | |
104 | |
105 elements = [GetPackage(kind.module)] | |
106 elements += _GetNameHierachy(kind) | |
107 return '.'.join(elements) | |
108 | |
109 def GetJavaType(kind): | |
110 if isinstance(kind, (mojom.Struct, mojom.Interface)): | |
111 return GetNameForKind(kind) | |
112 if isinstance(kind, mojom.Array): | |
113 return "%s[]" % GetJavaType(kind.kind) | |
114 if isinstance(kind, mojom.Enum): | |
115 return "int" | |
116 return _spec_to_java_type[kind.spec] | |
117 | |
118 def TranslateConstants(token, module): | |
119 def _TranslateNamedValue(named_value): | |
120 entity_value = GetNameForElement(named_value) | |
rmcilroy
2014/05/26 11:13:48
/s/entity_value/entity_name I think.
qsr
2014/05/26 12:05:42
Done.
| |
121 # Handle the case where named_value is a module level constant: | |
122 if (not isinstance(named_value, mojom.EnumValue) and | |
rmcilroy
2014/05/26 11:13:48
This seems a bit confusing to me, how about:
if n
qsr
2014/05/26 12:05:42
I still think the else after a return is not in an
rmcilroy
2014/05/27 09:44:34
Ok, this looks better, thanks.
| |
123 not named_value.parent_kind): | |
124 return (GetConstantsMainEntityFullyQualifiedName(named_value.module) + | |
125 '.'+ entity_value) | |
126 if named_value.parent_kind: | |
127 return GetJavaType(named_value.parent_kind) + '.' + entity_value | |
128 return GetPackage(named_value.module) + '.' + entity_value | |
129 | |
130 if isinstance(token, mojom.NamedValue): | |
131 return _TranslateNamedValue(token) | |
132 if re.match('^[0-9]+$', token): | |
rmcilroy
2014/05/26 11:13:48
Comment that you add Long suffix to all number lit
qsr
2014/05/26 12:05:42
Done.
| |
133 return token + 'L' | |
134 return token | |
135 | |
136 def ExpressionToText(value, module): | |
137 if value[0] != "EXPRESSION": | |
138 raise Exception("Expected EXPRESSION, got" + value) | |
139 return "".join(generator.ExpressionMapper(value, | |
140 lambda token: TranslateConstants(token, module))) | |
141 | |
142 def GetConstantsMainEntityFullyQualifiedName(module): | |
143 package = GetPackage(module) | |
144 return GetPackage(module) + '.' + GetConstantsMainEntityName(module) | |
145 | |
146 def GetConstantsMainEntityName(module): | |
147 # This constructs the name of the embedding classes for module level constants | |
148 # by extracting the mojom's filename and prepending it to Constants. | |
149 return (UpperCamelCase(module.path.split('/')[-1].rsplit('.', 1)[0]) + | |
150 'Constants') | |
151 | |
152 class Generator(generator.Generator): | |
153 | |
154 java_filters = { | |
155 "expression_to_text": ExpressionToText, | |
156 "java_type": GetJavaType, | |
157 "name": GetNameForElement, | |
158 "verify_token_type": generator.VerifyTokenType, | |
159 } | |
160 | |
161 def GetJinjaExports(self): | |
162 return { | |
163 "module": self.module, | |
164 "package": GetPackage(self.module), | |
165 } | |
166 | |
167 @UseJinja("java_templates/constants.java.tmpl", filters=java_filters, | |
168 lstrip_blocks=True, trim_blocks=True) | |
169 def GenerateConstantsSource(self, module): | |
170 exports = self.GetJinjaExports() | |
171 exports.update({"main_entity": GetConstantsMainEntityName(module), | |
172 "constants": module.constants}) | |
173 return exports | |
174 | |
175 def GenerateFiles(self, unparsed_args): | |
176 parser = argparse.ArgumentParser() | |
177 parser.add_argument("--java_output_directory", dest="java_output_directory") | |
178 args = parser.parse_args(unparsed_args) | |
179 if self.output_dir and args.java_output_directory: | |
180 self.output_dir = os.path.join(args.java_output_directory, | |
181 GetPackage(self.module).replace('.', '/')) | |
182 if not os.path.exists(self.output_dir): | |
183 os.makedirs(self.output_dir) | |
184 | |
185 if self.module.constants: | |
186 self.Write(self.GenerateConstantsSource(self.module), | |
187 "%s.java" % GetConstantsMainEntityName(self.module)) | |
OLD | NEW |