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

Side by Side Diff: tools/json_schema_compiler/compiler.py

Issue 12041098: Initial commit of the Dart Chrome Extension APIs generators (Closed) Base URL: http://git.chromium.org/chromium/src.git@file_path_bugfix
Patch Set: Created 7 years, 10 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 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 """Generator for C++ structs from api json files. 5 """Generator for C++ structs from api json files.
6 6
7 The purpose of this tool is to remove the need for hand-written code that 7 The purpose of this tool is to remove the need for hand-written code that
8 converts to and from base::Value types when receiving javascript api calls. 8 converts to and from base::Value types when receiving javascript api calls.
9 Originally written for generating code for extension apis. Reference schemas 9 Originally written for generating code for extension apis. Reference schemas
10 are in chrome/common/extensions/api. 10 are in chrome/common/extensions/api.
11 11
12 Usage example: 12 Usage example:
13 compiler.py --root /home/Work/src --namespace extensions windows.json 13 compiler.py --root /home/Work/src --namespace extensions windows.json
14 tabs.json 14 tabs.json
15 compiler.py --destdir gen --root /home/Work/src 15 compiler.py --destdir gen --root /home/Work/src
16 --namespace extensions windows.json tabs.json 16 --namespace extensions windows.json tabs.json
17 """ 17 """
18 18
19 import cc_generator 19 import cc_generator
20 import cpp_type_generator 20 import cpp_type_generator
21 import h_generator 21 import h_generator
22 import dart_generator
22 import idl_schema 23 import idl_schema
23 import json_schema 24 import json_schema
24 import model 25 import model
25 import schema_bundle_generator 26 import schema_bundle_generator
26 27
27 import optparse 28 import optparse
28 import os.path 29 import os.path
29 import sys 30 import sys
30 31
32 # list of supported languages to build; first is default
33 SUPPORTED_LANGS = ['c++', 'dart']
34
31 def load_schema(schema): 35 def load_schema(schema):
32 schema_filename, schema_extension = os.path.splitext(schema) 36 schema_filename, schema_extension = os.path.splitext(schema)
33 37
34 if schema_extension == '.json': 38 if schema_extension == '.json':
35 api_defs = json_schema.Load(schema) 39 api_defs = json_schema.Load(schema)
36 elif schema_extension == '.idl': 40 elif schema_extension == '.idl':
37 api_defs = idl_schema.Load(schema) 41 api_defs = idl_schema.Load(schema)
38 else: 42 else:
39 sys.exit("Did not recognize file extension %s for schema %s" % 43 sys.exit("Did not recognize file extension %s for schema %s" %
40 (schema_extension, schema)) 44 (schema_extension, schema))
41 if len(api_defs) != 1: 45 if len(api_defs) != 1:
42 sys.exit("File %s has multiple schemas. Files are only allowed to contain a" 46 sys.exit("File %s has multiple schemas. Files are only allowed to contain a"
43 " single schema." % schema) 47 " single schema." % schema)
44 48
45 return api_defs 49 return api_defs
46 50
47 def handle_single_schema(filename, dest_dir, root, root_namespace): 51 def handle_single_schema(filename, dest_dir, root, root_namespace, lang,
52 hooks_file):
48 schema = os.path.normpath(filename) 53 schema = os.path.normpath(filename)
49 schema_filename, schema_extension = os.path.splitext(schema) 54 schema_filename, schema_extension = os.path.splitext(schema)
50 path, short_filename = os.path.split(schema_filename) 55 path, short_filename = os.path.split(schema_filename)
51 api_defs = json_schema.DeleteNocompileNodes(load_schema(schema)) 56 api_defs = json_schema.DeleteNocompileNodes(load_schema(schema))
52 57
53 api_model = model.Model() 58 api_model = model.Model()
54 59
55 for target_namespace in api_defs: 60 for target_namespace in api_defs:
56 referenced_schemas = target_namespace.get('dependencies', []) 61 referenced_schemas = target_namespace.get('dependencies', [])
57 # Load type dependencies into the model. 62 # Load type dependencies into the model.
(...skipping 21 matching lines...) Expand all
79 if not namespace: 84 if not namespace:
80 continue 85 continue
81 86
82 if short_filename != namespace.unix_name: 87 if short_filename != namespace.unix_name:
83 sys.exit("Filename %s is illegal. Name files using unix_hacker style." % 88 sys.exit("Filename %s is illegal. Name files using unix_hacker style." %
84 filename) 89 filename)
85 90
86 # The output filename must match the input filename for gyp to deal with it 91 # The output filename must match the input filename for gyp to deal with it
87 # properly. 92 # properly.
88 out_file = namespace.unix_name 93 out_file = namespace.unix_name
89 type_generator = cpp_type_generator.CppTypeGenerator(
90 root_namespace, namespace, namespace.unix_name)
91 for referenced_namespace in api_model.namespaces.values():
92 if referenced_namespace == namespace:
93 continue
94 type_generator.AddNamespace(
95 referenced_namespace,
96 referenced_namespace.unix_name)
97 94
98 h_code = (h_generator.HGenerator(namespace, type_generator) 95 if lang.lower() == 'c++':
benwells 2013/01/25 03:15:32 I don't think this is needed now, but it would be
99 .Generate().Render()) 96 type_generator = cpp_type_generator.CppTypeGenerator(
100 cc_code = (cc_generator.CCGenerator(namespace, type_generator) 97 root_namespace, namespace, namespace.unix_name)
101 .Generate().Render()) 98 for referenced_namespace in api_model.namespaces.values():
99 if referenced_namespace == namespace:
100 continue
101 type_generator.AddNamespace(
102 referenced_namespace,
103 referenced_namespace.unix_name)
102 104
103 if dest_dir: 105 h_code = (h_generator.HGenerator(namespace, type_generator)
104 with open( 106 .Generate().Render())
105 os.path.join(dest_dir, namespace.source_file_dir, out_file + '.cc'), 107 cc_code = (cc_generator.CCGenerator(namespace, type_generator)
106 'w') as cc_file: 108 .Generate().Render())
107 cc_file.write(cc_code) 109
108 with open( 110 if dest_dir:
109 os.path.join(dest_dir, namespace.source_file_dir, out_file + '.h'), 111 with open(
110 'w') as h_file: 112 os.path.join(dest_dir, namespace.source_file_dir, out_file + '.cc'),
111 h_file.write(h_code) 113 'w') as cc_file:
114 cc_file.write(cc_code)
115 with open(
116 os.path.join(dest_dir, namespace.source_file_dir, out_file + '.h'),
117 'w') as h_file:
118 h_file.write(h_code)
119 else:
120 print '%s.h' % out_file
benwells 2013/01/25 03:15:32 You can factorize out the if dest_dir ... else: ..
121 print
122 print h_code
123 print
124 print '%s.cc' % out_file
125 print
126 print cc_code
127
128 elif lang.lower() == 'dart':
129 dart_code = (dart_generator.DartGenerator(namespace, hooks_file)
130 .Generate().Render())
131
132 if dest_dir:
133 with open(os.path.join(dest_dir, out_file + '.dart'), 'w') as dart_file:
134 dart_file.write(dart_code)
135 else:
136 print '%s.dart' % out_file
137 print
138 print dart_code
139
112 else: 140 else:
113 print '%s.h' % out_file 141 raise Exception("Unrecognised language %s. Supported languages are %s." %
114 print 142 (lang, SUPPORTED_LANGS))
115 print h_code
116 print
117 print '%s.cc' % out_file
118 print
119 print cc_code
120 143
121 def handle_bundle_schema(filenames, dest_dir, root, root_namespace): 144 def handle_bundle_schema(filenames, dest_dir, root, root_namespace, lang):
122 # Merge the source files into a single list of schemas. 145 # Merge the source files into a single list of schemas.
123 api_defs = [] 146 api_defs = []
124 for filename in filenames: 147 for filename in filenames:
125 schema = os.path.normpath(filename) 148 schema = os.path.normpath(filename)
126 schema_filename, schema_extension = os.path.splitext(schema) 149 schema_filename, schema_extension = os.path.splitext(schema)
127 api_defs.extend(load_schema(schema)) 150 api_defs.extend(load_schema(schema))
128 151
129 api_model = model.Model() 152 api_model = model.Model()
130 relpath = os.path.relpath(os.path.normpath(filenames[0]), root) 153 relpath = os.path.relpath(os.path.normpath(filenames[0]), root)
131 154
132 for target_namespace, schema_filename in zip(api_defs, filenames): 155 for target_namespace, schema_filename in zip(api_defs, filenames):
133 namespace = api_model.AddNamespace(target_namespace, relpath) 156 namespace = api_model.AddNamespace(target_namespace, relpath)
134 path, filename = os.path.split(schema_filename) 157 path, filename = os.path.split(schema_filename)
135 short_filename, extension = os.path.splitext(filename) 158 short_filename, extension = os.path.splitext(filename)
136 159
137 # Filenames are checked against the unix_names of the namespaces they 160 # Filenames are checked against the unix_names of the namespaces they
138 # generate because the gyp uses the names of the JSON files to generate 161 # generate because the gyp uses the names of the JSON files to generate
139 # the names of the .cc and .h files. We want these to be using unix_names. 162 # the names of the .cc and .h files. We want these to be using unix_names.
140 if namespace.unix_name != short_filename: 163 if namespace.unix_name != short_filename:
141 sys.exit("Filename %s is illegal. Name files using unix_hacker style." % 164 sys.exit("Filename %s is illegal. Name files using unix_hacker style." %
142 schema_filename) 165 schema_filename)
143 166
144 type_generator = cpp_type_generator.CppTypeGenerator(root_namespace) 167 if lang == "c++":
145 for referenced_namespace in api_model.namespaces.values(): 168 type_generator = cpp_type_generator.CppTypeGenerator(root_namespace)
146 type_generator.AddNamespace( 169 for referenced_namespace in api_model.namespaces.values():
147 referenced_namespace, 170 type_generator.AddNamespace(
148 referenced_namespace.unix_name) 171 referenced_namespace,
172 referenced_namespace.unix_name)
149 173
150 generator = schema_bundle_generator.SchemaBundleGenerator( 174 generator = schema_bundle_generator.SchemaBundleGenerator(
151 api_model, api_defs, type_generator) 175 api_model, api_defs, type_generator)
152 api_h_code = generator.GenerateAPIHeader().Render() 176 api_h_code = generator.GenerateAPIHeader().Render()
153 schemas_h_code = generator.GenerateSchemasHeader().Render() 177 schemas_h_code = generator.GenerateSchemasHeader().Render()
154 schemas_cc_code = generator.GenerateSchemasCC().Render() 178 schemas_cc_code = generator.GenerateSchemasCC().Render()
155 179
156 if dest_dir: 180 if dest_dir:
157 basedir = os.path.join(dest_dir, 'chrome/common/extensions/api') 181 basedir = os.path.join(dest_dir, 'chrome/common/extensions/api')
158 with open(os.path.join(basedir, 'generated_api.h'), 'w') as h_file: 182 with open(os.path.join(basedir, 'generated_api.h'), 'w') as h_file:
159 h_file.write(api_h_code) 183 h_file.write(api_h_code)
160 with open(os.path.join(basedir, 'generated_schemas.h'), 'w') as h_file: 184 with open(os.path.join(basedir, 'generated_schemas.h'), 'w') as h_file:
161 h_file.write(schemas_h_code) 185 h_file.write(schemas_h_code)
162 with open(os.path.join(basedir, 'generated_schemas.cc'), 'w') as cc_file: 186 with open(os.path.join(basedir, 'generated_schemas.cc'), 'w') as cc_file:
163 cc_file.write(schemas_cc_code) 187 cc_file.write(schemas_cc_code)
188 else:
189 print 'generated_api.h'
190 print
191 print api_h_code
192 print
193 print 'generated_schemas.h'
194 print
195 print schemas_h_code
196 print
197 print 'generated_schemas.cc'
198 print
199 print schemas_cc_code
200
201 elif lang == "dart":
202 raise Exception("Dart is not supported in bundle mode.")
203
164 else: 204 else:
165 print 'generated_api.h' 205 raise Exception("Unrecognised language %s. Supported languages are %s." %
166 print 206 (lang, SUPPORTED_LANGS))
167 print api_h_code 207
168 print
169 print 'generated_schemas.h'
170 print
171 print schemas_h_code
172 print
173 print 'generated_schemas.cc'
174 print
175 print schemas_cc_code
176 208
177 if __name__ == '__main__': 209 if __name__ == '__main__':
178 parser = optparse.OptionParser( 210 parser = optparse.OptionParser(
179 description='Generates a C++ model of an API from JSON schema', 211 description='Generates a C++ model of an API from JSON schema',
180 usage='usage: %prog [option]... schema') 212 usage='usage: %prog [option]... schema')
181 parser.add_option('-r', '--root', default='.', 213 parser.add_option('-r', '--root', default='.',
182 help='logical include root directory. Path to schema files from specified' 214 help='logical include root directory. Path to schema files from specified'
183 'dir will be the include path.') 215 'dir will be the include path.')
184 parser.add_option('-d', '--destdir', 216 parser.add_option('-d', '--destdir',
185 help='root directory to output generated files.') 217 help='root directory to output generated files.')
186 parser.add_option('-n', '--namespace', default='generated_api_schemas', 218 parser.add_option('-n', '--namespace', default='generated_api_schemas',
187 help='C++ namespace for generated files. e.g extensions::api.') 219 help='C++ namespace for generated files. e.g extensions::api.')
188 parser.add_option('-b', '--bundle', action="store_true", help= 220 parser.add_option('-b', '--bundle', action="store_true", help=
189 '''if supplied, causes compiler to generate bundle files for the given set of 221 '''if supplied, causes compiler to generate bundle files for the given set of
190 source files.''') 222 source files.''')
223 parser.add_option('-l', '--lang', default=SUPPORTED_LANGS[0],
224 help=
225 '''The language to generate the output in. Currently supported options are
226 %s.''' % SUPPORTED_LANGS)
227 parser.add_option("-H", "--hooks-file", dest="hooks_file",
benwells 2013/01/25 03:15:32 We should talk about custom hooks offline, I'm not
228 help="Adds custom hooks from the given file (Dart only).", metavar="FILE")
191 229
192 (opts, args) = parser.parse_args() 230 (opts, args) = parser.parse_args()
193 231
194 if not args: 232 if not args:
195 sys.exit(0) # This is OK as a no-op 233 sys.exit(0) # This is OK as a no-op
196 dest_dir = opts.destdir 234 dest_dir = opts.destdir
197 root_namespace = opts.namespace 235 root_namespace = opts.namespace
198 236
199 if opts.bundle: 237 if opts.bundle:
200 handle_bundle_schema(args, dest_dir, opts.root, root_namespace) 238 handle_bundle_schema(args, dest_dir, opts.root, root_namespace, opts.lang)
201 else: 239 else:
202 handle_single_schema(args[0], dest_dir, opts.root, root_namespace) 240 handle_single_schema(args[0], dest_dir, opts.root, root_namespace,
241 opts.lang, opts.hooks_file)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698