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

Side by Side Diff: mojo/public/tools/bindings/mojom_bindings_generator.py

Issue 1517043004: [mojo] Add typemap and variant support to generators (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@pickle3
Patch Set: Created 5 years 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 2013 The Chromium Authors. All rights reserved. 2 # Copyright 2013 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 5
6 """The frontend for the Mojo bindings system.""" 6 """The frontend for the Mojo bindings system."""
7 7
8 8
9 import argparse 9 import argparse
10 import imp 10 import imp
11 import json
11 import os 12 import os
12 import pprint 13 import pprint
14 import re
13 import sys 15 import sys
14 16
15 # Disable lint check for finding modules: 17 # Disable lint check for finding modules:
16 # pylint: disable=F0401 18 # pylint: disable=F0401
17 19
18 def _GetDirAbove(dirname): 20 def _GetDirAbove(dirname):
19 """Returns the directory "above" this file containing |dirname| (which must 21 """Returns the directory "above" this file containing |dirname| (which must
20 also be "above" this file).""" 22 also be "above" this file)."""
21 path = os.path.abspath(__file__) 23 path = os.path.abspath(__file__)
22 while True: 24 while True:
(...skipping 10 matching lines...) Expand all
33 sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), 35 sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
34 "pylib")) 36 "pylib"))
35 37
36 from mojom.error import Error 38 from mojom.error import Error
37 import mojom.fileutil as fileutil 39 import mojom.fileutil as fileutil
38 from mojom.generate.data import OrderedModuleFromData 40 from mojom.generate.data import OrderedModuleFromData
39 from mojom.parse.parser import Parse 41 from mojom.parse.parser import Parse
40 from mojom.parse.translate import Translate 42 from mojom.parse.translate import Translate
41 43
42 44
45 _BUILTIN_GENERATORS = {
46 "c++": "mojom_cpp_generator.py",
47 "javascript": "mojom_js_generator.py",
48 "java": "mojom_java_generator.py",
49 }
50
43 def LoadGenerators(generators_string): 51 def LoadGenerators(generators_string):
44 if not generators_string: 52 if not generators_string:
45 return [] # No generators. 53 return [] # No generators.
46 54
47 script_dir = os.path.dirname(os.path.abspath(__file__)) 55 script_dir = os.path.dirname(os.path.abspath(__file__))
48 generators = [] 56 generators = {}
49 for generator_name in [s.strip() for s in generators_string.split(",")]: 57 for generator_name in [s.strip() for s in generators_string.split(",")]:
50 # "Built-in" generators: 58 language = generator_name.lower()
51 if generator_name.lower() == "c++": 59 if language in _BUILTIN_GENERATORS:
52 generator_name = os.path.join(script_dir, "generators", 60 generator_name = os.path.join(script_dir, "generators",
53 "mojom_cpp_generator.py") 61 _BUILTIN_GENERATORS[language])
54 elif generator_name.lower() == "javascript":
55 generator_name = os.path.join(script_dir, "generators",
56 "mojom_js_generator.py")
57 elif generator_name.lower() == "java":
58 generator_name = os.path.join(script_dir, "generators",
59 "mojom_java_generator.py")
60 # Specified generator python module:
61 elif generator_name.endswith(".py"): 62 elif generator_name.endswith(".py"):
yzshen1 2015/12/15 00:09:10 This elif is probably not useful.
62 pass 63 pass
63 else: 64 else:
64 print "Unknown generator name %s" % generator_name 65 print "Unknown generator name %s" % generator_name
65 sys.exit(1) 66 sys.exit(1)
66 generator_module = imp.load_source(os.path.basename(generator_name)[:-3], 67 generator_module = imp.load_source(os.path.basename(generator_name)[:-3],
67 generator_name) 68 generator_name)
68 generators.append(generator_module) 69 generators[language] = generator_module
69 return generators 70 return generators
70 71
71 72
72 def MakeImportStackMessage(imported_filename_stack): 73 def MakeImportStackMessage(imported_filename_stack):
73 """Make a (human-readable) message listing a chain of imports. (Returned 74 """Make a (human-readable) message listing a chain of imports. (Returned
74 string begins with a newline (if nonempty) and does not end with one.)""" 75 string begins with a newline (if nonempty) and does not end with one.)"""
75 return ''.join( 76 return ''.join(
76 reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \ 77 reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \
77 zip(imported_filename_stack[1:], imported_filename_stack)])) 78 zip(imported_filename_stack[1:], imported_filename_stack)]))
78 79
79 80
80 def FindImportFile(dir_name, file_name, search_dirs): 81 def FindImportFile(dir_name, file_name, search_dirs):
81 for search_dir in [dir_name] + search_dirs: 82 for search_dir in [dir_name] + search_dirs:
82 path = os.path.join(search_dir, file_name) 83 path = os.path.join(search_dir, file_name)
83 if os.path.isfile(path): 84 if os.path.isfile(path):
84 return path 85 return path
85 return os.path.join(dir_name, file_name) 86 return os.path.join(dir_name, file_name)
86 87
87 class MojomProcessor(object): 88 class MojomProcessor(object):
88 def __init__(self, should_generate): 89 def __init__(self, should_generate):
89 self._should_generate = should_generate 90 self._should_generate = should_generate
90 self._processed_files = {} 91 self._processed_files = {}
91 self._parsed_files = {} 92 self._parsed_files = {}
93 self._typemap = {}
94
95 def LoadTypemaps(self, typemaps):
yzshen1 2015/12/15 00:09:10 Please consider writing tests in: https://code.goo
96 # Support some very simple single-line comments in typemap JSON.
97 comment_expr = r"^\s*//.*$"
98 def no_comments(line):
99 return not re.match(comment_expr, line)
100 for filename in typemaps:
101 with open(filename) as f:
102 typemaps = json.loads("".join(filter(no_comments, f.readlines())))
103 for language, typemap in typemaps.iteritems():
104 language_map = self._typemap.get(language, {})
105 language_map.update(typemap)
106 self._typemap[language] = language_map
92 107
93 def ProcessFile(self, args, remaining_args, generator_modules, filename): 108 def ProcessFile(self, args, remaining_args, generator_modules, filename):
94 self._ParseFileAndImports(filename, args.import_directories, []) 109 self._ParseFileAndImports(filename, args.import_directories, [])
95 110
96 return self._GenerateModule(args, remaining_args, generator_modules, 111 return self._GenerateModule(args, remaining_args, generator_modules,
97 filename) 112 filename)
98 113
99 def _GenerateModule(self, args, remaining_args, generator_modules, filename): 114 def _GenerateModule(self, args, remaining_args, generator_modules, filename):
100 # Return the already-generated module. 115 # Return the already-generated module.
101 if filename in self._processed_files: 116 if filename in self._processed_files:
(...skipping 17 matching lines...) Expand all
119 module = OrderedModuleFromData(mojom) 134 module = OrderedModuleFromData(mojom)
120 135
121 # Set the path as relative to the source root. 136 # Set the path as relative to the source root.
122 module.path = os.path.relpath(os.path.abspath(filename), 137 module.path = os.path.relpath(os.path.abspath(filename),
123 os.path.abspath(args.depth)) 138 os.path.abspath(args.depth))
124 139
125 # Normalize to unix-style path here to keep the generators simpler. 140 # Normalize to unix-style path here to keep the generators simpler.
126 module.path = module.path.replace('\\', '/') 141 module.path = module.path.replace('\\', '/')
127 142
128 if self._should_generate(filename): 143 if self._should_generate(filename):
129 for generator_module in generator_modules: 144 for language, generator_module in generator_modules.iteritems():
130 generator = generator_module.Generator(module, args.output_dir) 145 generator = generator_module.Generator(
146 module, args.output_dir, typemap=self._typemap.get(language, {}),
147 variant=args.variant)
131 filtered_args = [] 148 filtered_args = []
132 if hasattr(generator_module, 'GENERATOR_PREFIX'): 149 if hasattr(generator_module, 'GENERATOR_PREFIX'):
133 prefix = '--' + generator_module.GENERATOR_PREFIX + '_' 150 prefix = '--' + generator_module.GENERATOR_PREFIX + '_'
134 filtered_args = [arg for arg in remaining_args 151 filtered_args = [arg for arg in remaining_args
135 if arg.startswith(prefix)] 152 if arg.startswith(prefix)]
136 generator.GenerateFiles(filtered_args) 153 generator.GenerateFiles(filtered_args)
137 154
138 # Save result. 155 # Save result.
139 self._processed_files[filename] = module 156 self._processed_files[filename] = module
140 return module 157 return module
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 metavar="GENERATORS", 205 metavar="GENERATORS",
189 default="c++,javascript,java", 206 default="c++,javascript,java",
190 help="comma-separated list of generators") 207 help="comma-separated list of generators")
191 parser.add_argument("--debug_print_intermediate", action="store_true", 208 parser.add_argument("--debug_print_intermediate", action="store_true",
192 help="print the intermediate representation") 209 help="print the intermediate representation")
193 parser.add_argument("-I", dest="import_directories", action="append", 210 parser.add_argument("-I", dest="import_directories", action="append",
194 metavar="directory", default=[], 211 metavar="directory", default=[],
195 help="add a directory to be searched for import files") 212 help="add a directory to be searched for import files")
196 parser.add_argument("--use_bundled_pylibs", action="store_true", 213 parser.add_argument("--use_bundled_pylibs", action="store_true",
197 help="use Python modules bundled in the SDK") 214 help="use Python modules bundled in the SDK")
215 parser.add_argument("--typemap", action="append", metavar="TYPEMAP",
216 default=[], dest="typemaps",
217 help="apply TYPEMAP to generated output")
218 parser.add_argument("--variant", dest="variant", default=None,
219 help="output a named variant of the bindings")
198 (args, remaining_args) = parser.parse_known_args() 220 (args, remaining_args) = parser.parse_known_args()
199 221
200 generator_modules = LoadGenerators(args.generators_string) 222 generator_modules = LoadGenerators(args.generators_string)
201 223
202 fileutil.EnsureDirectoryExists(args.output_dir) 224 fileutil.EnsureDirectoryExists(args.output_dir)
203 225
204 processor = MojomProcessor(lambda filename: filename in args.filename) 226 processor = MojomProcessor(lambda filename: filename in args.filename)
227 processor.LoadTypemaps(set(args.typemaps))
205 for filename in args.filename: 228 for filename in args.filename:
206 processor.ProcessFile(args, remaining_args, generator_modules, filename) 229 processor.ProcessFile(args, remaining_args, generator_modules, filename)
207 230
208 return 0 231 return 0
209 232
210 233
211 if __name__ == "__main__": 234 if __name__ == "__main__":
212 sys.exit(main()) 235 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698