source.go 3.9 KB

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