/
docstrings.go
105 lines (93 loc) · 2.87 KB
/
docstrings.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package protodocs
import (
"strings"
"google.golang.org/protobuf/types/descriptorpb"
)
func extractDocStrings(file *descriptorpb.FileDescriptorProto, docstrings map[string]string) {
for _, loc := range file.GetSourceCodeInfo().GetLocation() {
if len(loc.GetLeadingComments()) == 0 {
continue
}
name, ok := getFullName(file, loc.GetPath())
if !ok {
continue
}
docstrings[name] = loc.GetLeadingComments()
}
}
func getFullName(descriptor *descriptorpb.FileDescriptorProto, path []int32) (string, bool) {
name := strings.Builder{}
name.WriteString(descriptor.GetPackage())
switch path[0] {
case fileDescriptorProtoMessageTypeFieldNumber:
msg := descriptor.GetMessageType()[path[1]]
if !appendMessageToFullName(msg, path, &name) {
return "", false
}
case fileDescriptorProtoEnumTypeFieldNumber:
enum := descriptor.GetEnumType()[path[1]]
if !appendEnumToFullName(enum, path, &name) {
return "", false
}
case fileDescriptorProtoServiceFieldNumber:
service := descriptor.GetService()[path[1]]
appendNameComponent(service.GetName(), &name)
if len(path) > 2 {
if !appendMethodToFullName(service, path, &name) {
return "", false
}
}
default:
return "", false
}
return name.String(), true
}
func appendMethodToFullName(service *descriptorpb.ServiceDescriptorProto, path []int32, name *strings.Builder) bool {
if len(path) == 4 && path[2] == serviceDescriptorProtoMethodFieldNumber {
appendFieldComponent(service.GetMethod()[path[3]].GetName(), name)
return true
}
return false
}
func appendToFullName(descriptor *descriptorpb.DescriptorProto, path []int32, name *strings.Builder) bool {
switch path[0] {
case descriptorProtoFieldFieldNumber:
field := descriptor.GetField()[path[1]]
appendFieldComponent(field.GetName(), name)
return true
case descriptorProtoNestedTypeFieldNumber:
msg := descriptor.GetNestedType()[path[1]]
return appendMessageToFullName(msg, path, name)
case descriptorProtoEnumTypeFieldNumber:
enum := descriptor.GetEnumType()[path[1]]
return appendEnumToFullName(enum, path, name)
default:
return false
}
}
func appendMessageToFullName(msg *descriptorpb.DescriptorProto, path []int32, name *strings.Builder) bool {
appendNameComponent(msg.GetName(), name)
if len(path) > 2 {
appendToFullName(msg, path[2:], name)
}
return true
}
func appendEnumToFullName(enum *descriptorpb.EnumDescriptorProto, path []int32, name *strings.Builder) bool {
appendNameComponent(enum.GetName(), name)
if len(path) <= 2 {
return true
}
if path[2] == enumDescriptorProtoValueFieldNumber {
appendFieldComponent(enum.GetValue()[path[3]].GetName(), name)
return true
}
return false
}
func appendNameComponent(component string, name *strings.Builder) {
name.WriteByte('.')
name.WriteString(component)
}
func appendFieldComponent(component string, name *strings.Builder) {
name.WriteByte('/')
name.WriteString(component)
}