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 # insert '_' between anything and a Title name (e.g, HTTPEntry2FooBar -> | |
41 # HTTP_Entry2_FooBar) | |
42 name = re.sub('([^_])([A-Z][^A-Z_]+)', r'\1_\2', name) | |
43 # insert '_' between non upper and start of upper blocks (e.g., | |
44 # HTTP_Entry2_FooBar -> HTTP_Entry2_Foo_Bar) | |
45 name = re.sub('([^A-Z_])([A-Z])', r'\1_\2', name) | |
46 return [x.lower() for x in name.split('_')] | |
47 | |
48 def CapitalizeFirst(string): | |
49 return string[0].upper() + string[1:] | |
50 | |
51 def UpperCamelCase(name): | |
52 return ''.join([CapitalizeFirst(x) for x in NameToComponent(name)]) | |
53 | |
54 def CamelCase(name): | |
55 uccc = UpperCamelCase(name) | |
56 return uccc[0].lower() + uccc[1:] | |
57 | |
58 def ConstantStyle(name): | |
59 components = NameToComponent(name) | |
60 if components[0] == 'k': | |
61 components = components[1:] | |
62 return '_'.join([x.upper() for x in components]) | |
63 | |
64 def GetNameForElement(element): | |
65 if (isinstance(element, mojom.Enum) or | |
66 isinstance(element, mojom.Interface) or | |
67 isinstance(element, mojom.Struct)): | |
68 return UpperCamelCase(element.name) | |
69 if (isinstance(element, mojom.Method) or | |
70 isinstance(element, mojom.Parameter) or | |
71 isinstance(element, mojom.Field)): | |
72 return CamelCase(element.name) | |
73 if isinstance(element, mojom.EnumValue): | |
74 return (UpperCamelCase(element.enum_name) + '.' + | |
75 ConstantStyle(element.name)) | |
76 if (isinstance(element, mojom.NamedValue) or | |
77 isinstance(element, mojom.Constant)): | |
78 return ConstantStyle(element.name) | |
79 raise Exception("Unexpected element: " % element) | |
80 | |
81 def GetPackage(module): | |
82 if 'JavaPackage' in module.attributes: | |
83 package = module.attributes['JavaPackage'] | |
84 if isinstance(package, basestring): | |
85 return package | |
86 assert package[0] == 'EXPRESSION' | |
87 assert len(package[1]) == 1 | |
88 return package[1][0][1:-1].encode('string_escape') | |
89 # Default package. | |
90 return "org.chromium.mojom." + module.namespace | |
91 | |
92 def GetNameForKind(kind): | |
93 def _GetNameHierachy(kind): | |
94 hierachy = [] | |
95 if kind.parent_kind: | |
96 hierachy = _GetNameHierachy(kind.parent_kind) | |
97 hierachy.append(kind.name) | |
98 return hierachy | |
99 | |
100 elements = [GetPackage(kind.module)] | |
101 elements += _GetNameHierachy(kind) | |
102 return '.'.join(elements) | |
103 | |
104 def GetJavaType(kind): | |
105 if isinstance(kind, (mojom.Struct, mojom.Interface)): | |
106 return GetNameForKind(kind) | |
107 if isinstance(kind, mojom.Array): | |
108 return "%s[]" % GetJavaType(kind.kind) | |
109 if isinstance(kind, mojom.Enum): | |
110 return "int" | |
111 return _spec_to_java_type[kind.spec] | |
112 | |
113 def TranslateConstants(token, module): | |
114 def _TranslateNamedValue(named_value): | |
115 entity_name = GetNameForElement(named_value) | |
116 if named_value.parent_kind: | |
117 return GetJavaType(named_value.parent_kind) + '.' + entity_name | |
118 # Handle the case where named_value is a module level constant: | |
119 if not isinstance(named_value, mojom.EnumValue): | |
120 entity_name = (GetConstantsMainEntityName(named_value.module) + '.' + | |
121 entity_name) | |
122 return GetPackage(named_value.module) + '.' + entity_name | |
123 | |
124 if isinstance(token, mojom.NamedValue): | |
125 return _TranslateNamedValue(token) | |
126 # Add Long suffix to all number literals. | |
127 if re.match('^[0-9]+$', token): | |
128 return token + 'L' | |
129 return token | |
130 | |
131 def ExpressionToText(value, module): | |
132 if value[0] != "EXPRESSION": | |
133 raise Exception("Expected EXPRESSION, got" + value) | |
134 return "".join(generator.ExpressionMapper(value, | |
135 lambda token: TranslateConstants(token, module))) | |
136 | |
137 def GetConstantsMainEntityFullyQualifiedName(module): | |
rmcilroy
2014/05/27 09:44:35
Remove please.
qsr
2014/05/27 10:01:50
Done.
| |
138 package = GetPackage(module) | |
139 return GetPackage(module) + '.' + GetConstantsMainEntityName(module) | |
140 | |
141 def GetConstantsMainEntityName(module): | |
142 # This constructs the name of the embedding classes for module level constants | |
143 # by extracting the mojom's filename and prepending it to Constants. | |
144 return (UpperCamelCase(module.path.split('/')[-1].rsplit('.', 1)[0]) + | |
145 'Constants') | |
146 | |
147 class Generator(generator.Generator): | |
148 | |
149 java_filters = { | |
150 "expression_to_text": ExpressionToText, | |
151 "java_type": GetJavaType, | |
152 "name": GetNameForElement, | |
153 "verify_token_type": generator.VerifyTokenType, | |
154 } | |
155 | |
156 def GetJinjaExports(self): | |
157 return { | |
158 "module": self.module, | |
159 "package": GetPackage(self.module), | |
160 } | |
161 | |
162 @UseJinja("java_templates/constants.java.tmpl", filters=java_filters, | |
163 lstrip_blocks=True, trim_blocks=True) | |
164 def GenerateConstantsSource(self, module): | |
165 exports = self.GetJinjaExports() | |
166 exports.update({"main_entity": GetConstantsMainEntityName(module), | |
167 "constants": module.constants}) | |
168 return exports | |
169 | |
170 def GenerateFiles(self, unparsed_args): | |
171 parser = argparse.ArgumentParser() | |
172 parser.add_argument("--java_output_directory", dest="java_output_directory") | |
173 args = parser.parse_args(unparsed_args) | |
174 if self.output_dir and args.java_output_directory: | |
175 self.output_dir = os.path.join(args.java_output_directory, | |
176 GetPackage(self.module).replace('.', '/')) | |
177 if not os.path.exists(self.output_dir): | |
178 os.makedirs(self.output_dir) | |
179 | |
180 if self.module.constants: | |
181 self.Write(self.GenerateConstantsSource(self.module), | |
182 "%s.java" % GetConstantsMainEntityName(self.module)) | |
OLD | NEW |