def FormatOptions(options, is_message=False): """Format MessageOptions/EnumOptions message. Args: options: A MessageOptions/EnumOptions message. is_message: is this a message type? Returns: Formatted options as a string. """ formatted_options = [] if options.deprecated: formatted_options.append('option deprecated = true;') if is_message: versioning_annotation = protoxform_options.GetVersioningAnnotation( options) if versioning_annotation: formatted_options.append( 'option (udpa.annotations.versioning).previous_message_type = "%s";' % versioning_annotation.previous_message_type) if formatted_options: return FormatBlock('\n'.join(formatted_options) + '\n') return ''
def FormatHeaderFromFile(source_code_info, file_proto, empty_file): """Format proto header. Args: source_code_info: SourceCodeInfo object. file_proto: FileDescriptorProto for file. empty_file: are there no message/enum/service defs in file? Returns: Formatted proto header as a string. """ # Load the type database. typedb = utils.GetTypeDb() # Figure out type dependencies in this .proto. types = Types() text_format.Merge(traverse.TraverseFile(file_proto, type_whisperer.TypeWhispererVisitor()), types) type_dependencies = sum([list(t.type_dependencies) for t in types.types.values()], []) for service in file_proto.service: for m in service.method: type_dependencies.extend([m.input_type[1:], m.output_type[1:]]) # Determine the envoy/ import paths from type deps. envoy_proto_paths = set( typedb.types[t].proto_path for t in type_dependencies if t.startswith('envoy.') and typedb.types[t].proto_path != file_proto.name) def CamelCase(s): return ''.join(t.capitalize() for t in re.split('[\._]', s)) package_line = 'package %s;\n' % file_proto.package file_block = '\n'.join(['syntax = "proto3";\n', package_line]) options = descriptor_pb2.FileOptions() options.java_outer_classname = CamelCase(os.path.basename(file_proto.name)) options.java_multiple_files = True options.java_package = 'io.envoyproxy.' + file_proto.package # This is a workaround for C#/Ruby namespace conflicts between packages and # objects, see https://github.com/envoyproxy/envoy/pull/3854. # TODO(htuch): remove once v3 fixes this naming issue in # https://github.com/envoyproxy/envoy/issues/8120. if file_proto.package in ['envoy.api.v2.listener', 'envoy.api.v2.cluster']: qualified_package = '.'.join(s.capitalize() for s in file_proto.package.split('.')) + 'NS' options.csharp_namespace = qualified_package options.ruby_package = qualified_package if file_proto.service: options.java_generic_services = True if file_proto.options.HasExtension(migrate_pb2.file_migrate): options.Extensions[migrate_pb2.file_migrate].CopyFrom( file_proto.options.Extensions[migrate_pb2.file_migrate]) if file_proto.options.HasExtension( status_pb2.file_status) and file_proto.package.endswith('alpha'): options.Extensions[status_pb2.file_status].CopyFrom( file_proto.options.Extensions[status_pb2.file_status]) if not empty_file: options.Extensions[ status_pb2.file_status].package_version_status = file_proto.options.Extensions[ status_pb2.file_status].package_version_status options_block = FormatOptions(options) requires_versioning_import = any( protoxform_options.GetVersioningAnnotation(m.options) for m in file_proto.message_type) envoy_imports = list(envoy_proto_paths) google_imports = [] infra_imports = [] misc_imports = [] public_imports = [] for idx, d in enumerate(file_proto.dependency): if idx in file_proto.public_dependency: public_imports.append(d) continue elif d.startswith('envoy/annotations') or d.startswith('udpa/annotations'): infra_imports.append(d) elif d.startswith('envoy/'): # We ignore existing envoy/ imports, since these are computed explicitly # from type_dependencies. pass elif d.startswith('google/'): google_imports.append(d) elif d.startswith('validate/'): infra_imports.append(d) elif d in ['udpa/annotations/versioning.proto', 'udpa/annotations/status.proto']: # Skip, we decide to add this based on requires_versioning_import and options. pass else: misc_imports.append(d) if options.HasExtension(status_pb2.file_status): infra_imports.append('udpa/annotations/status.proto') if requires_versioning_import: infra_imports.append('udpa/annotations/versioning.proto') def FormatImportBlock(xs): if not xs: return '' return FormatBlock('\n'.join(sorted('import "%s";' % x for x in set(xs) if x))) def FormatPublicImportBlock(xs): if not xs: return '' return FormatBlock('\n'.join(sorted('import public "%s";' % x for x in xs))) import_block = '\n'.join( map(FormatImportBlock, [envoy_imports, google_imports, misc_imports, infra_imports])) import_block += '\n' + FormatPublicImportBlock(public_imports) comment_block = FormatComments(source_code_info.file_level_comments) return ''.join(map(FormatBlock, [file_block, import_block, options_block, comment_block]))