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

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: set proper upstream 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
« no previous file with comments | « mojo/public/tools/bindings/mojom.gni ('k') | mojo/public/tools/bindings/mojom_list_outputs.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 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 pass
63 else: 62 else:
64 print "Unknown generator name %s" % generator_name 63 print "Unknown generator name %s" % generator_name
65 sys.exit(1) 64 sys.exit(1)
66 generator_module = imp.load_source(os.path.basename(generator_name)[:-3], 65 generator_module = imp.load_source(os.path.basename(generator_name)[:-3],
67 generator_name) 66 generator_name)
68 generators.append(generator_module) 67 generators[language] = generator_module
69 return generators 68 return generators
70 69
71 70
72 def MakeImportStackMessage(imported_filename_stack): 71 def MakeImportStackMessage(imported_filename_stack):
73 """Make a (human-readable) message listing a chain of imports. (Returned 72 """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.)""" 73 string begins with a newline (if nonempty) and does not end with one.)"""
75 return ''.join( 74 return ''.join(
76 reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \ 75 reversed(["\n %s was imported by %s" % (a, b) for (a, b) in \
77 zip(imported_filename_stack[1:], imported_filename_stack)])) 76 zip(imported_filename_stack[1:], imported_filename_stack)]))
78 77
79 78
80 def FindImportFile(dir_name, file_name, search_dirs): 79 def FindImportFile(dir_name, file_name, search_dirs):
81 for search_dir in [dir_name] + search_dirs: 80 for search_dir in [dir_name] + search_dirs:
82 path = os.path.join(search_dir, file_name) 81 path = os.path.join(search_dir, file_name)
83 if os.path.isfile(path): 82 if os.path.isfile(path):
84 return path 83 return path
85 return os.path.join(dir_name, file_name) 84 return os.path.join(dir_name, file_name)
86 85
87 class MojomProcessor(object): 86 class MojomProcessor(object):
88 def __init__(self, should_generate): 87 def __init__(self, should_generate):
89 self._should_generate = should_generate 88 self._should_generate = should_generate
90 self._processed_files = {} 89 self._processed_files = {}
91 self._parsed_files = {} 90 self._parsed_files = {}
91 self._typemap = {}
92
93 def LoadTypemaps(self, typemaps):
94 # Support some very simple single-line comments in typemap JSON.
95 comment_expr = r"^\s*//.*$"
96 def no_comments(line):
97 return not re.match(comment_expr, line)
98 for filename in typemaps:
99 with open(filename) as f:
100 typemaps = json.loads("".join(filter(no_comments, f.readlines())))
101 for language, typemap in typemaps.iteritems():
102 language_map = self._typemap.get(language, {})
103 language_map.update(typemap)
104 self._typemap[language] = language_map
92 105
93 def ProcessFile(self, args, remaining_args, generator_modules, filename): 106 def ProcessFile(self, args, remaining_args, generator_modules, filename):
94 self._ParseFileAndImports(filename, args.import_directories, []) 107 self._ParseFileAndImports(filename, args.import_directories, [])
95 108
96 return self._GenerateModule(args, remaining_args, generator_modules, 109 return self._GenerateModule(args, remaining_args, generator_modules,
97 filename) 110 filename)
98 111
99 def _GenerateModule(self, args, remaining_args, generator_modules, filename): 112 def _GenerateModule(self, args, remaining_args, generator_modules, filename):
100 # Return the already-generated module. 113 # Return the already-generated module.
101 if filename in self._processed_files: 114 if filename in self._processed_files:
(...skipping 17 matching lines...) Expand all
119 module = OrderedModuleFromData(mojom) 132 module = OrderedModuleFromData(mojom)
120 133
121 # Set the path as relative to the source root. 134 # Set the path as relative to the source root.
122 module.path = os.path.relpath(os.path.abspath(filename), 135 module.path = os.path.relpath(os.path.abspath(filename),
123 os.path.abspath(args.depth)) 136 os.path.abspath(args.depth))
124 137
125 # Normalize to unix-style path here to keep the generators simpler. 138 # Normalize to unix-style path here to keep the generators simpler.
126 module.path = module.path.replace('\\', '/') 139 module.path = module.path.replace('\\', '/')
127 140
128 if self._should_generate(filename): 141 if self._should_generate(filename):
129 for generator_module in generator_modules: 142 for language, generator_module in generator_modules.iteritems():
130 generator = generator_module.Generator(module, args.output_dir) 143 generator = generator_module.Generator(
144 module, args.output_dir, typemap=self._typemap.get(language, {}),
145 variant=args.variant)
131 filtered_args = [] 146 filtered_args = []
132 if hasattr(generator_module, 'GENERATOR_PREFIX'): 147 if hasattr(generator_module, 'GENERATOR_PREFIX'):
133 prefix = '--' + generator_module.GENERATOR_PREFIX + '_' 148 prefix = '--' + generator_module.GENERATOR_PREFIX + '_'
134 filtered_args = [arg for arg in remaining_args 149 filtered_args = [arg for arg in remaining_args
135 if arg.startswith(prefix)] 150 if arg.startswith(prefix)]
136 generator.GenerateFiles(filtered_args) 151 generator.GenerateFiles(filtered_args)
137 152
138 # Save result. 153 # Save result.
139 self._processed_files[filename] = module 154 self._processed_files[filename] = module
140 return module 155 return module
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
188 metavar="GENERATORS", 203 metavar="GENERATORS",
189 default="c++,javascript,java", 204 default="c++,javascript,java",
190 help="comma-separated list of generators") 205 help="comma-separated list of generators")
191 parser.add_argument("--debug_print_intermediate", action="store_true", 206 parser.add_argument("--debug_print_intermediate", action="store_true",
192 help="print the intermediate representation") 207 help="print the intermediate representation")
193 parser.add_argument("-I", dest="import_directories", action="append", 208 parser.add_argument("-I", dest="import_directories", action="append",
194 metavar="directory", default=[], 209 metavar="directory", default=[],
195 help="add a directory to be searched for import files") 210 help="add a directory to be searched for import files")
196 parser.add_argument("--use_bundled_pylibs", action="store_true", 211 parser.add_argument("--use_bundled_pylibs", action="store_true",
197 help="use Python modules bundled in the SDK") 212 help="use Python modules bundled in the SDK")
213 parser.add_argument("--typemap", action="append", metavar="TYPEMAP",
214 default=[], dest="typemaps",
215 help="apply TYPEMAP to generated output")
216 parser.add_argument("--variant", dest="variant", default=None,
217 help="output a named variant of the bindings")
198 (args, remaining_args) = parser.parse_known_args() 218 (args, remaining_args) = parser.parse_known_args()
199 219
220 if args.variant == "none":
221 args.variant = None
222
200 generator_modules = LoadGenerators(args.generators_string) 223 generator_modules = LoadGenerators(args.generators_string)
201 224
202 fileutil.EnsureDirectoryExists(args.output_dir) 225 fileutil.EnsureDirectoryExists(args.output_dir)
203 226
204 processor = MojomProcessor(lambda filename: filename in args.filename) 227 processor = MojomProcessor(lambda filename: filename in args.filename)
228 processor.LoadTypemaps(set(args.typemaps))
205 for filename in args.filename: 229 for filename in args.filename:
206 processor.ProcessFile(args, remaining_args, generator_modules, filename) 230 processor.ProcessFile(args, remaining_args, generator_modules, filename)
207 231
208 return 0 232 return 0
209 233
210 234
211 if __name__ == "__main__": 235 if __name__ == "__main__":
212 sys.exit(main()) 236 sys.exit(main())
OLDNEW
« no previous file with comments | « mojo/public/tools/bindings/mojom.gni ('k') | mojo/public/tools/bindings/mojom_list_outputs.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698