OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """ |
| 6 Provides simple state-less wrappers of the proto types used by plugins. |
| 7 |
| 8 See https://developers.google.com/protocol-buffers/docs/reference/cpp/google.pro
tobuf.descriptor.pb |
| 9 and https://developers.google.com/protocol-buffers/docs/reference/cpp/google.pro
tobuf.compiler.plugin.pb |
| 10 """ |
| 11 |
| 12 import os |
| 13 import sys |
| 14 |
| 15 from google.protobuf.descriptor_pb2 import FieldDescriptorProto |
| 16 |
| 17 import plugin |
| 18 import types |
| 19 |
| 20 sys.path.insert( |
| 21 1, os.path.join(os.path.dirname(__file__), '..', '..', |
| 22 'dist', 'python')) |
| 23 import plugin_pb2 |
| 24 |
| 25 |
| 26 class PluginRequest(object): |
| 27 def __init__(self, proto): |
| 28 self.proto = proto |
| 29 |
| 30 def GetArgs(self): |
| 31 return dict((v.split('=') for v in self.proto.parameter.split(','))) |
| 32 |
| 33 def GetAllFiles(self): |
| 34 return map(ProtoFile, self.proto.proto_file) |
| 35 |
| 36 |
| 37 def PluginRequestFromString(data): |
| 38 request_proto = plugin_pb2.CodeGeneratorRequest() |
| 39 request_proto.ParseFromString(data) |
| 40 return PluginRequest(request_proto) |
| 41 |
| 42 |
| 43 class PluginResponse(object): |
| 44 def __init__(self): |
| 45 self.proto = plugin_pb2.CodeGeneratorResponse() |
| 46 |
| 47 def AddFileWithContent(self, filename, content): |
| 48 file_proto = self.proto.file.add() |
| 49 file_proto.name = filename |
| 50 file_proto.content = content |
| 51 |
| 52 def AddError(self, err): |
| 53 self.proto.error += err + '\n' |
| 54 |
| 55 def WriteToStdout(self): |
| 56 sys.stdout.write(self.proto.SerializeToString()) |
| 57 sys.stdout.flush() |
| 58 |
| 59 |
| 60 class ProtoFile(object): |
| 61 def __init__(self, proto): |
| 62 self.proto = proto |
| 63 self.qualified_types = types.QualifiedTypes( |
| 64 self.ProtoPackage(), |
| 65 self.JavaPackage() + '.' + self.JavaOuterClass(), |
| 66 self.CppBaseNamespace(), |
| 67 self.CppConverterNamespace() |
| 68 ) |
| 69 |
| 70 def Filename(self): |
| 71 return self.proto.name |
| 72 |
| 73 def CheckSupported(self): |
| 74 if self.proto.service: |
| 75 return 'Services are not supported' |
| 76 |
| 77 if self.proto.extension: |
| 78 return 'Extensions are not supported' |
| 79 |
| 80 for child in self.GetMessages() + self.GetEnums(): |
| 81 err = child.CheckSupported() |
| 82 if err: |
| 83 return err |
| 84 |
| 85 def ProtoPackage(self): |
| 86 return self.proto.package if self.proto.HasField('package') else '' |
| 87 |
| 88 def ProtoNamespaces(self): |
| 89 return self.ProtoPackage().split('.') |
| 90 |
| 91 def CppBaseNamespace(self): |
| 92 return '::'.join(self.ProtoNamespaces()) |
| 93 |
| 94 def CppBaseHeader(self): |
| 95 assert self.proto.name.endswith('.proto') |
| 96 return self.proto.name[:-5] + 'pb.h' |
| 97 |
| 98 def CppConverterNamespace(self): |
| 99 return self.CppBaseNamespace() + '::json' |
| 100 |
| 101 def JavaPackage(self): |
| 102 if self.proto.options.HasField('java_package'): |
| 103 return self.proto.options.java_package |
| 104 else: |
| 105 return self.ProtoPackage() |
| 106 |
| 107 def GetMessages(self): |
| 108 return [ProtoMessage(n, self.qualified_types) |
| 109 for n in self.proto.message_type] |
| 110 |
| 111 def GetEnums(self): |
| 112 return [ProtoEnum(n, self.qualified_types) for n in self.proto.enum_type] |
| 113 |
| 114 def GetDependencies(self): |
| 115 return map(plugin.GetProtoFileForFilename, self.proto.dependency) |
| 116 |
| 117 def JavaFilename(self): |
| 118 return '/'.join(self.JavaQualifiedOuterClass().split('.')) + '.java' |
| 119 |
| 120 def JavaOuterClass(self): |
| 121 if self.proto.options.HasField('java_outer_classname'): |
| 122 return self.proto.options.java_outer_classname |
| 123 basename, _ = os.path.splitext(os.path.basename(self.proto.name)) |
| 124 return plugin.TitleCase(basename) |
| 125 |
| 126 def JavaQualifiedOuterClass(self): |
| 127 return self.qualified_types.java |
| 128 |
| 129 def CppConverterFilename(self): |
| 130 assert self.proto.name.endswith('.proto') |
| 131 return self.proto.name[:-6] + '_json_converter.h' |
| 132 |
| 133 |
| 134 class ProtoMessage(object): |
| 135 def __init__(self, proto, parent_typenames): |
| 136 self.proto = proto |
| 137 self.qualified_types = types.QualifiedTypesForChild( |
| 138 proto.name, parent_typenames) |
| 139 |
| 140 def CheckSupported(self): |
| 141 if self.proto.extension_range: |
| 142 return 'Extensions are not supported: ' + self.proto.extension_range |
| 143 |
| 144 for child in self.GetFields() + self.GetMessages() + self.GetEnums(): |
| 145 err = child.CheckSupported() |
| 146 if err: |
| 147 return err |
| 148 |
| 149 def QualifiedTypes(self): |
| 150 return self.qualified_types |
| 151 |
| 152 def JavaClassName(self): |
| 153 return plugin.TitleCase(self.proto.name) |
| 154 |
| 155 def CppConverterClassName(self): |
| 156 return plugin.TitleCase(self.proto.name) |
| 157 |
| 158 def GetFields(self): |
| 159 return map(ProtoField, self.proto.field) |
| 160 |
| 161 def GetMessages(self): |
| 162 return [ProtoMessage(n, self.qualified_types) |
| 163 for n in self.proto.nested_type] |
| 164 |
| 165 def GetEnums(self): |
| 166 return [ProtoEnum(n, self.qualified_types) for n in self.proto.enum_type] |
| 167 |
| 168 |
| 169 class ProtoField(object): |
| 170 def __init__(self, field_proto): |
| 171 self.proto = field_proto |
| 172 self.name = field_proto.name |
| 173 |
| 174 if self.IsClassType() and not self.proto.HasField('type_name'): |
| 175 raise Error('expected type_name') |
| 176 |
| 177 def Extendee(self): |
| 178 return self.proto.extendee if self.proto.HasField('extendee') else None |
| 179 |
| 180 def IsOptional(self): |
| 181 return self.proto.label == FieldDescriptorProto.LABEL_OPTIONAL |
| 182 |
| 183 def IsRepeated(self): |
| 184 return self.proto.label == FieldDescriptorProto.LABEL_REPEATED |
| 185 |
| 186 def IsRequired(self): |
| 187 return self.proto.label == FieldDescriptorProto.LABEL_REQUIRED |
| 188 |
| 189 def IsClassType(self): |
| 190 return self.proto.type == FieldDescriptorProto.TYPE_MESSAGE |
| 191 |
| 192 def IsEnumType(self): |
| 193 return self.proto.type == FieldDescriptorProto.TYPE_ENUM |
| 194 |
| 195 def JavaType(self): |
| 196 if self.IsClassType(): |
| 197 return types.ResolveJavaClassType(self.proto.type_name) |
| 198 elif self.IsEnumType(): |
| 199 return 'int' |
| 200 else: |
| 201 return types.GetJavaPrimitiveType(self.proto.type) |
| 202 |
| 203 def JavaListType(self): |
| 204 return types.GetJavaObjectType(self.JavaType()) |
| 205 |
| 206 def JavascriptIndex(self): |
| 207 return self.proto.number |
| 208 |
| 209 def JavaName(self): |
| 210 return plugin.TitleCase(self.name) |
| 211 |
| 212 def CppConverterType(self): |
| 213 return types.ResolveCppConverterType(self.proto.type_name) |
| 214 |
| 215 def CppPrimitiveType(self): |
| 216 assert not self.IsClassType() |
| 217 return types.GetCppPrimitiveType(self.proto.type) |
| 218 |
| 219 def CppValueType(self): |
| 220 return types.GetCppValueType(self.CppPrimitiveType()) |
| 221 |
| 222 def CheckSupported(self): |
| 223 if self.Extendee(): |
| 224 return 'Unsupported field extension: ' + self.DebugString() |
| 225 |
| 226 if self.JavaType() is None: |
| 227 return 'Unsupported type for field: ' + self.DebugString() |
| 228 |
| 229 if self.IsRequired(): |
| 230 return 'Required fields not supported: ' + self.DebugString() |
| 231 |
| 232 if self.proto.HasField('default_value'): |
| 233 return 'Default values are not supported: ' + self.DebugString() |
| 234 |
| 235 return None |
| 236 |
| 237 def DebugString(self): |
| 238 return '{name}, {type}, {extendee}'.format( |
| 239 name=self.name, |
| 240 type=self.proto.type, |
| 241 extendee=self.Extendee()) |
| 242 |
| 243 |
| 244 class ProtoEnum(object): |
| 245 def __init__(self, proto, parent_typenames): |
| 246 self.proto = proto |
| 247 self.qualified_types = types.QualifiedTypesForChild( |
| 248 proto.name, parent_typenames) |
| 249 |
| 250 def CheckSupported(self): |
| 251 if self.proto.HasField('options'): |
| 252 return 'Enum options are not supported: ' + self.DebugString() |
| 253 for val in self.Values(): |
| 254 err = val.CheckSupported() |
| 255 if err: |
| 256 return err + ' ' + self.DebugString() |
| 257 |
| 258 def QualifiedTypes(self): |
| 259 return self.qualified_types |
| 260 |
| 261 def JavaName(self): |
| 262 return plugin.TitleCase(self.proto.name) |
| 263 |
| 264 def Values(self): |
| 265 return map(ProtoEnumValue, self.proto.value) |
| 266 |
| 267 |
| 268 class ProtoEnumValue(object): |
| 269 def __init__(self, enum_value_proto): |
| 270 self.proto = enum_value_proto |
| 271 |
| 272 def GetName(self): |
| 273 return self.proto.name |
| 274 |
| 275 def GetValue(self): |
| 276 return self.proto.number |
| 277 |
| 278 def CheckSupported(self): |
| 279 if self.proto.HasField('options'): |
| 280 return 'Enum value options are not supported: {} {}'.format( |
| 281 self.proto.name, self.proto.value) |
OLD | NEW |