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 5package protoreflect 6 7import ( 8 "strconv" 9) 10 11// SourceLocations is a list of source locations. 12type 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. 36type 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. 68type SourcePath []int32 69 70// Equal reports whether p1 equals p2. 71func (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] 91func (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 100type appendFunc func(*SourcePath, []byte) []byte 101 102func (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 115func (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} 129