|
1 // Copyright 2019 The Go Authors. All rights reserved. |
|
2 // Use of this source code is governed by a BSD-style |
|
3 // license that can be found in the LICENSE file. |
|
4 |
|
5 package protoreflect |
|
6 |
|
7 import ( |
|
8 "strconv" |
|
9 ) |
|
10 |
|
11 // SourceLocations is a list of source locations. |
|
12 type SourceLocations interface { |
|
13 // Len reports the number of source locations in the proto file. |
|
14 Len() int |
|
15 // Get returns the ith SourceLocation. It panics if out of bounds. |
|
16 Get(int) SourceLocation |
|
17 |
|
18 // ByPath returns the SourceLocation for the given path, |
|
19 // returning the first location if multiple exist for the same path. |
|
20 // If multiple locations exist for the same path, |
|
21 // then SourceLocation.Next index can be used to identify the |
|
22 // index of the next SourceLocation. |
|
23 // If no location exists for this path, it returns the zero value. |
|
24 ByPath(path SourcePath) SourceLocation |
|
25 |
|
26 // ByDescriptor returns the SourceLocation for the given descriptor, |
|
27 // returning the first location if multiple exist for the same path. |
|
28 // If no location exists for this descriptor, it returns the zero value. |
|
29 ByDescriptor(desc Descriptor) SourceLocation |
|
30 |
|
31 doNotImplement |
|
32 } |
|
33 |
|
34 // SourceLocation describes a source location and |
|
35 // corresponds with the google.protobuf.SourceCodeInfo.Location message. |
|
36 type SourceLocation struct { |
|
37 // Path is the path to the declaration from the root file descriptor. |
|
38 // The contents of this slice must not be mutated. |
|
39 Path SourcePath |
|
40 |
|
41 // StartLine and StartColumn are the zero-indexed starting location |
|
42 // in the source file for the declaration. |
|
43 StartLine, StartColumn int |
|
44 // EndLine and EndColumn are the zero-indexed ending location |
|
45 // in the source file for the declaration. |
|
46 // In the descriptor.proto, the end line may be omitted if it is identical |
|
47 // to the start line. Here, it is always populated. |
|
48 EndLine, EndColumn int |
|
49 |
|
50 // LeadingDetachedComments are the leading detached comments |
|
51 // for the declaration. The contents of this slice must not be mutated. |
|
52 LeadingDetachedComments []string |
|
53 // LeadingComments is the leading attached comment for the declaration. |
|
54 LeadingComments string |
|
55 // TrailingComments is the trailing attached comment for the declaration. |
|
56 TrailingComments string |
|
57 |
|
58 // Next is an index into SourceLocations for the next source location that |
|
59 // has the same Path. It is zero if there is no next location. |
|
60 Next int |
|
61 } |
|
62 |
|
63 // SourcePath identifies part of a file descriptor for a source location. |
|
64 // The SourcePath is a sequence of either field numbers or indexes into |
|
65 // a repeated field that form a path starting from the root file descriptor. |
|
66 // |
|
67 // See google.protobuf.SourceCodeInfo.Location.path. |
|
68 type SourcePath []int32 |
|
69 |
|
70 // Equal reports whether p1 equals p2. |
|
71 func (p1 SourcePath) Equal(p2 SourcePath) bool { |
|
72 if len(p1) != len(p2) { |
|
73 return false |
|
74 } |
|
75 for i := range p1 { |
|
76 if p1[i] != p2[i] { |
|
77 return false |
|
78 } |
|
79 } |
|
80 return true |
|
81 } |
|
82 |
|
83 // String formats the path in a humanly readable manner. |
|
84 // The output is guaranteed to be deterministic, |
|
85 // making it suitable for use as a key into a Go map. |
|
86 // It is not guaranteed to be stable as the exact output could change |
|
87 // in a future version of this module. |
|
88 // |
|
89 // Example output: |
|
90 // .message_type[6].nested_type[15].field[3] |
|
91 func (p SourcePath) String() string { |
|
92 b := p.appendFileDescriptorProto(nil) |
|
93 for _, i := range p { |
|
94 b = append(b, '.') |
|
95 b = strconv.AppendInt(b, int64(i), 10) |
|
96 } |
|
97 return string(b) |
|
98 } |
|
99 |
|
100 type appendFunc func(*SourcePath, []byte) []byte |
|
101 |
|
102 func (p *SourcePath) appendSingularField(b []byte, name string, f appendFunc) []byte { |
|
103 if len(*p) == 0 { |
|
104 return b |
|
105 } |
|
106 b = append(b, '.') |
|
107 b = append(b, name...) |
|
108 *p = (*p)[1:] |
|
109 if f != nil { |
|
110 b = f(p, b) |
|
111 } |
|
112 return b |
|
113 } |
|
114 |
|
115 func (p *SourcePath) appendRepeatedField(b []byte, name string, f appendFunc) []byte { |
|
116 b = p.appendSingularField(b, name, nil) |
|
117 if len(*p) == 0 || (*p)[0] < 0 { |
|
118 return b |
|
119 } |
|
120 b = append(b, '[') |
|
121 b = strconv.AppendUint(b, uint64((*p)[0]), 10) |
|
122 b = append(b, ']') |
|
123 *p = (*p)[1:] |
|
124 if f != nil { |
|
125 b = f(p, b) |
|
126 } |
|
127 return b |
|
128 } |