OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package descutil |
| 6 |
| 7 import ( |
| 8 "strings" |
| 9 |
| 10 pb "google.golang.org/genproto/protobuf" |
| 11 ) |
| 12 |
| 13 // splitFullName splits package name and service/type name. |
| 14 func splitFullName(fullName string) (pkg string, name string) { |
| 15 lastDot := strings.LastIndex(fullName, ".") |
| 16 if lastDot < 0 { |
| 17 return "", fullName |
| 18 } |
| 19 return fullName[:lastDot], fullName[lastDot+1:] |
| 20 } |
| 21 |
| 22 //////////////////////////////////////////////////////////////////////////////// |
| 23 // FileDescriptorSet |
| 24 |
| 25 // FindFile searches for a FileDescriptorProto by name. |
| 26 func FindFile(s *pb.FileDescriptorSet, name string) int { |
| 27 for i, x := range s.GetFile() { |
| 28 if x.GetName() == name { |
| 29 return i |
| 30 } |
| 31 } |
| 32 return -1 |
| 33 } |
| 34 |
| 35 // Resolve searches for an object by full name. obj can be one of |
| 36 // *ServiceDescriptorProto, |
| 37 // *MethodDescriptorProto, |
| 38 // *DescriptorProto, |
| 39 // *FieldDescriptorProto, |
| 40 // *DescriptorProto, |
| 41 // *EnumDescriptorProto, |
| 42 // *EnumValueDescriptorProto or |
| 43 // nil |
| 44 // |
| 45 // For path, see comment in SourceCodeInfo message. |
| 46 func Resolve(s *pb.FileDescriptorSet, fullName string) (file *pb.FileDescriptorP
roto, obj interface{}, path []int) { |
| 47 if fullName == "" { |
| 48 return nil, nil, nil |
| 49 } |
| 50 pkg, name := splitFullName(fullName) |
| 51 |
| 52 // Check top-level objects. |
| 53 for _, f := range s.GetFile() { |
| 54 if f.GetPackage() == pkg { |
| 55 if i := FindServiceForFile(f, name); i != -1 { |
| 56 return f, f.Service[i], []int{FileDescriptorProt
oServiceTag, i} |
| 57 } |
| 58 if i := FindMessageForFile(f, name); i != -1 { |
| 59 return f, f.MessageType[i], []int{FileDescriptor
ProtoMessageTag, i} |
| 60 } |
| 61 if i := FindEnumForFile(f, name); i != -1 { |
| 62 return f, f.EnumType[i], []int{FileDescriptorPro
toEnumTag, i} |
| 63 } |
| 64 } |
| 65 } |
| 66 |
| 67 // Recurse. |
| 68 var parent interface{} |
| 69 file, parent, path = Resolve(s, pkg) |
| 70 switch parent := parent.(type) { |
| 71 |
| 72 case *pb.ServiceDescriptorProto: |
| 73 if i := FindMethodForService(parent, name); i != -1 { |
| 74 return file, parent.Method[i], append(path, ServiceDescr
iptorProtoMethodTag, i) |
| 75 } |
| 76 |
| 77 case *pb.DescriptorProto: |
| 78 if i := FindMessage(parent, name); i != -1 { |
| 79 return file, parent.NestedType[i], append(path, Descript
orProtoNestedTypeTag, i) |
| 80 } |
| 81 if i := FindEnum(parent, name); i != -1 { |
| 82 return file, parent.EnumType[i], append(path, Descriptor
ProtoEnumTypeTag, i) |
| 83 } |
| 84 if i := FindField(parent, name); i != -1 { |
| 85 return file, parent.Field[i], append(path, DescriptorPro
toFieldTag, i) |
| 86 } |
| 87 if i := FindOneOf(parent, name); i != -1 { |
| 88 return file, parent.OneofDecl[i], append(path, Descripto
rProtoOneOfTag, i) |
| 89 } |
| 90 |
| 91 case *pb.EnumDescriptorProto: |
| 92 if i := FindEnumValue(parent, name); i != -1 { |
| 93 return file, parent.Value[i], append(path, EnumDescripto
rProtoValueTag, i) |
| 94 } |
| 95 } |
| 96 |
| 97 return nil, nil, nil |
| 98 } |
| 99 |
| 100 // FindService searches for a service by full name. |
| 101 func FindService(s *pb.FileDescriptorSet, fullName string) (file *pb.FileDescrip
torProto, serviceIndex int) { |
| 102 pkg, name := splitFullName(fullName) |
| 103 for _, f := range s.GetFile() { |
| 104 if f.GetPackage() == pkg { |
| 105 if i := FindServiceForFile(f, name); i != -1 { |
| 106 return f, i |
| 107 } |
| 108 } |
| 109 } |
| 110 return nil, -1 |
| 111 } |
| 112 |
| 113 //////////////////////////////////////////////////////////////////////////////// |
| 114 // FileDescriptorProto |
| 115 |
| 116 // FindServiceForFile searches for a FileDescriptorProto by name. |
| 117 func FindServiceForFile(f *pb.FileDescriptorProto, name string) int { |
| 118 for i, x := range f.GetService() { |
| 119 if x.GetName() == name { |
| 120 return i |
| 121 } |
| 122 } |
| 123 return -1 |
| 124 } |
| 125 |
| 126 // FindMessageForFile searches for a DescriptorProto by name. |
| 127 func FindMessageForFile(f *pb.FileDescriptorProto, name string) int { |
| 128 for i, x := range f.GetMessageType() { |
| 129 if x.GetName() == name { |
| 130 return i |
| 131 } |
| 132 } |
| 133 return -1 |
| 134 } |
| 135 |
| 136 // FindEnumForFile searches for an EnumDescriptorProto by name. |
| 137 func FindEnumForFile(f *pb.FileDescriptorProto, name string) int { |
| 138 for i, x := range f.GetEnumType() { |
| 139 if x.GetName() == name { |
| 140 return i |
| 141 } |
| 142 } |
| 143 return -1 |
| 144 } |
| 145 |
| 146 //////////////////////////////////////////////////////////////////////////////// |
| 147 // ServiceDescriptorProto |
| 148 |
| 149 // FindMethodForService searches for a MethodDescriptorProto by name. |
| 150 func FindMethodForService(s *pb.ServiceDescriptorProto, name string) int { |
| 151 for i, x := range s.GetMethod() { |
| 152 if x.GetName() == name { |
| 153 return i |
| 154 } |
| 155 } |
| 156 return -1 |
| 157 } |
| 158 |
| 159 //////////////////////////////////////////////////////////////////////////////// |
| 160 // DescriptorProto (a message) |
| 161 |
| 162 // FindField searches for a FieldDescriptorProto by name. |
| 163 func FindField(d *pb.DescriptorProto, name string) int { |
| 164 for i, x := range d.GetField() { |
| 165 if x.GetName() == name { |
| 166 return i |
| 167 } |
| 168 } |
| 169 return -1 |
| 170 } |
| 171 |
| 172 // FindMessage searches for a nested DescriptorProto by name. |
| 173 func FindMessage(d *pb.DescriptorProto, name string) int { |
| 174 for i, x := range d.GetNestedType() { |
| 175 if x.GetName() == name { |
| 176 return i |
| 177 } |
| 178 } |
| 179 return -1 |
| 180 } |
| 181 |
| 182 // FindEnum searches for a nested EnumDescriptorProto by name. |
| 183 func FindEnum(d *pb.DescriptorProto, name string) int { |
| 184 for i, x := range d.GetEnumType() { |
| 185 if x.GetName() == name { |
| 186 return i |
| 187 } |
| 188 } |
| 189 return -1 |
| 190 } |
| 191 |
| 192 // FindOneOf searches for a nested OneofDescriptorProto by name. |
| 193 func FindOneOf(d *pb.DescriptorProto, name string) int { |
| 194 for i, x := range d.GetOneofDecl() { |
| 195 if x.GetName() == name { |
| 196 return i |
| 197 } |
| 198 } |
| 199 return -1 |
| 200 } |
| 201 |
| 202 //////////////////////////////////////////////////////////////////////////////// |
| 203 // FieldDescriptorProto |
| 204 |
| 205 // Repeated returns true if the field is repeated. |
| 206 func Repeated(f *pb.FieldDescriptorProto) bool { |
| 207 return f.GetLabel() == pb.FieldDescriptorProto_LABEL_REPEATED |
| 208 } |
| 209 |
| 210 //////////////////////////////////////////////////////////////////////////////// |
| 211 // EnumDescriptorProto |
| 212 |
| 213 // FindEnumValue searches for an EnumValueDescriptorProto by name. |
| 214 func FindEnumValue(e *pb.EnumDescriptorProto, name string) int { |
| 215 for i, x := range e.GetValue() { |
| 216 if x.GetName() == name { |
| 217 return i |
| 218 } |
| 219 } |
| 220 return -1 |
| 221 } |
| 222 |
| 223 // FindValueByNumber searches for an EnumValueDescriptorProto by number. |
| 224 func FindValueByNumber(e *pb.EnumDescriptorProto, number int32) int { |
| 225 for i, x := range e.GetValue() { |
| 226 if x.GetNumber() == number { |
| 227 return i |
| 228 } |
| 229 } |
| 230 return -1 |
| 231 } |
| 232 |
| 233 //////////////////////////////////////////////////////////////////////////////// |
| 234 // SourceCodeInfo |
| 235 |
| 236 // FindLocation searches for a location by path. |
| 237 func FindLocation(s *pb.SourceCodeInfo, path []int) *pb.SourceCodeInfo_Location
{ |
| 238 Outer: |
| 239 for _, l := range s.GetLocation() { |
| 240 if len(path) != len(l.Path) { |
| 241 continue |
| 242 } |
| 243 for i := range path { |
| 244 if int32(path[i]) != l.Path[i] { |
| 245 continue Outer |
| 246 } |
| 247 } |
| 248 return l |
| 249 } |
| 250 return nil |
| 251 } |
OLD | NEW |