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

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

Issue 12522004: Lazily load extension API schemas (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 9 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
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 optparse
20 import os
21 import sys
22
23 from cpp_bundle_generator import CppBundleGenerator
19 from cpp_generator import CppGenerator 24 from cpp_generator import CppGenerator
20 from cpp_type_generator import CppTypeGenerator 25 from cpp_type_generator import CppTypeGenerator
21 from dart_generator import DartGenerator 26 from dart_generator import DartGenerator
22 from cpp_bundle_generator import CppBundleGenerator 27 import json_schema
23 from model import Model, UnixName 28 from model import Model, UnixName
24 import idl_schema 29 from schema_loader import SchemaLoader
25 import json_schema
26
27 import optparse
28 import os.path
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):
36 schema_filename, schema_extension = os.path.splitext(schema)
37
38 if schema_extension == '.json':
39 api_defs = json_schema.Load(schema)
40 elif schema_extension == '.idl':
41 api_defs = idl_schema.Load(schema)
42 else:
43 sys.exit('Did not recognize file extension %s for schema %s' %
44 (schema_extension, schema))
45 if len(api_defs) != 1:
46 sys.exit('File %s has multiple schemas. Files are only allowed to contain a'
47 ' single schema.' % schema)
48
49 return api_defs
50
51 def GenerateSchema(generator, 35 def GenerateSchema(generator,
52 filenames, 36 filenames,
53 root, 37 root,
54 destdir, 38 destdir,
55 root_namespace, 39 root_namespace,
56 dart_overrides_dir): 40 dart_overrides_dir):
41 schema_loader = SchemaLoader(os.path.dirname(os.path.relpath(
42 os.path.normpath(filenames[0]), root)))
57 # Merge the source files into a single list of schemas. 43 # Merge the source files into a single list of schemas.
58 api_defs = [] 44 api_defs = []
59 for filename in filenames: 45 for filename in filenames:
60 schema = os.path.normpath(filename) 46 schema = os.path.normpath(filename)
61 schema_filename, schema_extension = os.path.splitext(schema) 47 schema_filename, schema_extension = os.path.splitext(schema)
62 path, short_filename = os.path.split(schema_filename) 48 path, short_filename = os.path.split(schema_filename)
63 api_def = _LoadSchema(schema) 49 api_def = schema_loader.LoadSchema(schema)
64 50
65 # If compiling the C++ model code, delete 'nocompile' nodes. 51 # If compiling the C++ model code, delete 'nocompile' nodes.
66 if generator == 'cpp': 52 if generator == 'cpp':
67 api_def = json_schema.DeleteNodes(api_def, 'nocompile') 53 api_def = json_schema.DeleteNodes(api_def, 'nocompile')
68 api_defs.extend(api_def) 54 api_defs.extend(api_def)
69 55
70 api_model = Model() 56 api_model = Model()
71 57
72 # Load type dependencies into the model.
73 #
74 # HACK(kalman): bundle mode doesn't work with dependencies, because not all
75 # schemas work in bundle mode.
76 #
77 # TODO(kalman): load dependencies lazily (get rid of the 'dependencies' list)
78 # and this problem will go away.
79 if generator != 'cpp-bundle':
80 for target_namespace in api_defs:
81 for referenced_schema in target_namespace.get('dependencies', []):
82 split_schema = referenced_schema.split(':', 1)
83 if len(split_schema) > 1:
84 if split_schema[0] != 'api':
85 continue
86 else:
87 referenced_schema = split_schema[1]
88
89 referenced_schema_path = os.path.join(
90 os.path.dirname(schema), '%s.json' % UnixName(referenced_schema))
91 referenced_api_defs = json_schema.Load(referenced_schema_path)
92
93 for namespace in referenced_api_defs:
94 api_model.AddNamespace(
95 namespace,
96 os.path.relpath(referenced_schema_path, root),
97 include_compiler_options=True)
98
99 # For single-schema compilation make sure that the first (i.e. only) schema 58 # For single-schema compilation make sure that the first (i.e. only) schema
100 # is the default one. 59 # is the default one.
101 default_namespace = None 60 default_namespace = None
102 61
103 # Load the actual namespaces into the model. 62 # Load the actual namespaces into the model.
104 for target_namespace, schema_filename in zip(api_defs, filenames): 63 for target_namespace, schema_filename in zip(api_defs, filenames):
105 relpath = os.path.relpath(os.path.normpath(schema_filename), root) 64 relpath = os.path.relpath(os.path.normpath(schema_filename), root)
106 namespace = api_model.AddNamespace(target_namespace, 65 namespace = api_model.AddNamespace(target_namespace,
107 relpath, 66 relpath,
108 include_compiler_options=True) 67 include_compiler_options=True)
109 if default_namespace is None: 68 if default_namespace is None:
110 default_namespace = namespace 69 default_namespace = namespace
111 70
112 path, filename = os.path.split(schema_filename) 71 path, filename = os.path.split(schema_filename)
113 short_filename, extension = os.path.splitext(filename) 72 short_filename, extension = os.path.splitext(filename)
114 73
115 # Filenames are checked against the unix_names of the namespaces they 74 # 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 75 # 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. 76 # the names of the .cc and .h files. We want these to be using unix_names.
118 if namespace.unix_name != short_filename: 77 if namespace.unix_name != short_filename:
119 sys.exit("Filename %s is illegal. Name files using unix_hacker style." % 78 sys.exit("Filename %s is illegal. Name files using unix_hacker style." %
120 schema_filename) 79 schema_filename)
121 80
122 # The output filename must match the input filename for gyp to deal with it 81 # The output filename must match the input filename for gyp to deal with it
123 # properly. 82 # properly.
124 out_file = namespace.unix_name 83 out_file = namespace.unix_name
125 84
126 # Construct the type generator with all the namespaces in this model. 85 # Construct the type generator with all the namespaces in this model.
127 type_generator = CppTypeGenerator(api_model, 86 type_generator = CppTypeGenerator(api_model,
87 schema_loader,
128 default_namespace=default_namespace) 88 default_namespace=default_namespace)
129 89
130 if generator == 'cpp-bundle': 90 if generator == 'cpp-bundle':
131 cpp_bundle_generator = CppBundleGenerator(root, 91 cpp_bundle_generator = CppBundleGenerator(root,
132 api_model, 92 api_model,
133 api_defs, 93 api_defs,
134 type_generator, 94 type_generator,
135 root_namespace) 95 root_namespace)
136 generators = [ 96 generators = [
137 ('generated_api.cc', cpp_bundle_generator.api_cc_generator), 97 ('generated_api.cc', cpp_bundle_generator.api_cc_generator),
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 # Unless in bundle mode, only one file should be specified. 150 # Unless in bundle mode, only one file should be specified.
191 if opts.generator != 'cpp-bundle' and len(filenames) > 1: 151 if opts.generator != 'cpp-bundle' and len(filenames) > 1:
192 # TODO(sashab): Could also just use filenames[0] here and not complain. 152 # TODO(sashab): Could also just use filenames[0] here and not complain.
193 raise Exception( 153 raise Exception(
194 "Unless in bundle mode, only one file can be specified at a time.") 154 "Unless in bundle mode, only one file can be specified at a time.")
195 155
196 result = GenerateSchema(opts.generator, filenames, opts.root, opts.destdir, 156 result = GenerateSchema(opts.generator, filenames, opts.root, opts.destdir,
197 opts.namespace, opts.dart_overrides_dir) 157 opts.namespace, opts.dart_overrides_dir)
198 if not opts.destdir: 158 if not opts.destdir:
199 print result 159 print result
OLDNEW
« no previous file with comments | « chrome/renderer/resources/extensions/test_custom_bindings.js ('k') | tools/json_schema_compiler/cpp_type_generator.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698