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 descriptor | |
6 | |
7 import ( | |
8 "strings" | |
9 ) | |
10 | |
11 const ( | |
12 // NumberFileDescriptorProto_Package is the number of package field | |
13 // in FileDescriptorProto message. | |
14 NumberFileDescriptorProto_Package = 2 | |
15 // NumberFileDescriptorProto_Message is the number of message field | |
16 // in FileDescriptorProto message. | |
17 NumberFileDescriptorProto_Message = 4 | |
18 // NumberFileDescriptorProto_Enum is the number of enum field | |
19 // in FileDescriptorProto message. | |
20 NumberFileDescriptorProto_Enum = 5 | |
21 // NumberFileDescriptorProto_Service is the number of service field | |
22 // in FileDescriptorProto message. | |
23 NumberFileDescriptorProto_Service = 6 | |
24 | |
25 // NumberServiceDescriptorProto_Method is the number of method field | |
26 // in ServiceDescriptorProto message. | |
27 NumberServiceDescriptorProto_Method = 2 | |
28 | |
29 // NumberDescriptorProto_Field is the number of field field | |
30 // in DescriptorProto message. | |
31 NumberDescriptorProto_Field = 2 | |
32 // NumberDescriptorProto_NestedType is the number of nested_type field | |
33 // in DescriptorProto message. | |
34 NumberDescriptorProto_NestedType = 3 | |
35 // NumberDescriptorProto_EnumType is the number of enum_type field | |
36 // in DescriptorProto message. | |
37 NumberDescriptorProto_EnumType = 4 | |
38 // NumberDescriptorProto_OneOf is the number of oneof_decl field | |
39 // in DescriptorProto message. | |
40 NumberDescriptorProto_OneOf = 8 | |
41 | |
42 // NumberEnumDescriptorProto_Value is the number of value field | |
43 // in EnumDescriptorProto message. | |
44 NumberEnumDescriptorProto_Value = 2 | |
45 ) | |
46 | |
47 // splitFullName splits package name and service/type name. | |
48 func splitFullName(fullName string) (pkg string, name string) { | |
49 lastDot := strings.LastIndex(fullName, ".") | |
50 if lastDot < 0 { | |
51 return "", fullName | |
52 } | |
53 return fullName[:lastDot], fullName[lastDot+1:] | |
54 } | |
55 | |
56 //////////////////////////////////////////////////////////////////////////////// | |
57 // FileDescriptorSet | |
58 | |
59 // FindFile searches for a FileDescriptorProto by name. | |
60 func (s *FileDescriptorSet) FindFile(name string) int { | |
61 for i, x := range s.GetFile() { | |
62 if x.GetName() == name { | |
63 return i | |
64 } | |
65 } | |
66 return -1 | |
67 } | |
68 | |
69 // Resolve searches for an object by full name. obj can be one of | |
70 // *ServiceDescriptorProto, | |
71 // *MethodDescriptorProto, | |
72 // *DescriptorProto, | |
73 // *FieldDescriptorProto, | |
74 // *DescriptorProto, | |
75 // *EnumDescriptorProto, | |
76 // *EnumValueDescriptorProto or | |
77 // nil | |
78 // | |
79 // For path, see comment in SourceCodeInfo message. | |
80 func (s *FileDescriptorSet) Resolve(fullName string) (file *FileDescriptorProto,
obj interface{}, path []int) { | |
81 if fullName == "" { | |
82 return nil, nil, nil | |
83 } | |
84 pkg, name := splitFullName(fullName) | |
85 | |
86 // Check top-level objects. | |
87 for _, f := range s.GetFile() { | |
88 if f.GetPackage() == pkg { | |
89 if i := f.FindService(name); i != -1 { | |
90 return f, f.Service[i], []int{NumberFileDescript
orProto_Service, i} | |
91 } | |
92 if i := f.FindMessage(name); i != -1 { | |
93 return f, f.MessageType[i], []int{NumberFileDesc
riptorProto_Message, i} | |
94 } | |
95 if i := f.FindEnum(name); i != -1 { | |
96 return f, f.EnumType[i], []int{NumberFileDescrip
torProto_Enum, i} | |
97 } | |
98 } | |
99 } | |
100 | |
101 // Recurse. | |
102 var parent interface{} | |
103 file, parent, path = s.Resolve(pkg) | |
104 switch parent := parent.(type) { | |
105 | |
106 case *ServiceDescriptorProto: | |
107 if i := parent.FindMethod(name); i != -1 { | |
108 return file, parent.Method[i], append(path, NumberServic
eDescriptorProto_Method, i) | |
109 } | |
110 | |
111 case *DescriptorProto: | |
112 if i := parent.FindMessage(name); i != -1 { | |
113 return file, parent.NestedType[i], append(path, NumberDe
scriptorProto_NestedType, i) | |
114 } | |
115 if i := parent.FindEnum(name); i != -1 { | |
116 return file, parent.EnumType[i], append(path, NumberDesc
riptorProto_EnumType, i) | |
117 } | |
118 if i := parent.FindField(name); i != -1 { | |
119 return file, parent.Field[i], append(path, NumberDescrip
torProto_Field, i) | |
120 } | |
121 if i := parent.FindOneOf(name); i != -1 { | |
122 return file, parent.OneofDecl[i], append(path, NumberDes
criptorProto_OneOf, i) | |
123 } | |
124 | |
125 case *EnumDescriptorProto: | |
126 if i := parent.FindValue(name); i != -1 { | |
127 return file, parent.Value[i], append(path, NumberEnumDes
criptorProto_Value, i) | |
128 } | |
129 } | |
130 | |
131 return nil, nil, nil | |
132 } | |
133 | |
134 // FindService searches for a service by full name. | |
135 func (s *FileDescriptorSet) FindService(fullName string) (file *FileDescriptorPr
oto, serviceIndex int) { | |
136 pkg, name := splitFullName(fullName) | |
137 for _, f := range s.GetFile() { | |
138 if f.GetPackage() == pkg { | |
139 if i := f.FindService(name); i != -1 { | |
140 return f, i | |
141 } | |
142 } | |
143 } | |
144 return nil, -1 | |
145 } | |
146 | |
147 //////////////////////////////////////////////////////////////////////////////// | |
148 // FileDescriptorProto | |
149 | |
150 // FindService searches for a ServiceDescriptorProto by name. | |
151 func (f *FileDescriptorProto) FindService(name string) int { | |
152 for i, x := range f.GetService() { | |
153 if x.GetName() == name { | |
154 return i | |
155 } | |
156 } | |
157 return -1 | |
158 } | |
159 | |
160 // FindMessage searches for a DescriptorProto by name. | |
161 func (f *FileDescriptorProto) FindMessage(name string) int { | |
162 for i, x := range f.GetMessageType() { | |
163 if x.GetName() == name { | |
164 return i | |
165 } | |
166 } | |
167 return -1 | |
168 } | |
169 | |
170 // FindEnum searches for an EnumDescriptorProto by name. | |
171 func (f *FileDescriptorProto) FindEnum(name string) int { | |
172 for i, x := range f.GetEnumType() { | |
173 if x.GetName() == name { | |
174 return i | |
175 } | |
176 } | |
177 return -1 | |
178 } | |
179 | |
180 //////////////////////////////////////////////////////////////////////////////// | |
181 // ServiceDescriptorProto | |
182 | |
183 // FindMethod searches for a MethodDescriptorProto by name. | |
184 func (s *ServiceDescriptorProto) FindMethod(name string) int { | |
185 for i, x := range s.GetMethod() { | |
186 if x.GetName() == name { | |
187 return i | |
188 } | |
189 } | |
190 return -1 | |
191 } | |
192 | |
193 //////////////////////////////////////////////////////////////////////////////// | |
194 // DescriptorProto (a message) | |
195 | |
196 // FindField searches for a FieldDescriptorProto by name. | |
197 func (d *DescriptorProto) FindField(name string) int { | |
198 for i, x := range d.GetField() { | |
199 if x.GetName() == name { | |
200 return i | |
201 } | |
202 } | |
203 return -1 | |
204 } | |
205 | |
206 // FindMessage searches for a nested DescriptorProto by name. | |
207 func (d *DescriptorProto) FindMessage(name string) int { | |
208 for i, x := range d.GetNestedType() { | |
209 if x.GetName() == name { | |
210 return i | |
211 } | |
212 } | |
213 return -1 | |
214 } | |
215 | |
216 // FindEnum searches for a nested EnumDescriptorProto by name. | |
217 func (d *DescriptorProto) FindEnum(name string) int { | |
218 for i, x := range d.GetEnumType() { | |
219 if x.GetName() == name { | |
220 return i | |
221 } | |
222 } | |
223 return -1 | |
224 } | |
225 | |
226 // FindOneOf searches for a nested OneofDescriptorProto by name. | |
227 func (d *DescriptorProto) FindOneOf(name string) int { | |
228 for i, x := range d.GetOneofDecl() { | |
229 if x.GetName() == name { | |
230 return i | |
231 } | |
232 } | |
233 return -1 | |
234 } | |
235 | |
236 //////////////////////////////////////////////////////////////////////////////// | |
237 // FieldDescriptorProto | |
238 | |
239 // Repeated returns true if the field is repeated. | |
240 func (f *FieldDescriptorProto) Repeated() bool { | |
241 return f.GetLabel() == FieldDescriptorProto_LABEL_REPEATED | |
242 } | |
243 | |
244 //////////////////////////////////////////////////////////////////////////////// | |
245 // EnumDescriptorProto | |
246 | |
247 // FindValue searches for an EnumValueDescriptorProto by name. | |
248 func (e *EnumDescriptorProto) FindValue(name string) int { | |
249 for i, x := range e.GetValue() { | |
250 if x.GetName() == name { | |
251 return i | |
252 } | |
253 } | |
254 return -1 | |
255 } | |
256 | |
257 // FindValueByNumber searches for an EnumValueDescriptorProto by number. | |
258 func (e *EnumDescriptorProto) FindValueByNumber(number int32) int { | |
259 for i, x := range e.GetValue() { | |
260 if x.GetNumber() == number { | |
261 return i | |
262 } | |
263 } | |
264 return -1 | |
265 } | |
266 | |
267 //////////////////////////////////////////////////////////////////////////////// | |
268 // SourceCodeInfo | |
269 | |
270 // FindLocation searches for a location by path. | |
271 func (s *SourceCodeInfo) FindLocation(path []int) *SourceCodeInfo_Location { | |
272 Outer: | |
273 for _, l := range s.GetLocation() { | |
274 if len(path) != len(l.Path) { | |
275 continue | |
276 } | |
277 for i := range path { | |
278 if int32(path[i]) != l.Path[i] { | |
279 continue Outer | |
280 } | |
281 } | |
282 return l | |
283 } | |
284 return nil | |
285 } | |
OLD | NEW |