source.go

  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//
 91//	.message_type[6].nested_type[15].field[3]
 92func (p SourcePath) String() string {
 93	b := p.appendFileDescriptorProto(nil)
 94	for _, i := range p {
 95		b = append(b, '.')
 96		b = strconv.AppendInt(b, int64(i), 10)
 97	}
 98	return string(b)
 99}
100
101type appendFunc func(*SourcePath, []byte) []byte
102
103func (p *SourcePath) appendSingularField(b []byte, name string, f appendFunc) []byte {
104	if len(*p) == 0 {
105		return b
106	}
107	b = append(b, '.')
108	b = append(b, name...)
109	*p = (*p)[1:]
110	if f != nil {
111		b = f(p, b)
112	}
113	return b
114}
115
116func (p *SourcePath) appendRepeatedField(b []byte, name string, f appendFunc) []byte {
117	b = p.appendSingularField(b, name, nil)
118	if len(*p) == 0 || (*p)[0] < 0 {
119		return b
120	}
121	b = append(b, '[')
122	b = strconv.AppendUint(b, uint64((*p)[0]), 10)
123	b = append(b, ']')
124	*p = (*p)[1:]
125	if f != nil {
126		b = f(p, b)
127	}
128	return b
129}