def _GenerateSchema(filename, root, destdir, namespace): """Generates C++ features files from the json file |filename|. """ # Load in the feature permissions from the JSON file. schema = os.path.normpath(filename) schema_loader = SchemaLoader( os.path.dirname(os.path.relpath(schema, root)), os.path.dirname(schema), [], None) schema_filename = os.path.splitext(schema)[0] feature_defs = schema_loader.LoadSchema(schema) # Generate a list of the features defined and a list of their models. feature_list = [] for feature_def, feature in feature_defs.items(): feature_list.append(CreateFeature(feature_def, feature)) source_file_dir, _ = os.path.split(schema) relpath = os.path.relpath(os.path.normpath(source_file_dir), root) full_path = os.path.join(relpath, schema) generators = [('%s.cc' % schema_filename, CCGenerator()), ('%s.h' % schema_filename, HGenerator())] # Generate and output the code for all features. output_code = [] for filename, generator in generators: code = generator.Generate(feature_list, full_path, namespace).Render() if destdir: with open(os.path.join(destdir, relpath, filename), 'w') as f: f.write(code) output_code += [filename, '', code, ''] return '\n'.join(output_code)
def _ShowCompiledFile(self, parsed_url, head, body): """Show the compiled version of a json or idl file given the path to the compiled file. """ api_model = model.Model() request_path = self._GetRequestPath(parsed_url) (file_root, file_ext) = os.path.splitext(request_path) (filedir, filename) = os.path.split(file_root) schema_loader = SchemaLoader("./", filedir, self.server.include_rules, self.server.cpp_namespace_pattern) try: # Get main file. namespace = schema_loader.ResolveNamespace(filename) type_generator = cpp_type_generator.CppTypeGenerator( api_model, schema_loader, namespace) # Generate code cpp_namespace = 'generated_api_schemas' if file_ext == '.h': cpp_code = (h_generator.HGenerator(type_generator) .Generate(namespace).Render()) elif file_ext == '.cc': cpp_code = (cc_generator.CCGenerator(type_generator) .Generate(namespace).Render()) else: self.send_error(404, "File not found: %s" % request_path) return # Do highlighting on the generated code (highlighter_param, style_param) = self._GetHighlighterParams(parsed_url) head.Append('<style>' + self.server.highlighters[highlighter_param].GetCSS(style_param) + '</style>') body.Append(self.server.highlighters[highlighter_param] .GetCodeElement(cpp_code, style_param)) except IOError: self.send_error(404, "File not found: %s" % request_path) return except (TypeError, KeyError, AttributeError, AssertionError, NotImplementedError) as error: body.Append('<pre>') body.Append('compiler error: %s' % error) body.Append('Check server log for more details') body.Append('</pre>') raise
def _LoadNamespace(filename): filename = os.path.join(os.path.dirname(__file__), filename) schema_loader = SchemaLoader( os.path.dirname(os.path.relpath(os.path.normpath(filename), os.path.dirname(filename))), os.path.dirname(filename)) schema = os.path.normpath(filename) api_def = schema_loader.LoadSchema(os.path.split(schema)[1])[0] api_model = Model() relpath = os.path.relpath(os.path.normpath(filename), os.path.dirname(filename)) namespace = api_model.AddNamespace(api_def, relpath) generator = ppapi_generator._PpapiGeneratorBase(namespace) return namespace, generator
def ResolveNamespace(self, full_namespace): '''Returns the model.Namespace object associated with the |full_namespace|, or None if one can't be found. ''' filenames = _GenerateFilenames(full_namespace) for path, cpp_namespace in self._include_rules: cpp_namespace_environment = None if cpp_namespace: cpp_namespace_environment = CppNamespaceEnvironment(cpp_namespace) for filename in reversed(filenames): filepath = os.path.join(path, filename); if os.path.exists(os.path.join(self._root, filepath)): schema = SchemaLoader(self._root).LoadSchema(filepath)[0] return Model().AddNamespace( schema, filepath, environment=cpp_namespace_environment) return None
def GenerateSchema(generator_name, file_paths, root, destdir, cpp_namespace_pattern, bundle_name, impl_dir, include_rules): # Merge the source files into a single list of schemas. api_defs = [] for file_path in file_paths: schema = os.path.relpath(file_path, root) api_def = SchemaLoader(root).LoadSchema(schema) # If compiling the C++ model code, delete 'nocompile' nodes. if generator_name == 'cpp': api_def = json_schema.DeleteNodes(api_def, 'nocompile') # Delete all 'nodefine' nodes. They are only for documentation. api_def = json_schema.DeleteNodes(api_def, 'nodefine') api_defs.extend(api_def) api_model = Model(allow_inline_enums=False) # For single-schema compilation make sure that the first (i.e. only) schema # is the default one. default_namespace = None # If we have files from multiple source paths, we'll use the common parent # path as the source directory. src_path = None # Load the actual namespaces into the model. for target_namespace, file_path in zip(api_defs, file_paths): relpath = os.path.relpath(os.path.normpath(file_path), root) namespace = api_model.AddNamespace(target_namespace, relpath, include_compiler_options=True, environment=CppNamespaceEnvironment( cpp_namespace_pattern)) if default_namespace is None: default_namespace = namespace if src_path is None: src_path = namespace.source_file_dir else: src_path = os.path.commonprefix((src_path, namespace.source_file_dir)) _, filename = os.path.split(file_path) filename_base, _ = os.path.splitext(filename) # Construct the type generator with all the namespaces in this model. schema_dir = os.path.dirname(os.path.relpath(file_paths[0], root)) namespace_resolver = NamespaceResolver(root, schema_dir, include_rules, cpp_namespace_pattern) type_generator = CppTypeGenerator(api_model, namespace_resolver, default_namespace) if generator_name in ('cpp-bundle-registration', 'cpp-bundle-schema'): cpp_bundle_generator = CppBundleGenerator(root, api_model, api_defs, type_generator, cpp_namespace_pattern, bundle_name, src_path, impl_dir) if generator_name == 'cpp-bundle-registration': generators = [ ('generated_api_registration.cc', cpp_bundle_generator.api_cc_generator), ('generated_api_registration.h', cpp_bundle_generator.api_h_generator), ] elif generator_name == 'cpp-bundle-schema': generators = [ ('generated_schemas.cc', cpp_bundle_generator.schemas_cc_generator), ('generated_schemas.h', cpp_bundle_generator.schemas_h_generator) ] elif generator_name == 'cpp': cpp_generator = CppGenerator(type_generator) generators = [ ('%s.h' % filename_base, cpp_generator.h_generator), ('%s.cc' % filename_base, cpp_generator.cc_generator) ] elif generator_name == 'externs': generators = [ ('%s_externs.js' % namespace.unix_name, JsExternsGenerator()) ] elif generator_name == 'interface': generators = [ ('%s_interface.js' % namespace.unix_name, JsInterfaceGenerator()) ] else: raise Exception('Unrecognised generator %s' % generator_name) output_code = [] for filename, generator in generators: code = generator.Generate(namespace).Render() if destdir: if generator_name == 'cpp-bundle-registration': # Function registrations must be output to impl_dir, since they link in # API implementations. output_dir = os.path.join(destdir, impl_dir) else: output_dir = os.path.join(destdir, src_path) if not os.path.exists(output_dir): os.makedirs(output_dir) with open(os.path.join(output_dir, filename), 'w') as f: f.write(code) # If multiple files are being output, add the filename for each file. if len(generators) > 1: output_code += [filename, '', code, ''] else: output_code += [code] return '\n'.join(output_code)
def GenerateSchema(generator, filenames, root, destdir, root_namespace, dart_overrides_dir): schema_loader = SchemaLoader( os.path.dirname(os.path.relpath(os.path.normpath(filenames[0]), root)), os.path.dirname(filenames[0])) # Merge the source files into a single list of schemas. api_defs = [] for filename in filenames: schema = os.path.normpath(filename) api_def = schema_loader.LoadSchema(os.path.split(schema)[1]) # If compiling the C++ model code, delete 'nocompile' nodes. if generator == 'cpp': api_def = json_schema.DeleteNodes(api_def, 'nocompile') api_defs.extend(api_def) api_model = Model() # For single-schema compilation make sure that the first (i.e. only) schema # is the default one. default_namespace = None # Load the actual namespaces into the model. for target_namespace, schema_filename in zip(api_defs, filenames): relpath = os.path.relpath(os.path.normpath(schema_filename), root) namespace = api_model.AddNamespace(target_namespace, relpath, include_compiler_options=True) if default_namespace is None: default_namespace = namespace path, filename = os.path.split(schema_filename) short_filename, extension = os.path.splitext(filename) # Filenames are checked against the unix_names of the namespaces they # generate because the gyp uses the names of the JSON files to generate # the names of the .cc and .h files. We want these to be using unix_names. if namespace.unix_name != short_filename: sys.exit( "Filename %s is illegal. Name files using unix_hacker style." % schema_filename) # Construct the type generator with all the namespaces in this model. type_generator = CppTypeGenerator(api_model, schema_loader, default_namespace=default_namespace) if generator == 'cpp-bundle': cpp_bundle_generator = CppBundleGenerator(root, api_model, api_defs, type_generator, root_namespace) generators = [ ('generated_api.cc', cpp_bundle_generator.api_cc_generator), ('generated_api.h', cpp_bundle_generator.api_h_generator), ('generated_schemas.cc', cpp_bundle_generator.schemas_cc_generator), ('generated_schemas.h', cpp_bundle_generator.schemas_h_generator) ] elif generator == 'cpp': cpp_generator = CppGenerator(type_generator, root_namespace) generators = [ ('%s.h' % namespace.unix_name, cpp_generator.h_generator), ('%s.cc' % namespace.unix_name, cpp_generator.cc_generator) ] elif generator == 'dart': generators = [('%s.dart' % namespace.unix_name, DartGenerator(dart_overrides_dir))] else: raise Exception('Unrecognised generator %s' % generator) output_code = [] for filename, generator in generators: code = generator.Generate(namespace).Render() if destdir: with open( os.path.join(destdir, namespace.source_file_dir, filename), 'w') as f: f.write(code) output_code += [filename, '', code, ''] return '\n'.join(output_code)
def GenerateSchema(generator, filenames, root, destdir, root_namespace, dart_overrides_dir, impl_dir): # Merge the source files into a single list of schemas. api_defs = [] for filename in filenames: schema = os.path.normpath(filename) schema_loader = SchemaLoader( os.path.dirname(os.path.relpath(os.path.normpath(filename), root)), os.path.dirname(filename)) api_def = schema_loader.LoadSchema(os.path.split(schema)[1]) # If compiling the C++ model code, delete 'nocompile' nodes. if generator == 'cpp': api_def = json_schema.DeleteNodes(api_def, 'nocompile') api_defs.extend(api_def) api_model = Model() # For single-schema compilation make sure that the first (i.e. only) schema # is the default one. default_namespace = None # If we have files from multiple source paths, we'll use the common parent # path as the source directory. src_path = None # Load the actual namespaces into the model. for target_namespace, schema_filename in zip(api_defs, filenames): relpath = os.path.relpath(os.path.normpath(schema_filename), root) namespace = api_model.AddNamespace(target_namespace, relpath, include_compiler_options=True) if default_namespace is None: default_namespace = namespace if src_path is None: src_path = namespace.source_file_dir else: src_path = os.path.commonprefix( (src_path, namespace.source_file_dir)) path, filename = os.path.split(schema_filename) short_filename, extension = os.path.splitext(filename) # Construct the type generator with all the namespaces in this model. type_generator = CppTypeGenerator(api_model, schema_loader, default_namespace=default_namespace) if generator == 'cpp-bundle': cpp_bundle_generator = CppBundleGenerator(root, api_model, api_defs, type_generator, root_namespace, src_path, impl_dir) generators = [ ('generated_api.cc', cpp_bundle_generator.api_cc_generator), ('generated_api.h', cpp_bundle_generator.api_h_generator), ('generated_schemas.cc', cpp_bundle_generator.schemas_cc_generator), ('generated_schemas.h', cpp_bundle_generator.schemas_h_generator) ] elif generator == 'cpp': cpp_generator = CppGenerator(type_generator, root_namespace) generators = [('%s.h' % short_filename, cpp_generator.h_generator), ('%s.cc' % short_filename, cpp_generator.cc_generator)] elif generator == 'dart': generators = [('%s.dart' % namespace.unix_name, DartGenerator(dart_overrides_dir))] elif generator == 'ppapi': generator = PpapiGenerator() generators = [ (os.path.join('api', 'ppb_%s.idl' % namespace.unix_name), generator.idl_generator), ] else: raise Exception('Unrecognised generator %s' % generator) output_code = [] for filename, generator in generators: code = generator.Generate(namespace).Render() if destdir: output_dir = os.path.join(destdir, src_path) if not os.path.exists(output_dir): os.makedirs(output_dir) with open(os.path.join(output_dir, filename), 'w') as f: f.write(code) output_code += [filename, '', code, ''] return '\n'.join(output_code)