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

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

Issue 12320030: Revert 183709 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/json_schema_compiler/dart_generator_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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.
(...skipping 14 matching lines...) Expand all
25 import json_schema 25 import json_schema
26 26
27 import optparse 27 import optparse
28 import os.path 28 import os.path
29 import sys 29 import sys
30 30
31 # Names of supported code generators, as specified on the command-line. 31 # Names of supported code generators, as specified on the command-line.
32 # First is default. 32 # First is default.
33 GENERATORS = ['cpp', 'cpp-bundle', 'dart'] 33 GENERATORS = ['cpp', 'cpp-bundle', 'dart']
34 34
35 def _LoadSchema(schema): 35 def load_schema(schema):
36 schema_filename, schema_extension = os.path.splitext(schema) 36 schema_filename, schema_extension = os.path.splitext(schema)
37 37
38 if schema_extension == '.json': 38 if schema_extension == '.json':
39 api_defs = json_schema.Load(schema) 39 api_defs = json_schema.Load(schema)
40 elif schema_extension == '.idl': 40 elif schema_extension == '.idl':
41 api_defs = idl_schema.Load(schema) 41 api_defs = idl_schema.Load(schema)
42 else: 42 else:
43 sys.exit('Did not recognize file extension %s for schema %s' % 43 sys.exit('Did not recognize file extension %s for schema %s' %
44 (schema_extension, schema)) 44 (schema_extension, schema))
45 if len(api_defs) != 1: 45 if len(api_defs) != 1:
46 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'
47 ' single schema.' % schema) 47 ' single schema.' % schema)
48 48
49 return api_defs 49 return api_defs
50 50
51 def GenerateSchema(generator, 51 if __name__ == '__main__':
52 filenames, 52 parser = optparse.OptionParser(
53 root, 53 description='Generates a C++ model of an API from JSON schema',
54 destdir, 54 usage='usage: %prog [option]... schema')
55 root_namespace, 55 parser.add_option('-r', '--root', default='.',
56 dart_overrides_dir): 56 help='logical include root directory. Path to schema files from specified'
57 'dir will be the include path.')
58 parser.add_option('-d', '--destdir',
59 help='root directory to output generated files.')
60 parser.add_option('-n', '--namespace', default='generated_api_schemas',
61 help='C++ namespace for generated files. e.g extensions::api.')
62 parser.add_option('-g', '--generator', default=GENERATORS[0],
63 choices=GENERATORS,
64 help='The generator to use to build the output code. Supported values are'
65 ' %s' % GENERATORS)
66 parser.add_option('-D', '--dart-overrides-dir', dest='dart_overrides_dir',
67 help='Adds custom dart from files in the given directory (Dart only).')
68
69 (opts, filenames) = parser.parse_args()
70
71 if not filenames:
72 sys.exit(0) # This is OK as a no-op
73
74 # Unless in bundle mode, only one file should be specified.
75 if opts.generator != 'cpp-bundle' and len(filenames) > 1:
76 # TODO(sashab): Could also just use filenames[0] here and not complain.
77 raise Exception(
78 "Unless in bundle mode, only one file can be specified at a time.")
79
57 # Merge the source files into a single list of schemas. 80 # Merge the source files into a single list of schemas.
58 api_defs = [] 81 api_defs = []
59 for filename in filenames: 82 for filename in filenames:
60 schema = os.path.normpath(filename) 83 schema = os.path.normpath(filename)
61 schema_filename, schema_extension = os.path.splitext(schema) 84 schema_filename, schema_extension = os.path.splitext(schema)
62 path, short_filename = os.path.split(schema_filename) 85 path, short_filename = os.path.split(schema_filename)
63 api_def = _LoadSchema(schema) 86 api_def = load_schema(schema)
64 87
65 # If compiling the C++ model code, delete 'nocompile' nodes. 88 # If compiling the C++ model code, delete 'nocompile' nodes.
66 if generator == 'cpp': 89 if opts.generator == 'cpp':
67 api_def = json_schema.DeleteNodes(api_def, 'nocompile') 90 api_def = json_schema.DeleteNodes(api_def, 'nocompile')
68 api_defs.extend(api_def) 91 api_defs.extend(api_def)
69 92
70 api_model = Model() 93 api_model = Model()
71 94
72 # Load type dependencies into the model. 95 # Load type dependencies into the model.
73 # 96 #
74 # HACK(kalman): bundle mode doesn't work with dependencies, because not all 97 # HACK(kalman): bundle mode doesn't work with dependencies, because not all
75 # schemas work in bundle mode. 98 # schemas work in bundle mode.
76 # 99 #
77 # TODO(kalman): load dependencies lazily (get rid of the 'dependencies' list) 100 # TODO(kalman): load dependencies lazily (get rid of the 'dependencies' list)
78 # and this problem will go away. 101 # and this problem will go away.
79 if generator != 'cpp-bundle': 102 if opts.generator != 'cpp-bundle':
80 for target_namespace in api_defs: 103 for target_namespace in api_defs:
81 for referenced_schema in target_namespace.get('dependencies', []): 104 for referenced_schema in target_namespace.get('dependencies', []):
82 split_schema = referenced_schema.split(':', 1) 105 split_schema = referenced_schema.split(':', 1)
83 if len(split_schema) > 1: 106 if len(split_schema) > 1:
84 if split_schema[0] != 'api': 107 if split_schema[0] != 'api':
85 continue 108 continue
86 else: 109 else:
87 referenced_schema = split_schema[1] 110 referenced_schema = split_schema[1]
88 111
89 referenced_schema_path = os.path.join( 112 referenced_schema_path = os.path.join(
90 os.path.dirname(schema), referenced_schema + '.json') 113 os.path.dirname(schema), referenced_schema + '.json')
91 referenced_api_defs = json_schema.Load(referenced_schema_path) 114 referenced_api_defs = json_schema.Load(referenced_schema_path)
92 115
93 for namespace in referenced_api_defs: 116 for namespace in referenced_api_defs:
94 api_model.AddNamespace( 117 api_model.AddNamespace(
95 namespace, 118 namespace,
96 os.path.relpath(referenced_schema_path, root), 119 os.path.relpath(referenced_schema_path, opts.root),
97 include_compiler_options=True) 120 include_compiler_options=True)
98 121
99 # For single-schema compilation make sure that the first (i.e. only) schema 122 # For single-schema compilation make sure that the first (i.e. only) schema
100 # is the default one. 123 # is the default one.
101 default_namespace = None 124 default_namespace = None
102 125
103 # Load the actual namespaces into the model. 126 # Load the actual namespaces into the model.
104 for target_namespace, schema_filename in zip(api_defs, filenames): 127 for target_namespace, schema_filename in zip(api_defs, filenames):
105 relpath = os.path.relpath(os.path.normpath(schema_filename), root) 128 relpath = os.path.relpath(os.path.normpath(schema_filename), opts.root)
106 namespace = api_model.AddNamespace(target_namespace, 129 namespace = api_model.AddNamespace(target_namespace,
107 relpath, 130 relpath,
108 include_compiler_options=True) 131 include_compiler_options=True)
109 if default_namespace is None: 132 if default_namespace is None:
110 default_namespace = namespace 133 default_namespace = namespace
111 134
112 path, filename = os.path.split(schema_filename) 135 path, filename = os.path.split(schema_filename)
113 short_filename, extension = os.path.splitext(filename) 136 short_filename, extension = os.path.splitext(filename)
114 137
115 # Filenames are checked against the unix_names of the namespaces they 138 # Filenames are checked against the unix_names of the namespaces they
116 # generate because the gyp uses the names of the JSON files to generate 139 # generate because the gyp uses the names of the JSON files to generate
117 # the names of the .cc and .h files. We want these to be using unix_names. 140 # the names of the .cc and .h files. We want these to be using unix_names.
118 if namespace.unix_name != short_filename: 141 if namespace.unix_name != short_filename:
119 sys.exit("Filename %s is illegal. Name files using unix_hacker style." % 142 sys.exit("Filename %s is illegal. Name files using unix_hacker style." %
120 schema_filename) 143 schema_filename)
121 144
122 # The output filename must match the input filename for gyp to deal with it 145 # The output filename must match the input filename for gyp to deal with it
123 # properly. 146 # properly.
124 out_file = namespace.unix_name 147 out_file = namespace.unix_name
125 148
126 # Construct the type generator with all the namespaces in this model. 149 # Construct the type generator with all the namespaces in this model.
127 type_generator = CppTypeGenerator(api_model, 150 type_generator = CppTypeGenerator(api_model,
128 default_namespace=default_namespace) 151 default_namespace=default_namespace)
129 152
130 if generator == 'cpp-bundle': 153 if opts.generator == 'cpp-bundle':
131 cpp_bundle_generator = CppBundleGenerator(root, 154 cpp_bundle_generator = CppBundleGenerator(opts.root,
132 api_model, 155 api_model,
133 api_defs, 156 api_defs,
134 type_generator, 157 type_generator,
135 root_namespace) 158 opts.namespace)
136 generators = [ 159 generators = [
137 ('generated_api.cc', cpp_bundle_generator.api_cc_generator), 160 ('generated_api.cc', cpp_bundle_generator.api_cc_generator),
138 ('generated_api.h', cpp_bundle_generator.api_h_generator), 161 ('generated_api.h', cpp_bundle_generator.api_h_generator),
139 ('generated_schemas.cc', cpp_bundle_generator.schemas_cc_generator), 162 ('generated_schemas.cc', cpp_bundle_generator.schemas_cc_generator),
140 ('generated_schemas.h', cpp_bundle_generator.schemas_h_generator) 163 ('generated_schemas.h', cpp_bundle_generator.schemas_h_generator)
141 ] 164 ]
142 elif generator == 'cpp': 165 elif opts.generator == 'cpp':
143 cpp_generator = CppGenerator(type_generator, root_namespace) 166 cpp_generator = CppGenerator(type_generator, opts.namespace)
144 generators = [ 167 generators = [
145 ('%s.h' % namespace.unix_name, cpp_generator.h_generator), 168 ('%s.h' % namespace.unix_name, cpp_generator.h_generator),
146 ('%s.cc' % namespace.unix_name, cpp_generator.cc_generator) 169 ('%s.cc' % namespace.unix_name, cpp_generator.cc_generator)
147 ] 170 ]
148 elif generator == 'dart': 171 elif opts.generator == 'dart':
149 generators = [ 172 generators = [
150 ('%s.dart' % namespace.unix_name, DartGenerator( 173 ('%s.dart' % namespace.unix_name, DartGenerator(
151 dart_overrides_dir)) 174 opts.dart_overrides_dir))
152 ] 175 ]
153 else: 176 else:
154 raise Exception('Unrecognised generator %s' % generator) 177 raise Exception('Unrecognised generator %s' % opts.generator)
155 178
156 output_code = []
157 for filename, generator in generators: 179 for filename, generator in generators:
158 code = generator.Generate(namespace).Render() 180 code = generator.Generate(namespace).Render()
159 if destdir: 181 if opts.destdir:
160 with open(os.path.join(destdir, namespace.source_file_dir, 182 with open(os.path.join(opts.destdir, namespace.source_file_dir,
161 filename), 'w') as f: 183 filename), 'w') as f:
162 f.write(code) 184 f.write(code)
163 output_code += [filename, '', code, ''] 185 else:
164 186 print filename
165 return '\n'.join(output_code) 187 print
166 188 print code
167 if __name__ == '__main__': 189 print
168 parser = optparse.OptionParser(
169 description='Generates a C++ model of an API from JSON schema',
170 usage='usage: %prog [option]... schema')
171 parser.add_option('-r', '--root', default='.',
172 help='logical include root directory. Path to schema files from specified'
173 'dir will be the include path.')
174 parser.add_option('-d', '--destdir',
175 help='root directory to output generated files.')
176 parser.add_option('-n', '--namespace', default='generated_api_schemas',
177 help='C++ namespace for generated files. e.g extensions::api.')
178 parser.add_option('-g', '--generator', default=GENERATORS[0],
179 choices=GENERATORS,
180 help='The generator to use to build the output code. Supported values are'
181 ' %s' % GENERATORS)
182 parser.add_option('-D', '--dart-overrides-dir', dest='dart_overrides_dir',
183 help='Adds custom dart from files in the given directory (Dart only).')
184
185 (opts, filenames) = parser.parse_args()
186
187 if not filenames:
188 sys.exit(0) # This is OK as a no-op
189
190 # Unless in bundle mode, only one file should be specified.
191 if opts.generator != 'cpp-bundle' and len(filenames) > 1:
192 # TODO(sashab): Could also just use filenames[0] here and not complain.
193 raise Exception(
194 "Unless in bundle mode, only one file can be specified at a time.")
195
196 if opts.destdir:
197 print(GenerateSchema(opts.generator, filenames, opts.root, opts.destdir,
198 opts.namespace, opts.dart_overrides_dir))
OLDNEW
« no previous file with comments | « no previous file | tools/json_schema_compiler/dart_generator_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698