Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(139)

Side by Side Diff: client/cmd/rpc/printer.go

Issue 1587323003: client/cmd/rpc: RPC CLI (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@discovery
Patch Set: check status Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package main
6
7 import (
8 "fmt"
9 "io"
10 "strings"
11
12 "github.com/luci/luci-go/common/indented"
13 "github.com/luci/luci-go/common/proto/google/descriptor"
14 )
15
16 // printer prints a proto3 definition from a description.
17 // Does not support options.
18 type printer struct {
19 // File is the file containing the desriptors being printed.
20 // Used to relativize names and print comments.
21 File *descriptor.FileDescriptorProto
22 Out indented.Writer
23
24 // Err is not nil if writing to Out failed.
25 Err error
26 }
27
28 func newPrinter(out io.Writer) *printer {
29 return &printer{Out: indented.Writer{Writer: out}}
30 }
31
32 // Printf prints to p.Out unless there was an error.
33 func (p *printer) Printf(format string, a ...interface{}) {
34 if p.Err == nil {
35 _, p.Err = fmt.Fprintf(&p.Out, format, a...)
36 }
37 }
38
39 // Package prints package declaration.
40 func (p *printer) Package(name string) {
41 p.Printf("package %s;\n", name)
42 }
43
44 // open prints a string, followed by " {\n" and increases indentation level.
45 // Returns a function that decreases indentation level and closes the brace.
46 // Usage: defer open("package x")()
47 func (p *printer) open(format string, a ...interface{}) func() {
48 p.Printf(format, a...)
49 p.Printf(" {\n")
50 p.Out.Level++
51 return func() {
52 p.Out.Level--
53 p.Printf("}\n")
54 }
55 }
56
57 // MaybeLeadingComments prints leading comments of the protobuf entity
58 // at path, if found.
59 //
60 // For path, see comment in SourceCodeInfo.Location message in
61 // common/proto/google/descriptor/descriptor.proto.
62 func (p *printer) MaybeLeadingComments(path []int) {
63 if p.File == nil || p.File.SourceCodeInfo == nil || len(path) == 0 {
64 return
65 }
66
67 loc := p.File.SourceCodeInfo.FindLocation(path)
68 if loc == nil {
69 return
70 }
71
72 comments := loc.GetLeadingComments()
73 // print comments, but insert "//" before each newline.
74 for len(comments) > 0 {
75 var toPrint string
76 if lineEnd := strings.Index(comments, "\n"); lineEnd >= 0 {
77 toPrint = comments[:lineEnd+1] // includes newline
78 comments = comments[lineEnd+1:]
79 } else {
80 // actually this does not happen, because comments alway s end with
81 // newline, but just in case.
82 toPrint = comments + "\n"
83 comments = ""
84 }
85 p.Printf("//%s", toPrint)
86 }
87 }
88
89 // shorten removes leading "." and trims package name if it matches p.File.
90 func (p *printer) shorten(name string) string {
91 name = strings.TrimPrefix(name, ".")
92 if p.File != nil && p.File.GetPackage() != "" {
93 name = strings.TrimPrefix(name, p.File.GetPackage()+".")
94 }
95 return name
96 }
97
98 // Service prints a service definition.
99 // If methodIndex != -1, only one method is printed.
100 // If serviceIndex != -1, leading comments are printed if found.
101 func (p *printer) Service(service *descriptor.ServiceDescriptorProto, serviceInd ex, methodIndex int) {
102 var path []int
103 if serviceIndex != -1 {
104 path = []int{descriptor.NumberFileDescriptorProto_Service, servi ceIndex}
105 p.MaybeLeadingComments(path)
106 }
107 defer p.open("service %s", service.GetName())()
108
109 printMethod := func(i int) {
110 var methodPath []int
111 if path != nil {
112 methodPath = append(path, descriptor.NumberServiceDescri ptorProto_Method, i)
113 }
114 p.Method(service.Method[i], methodPath)
115 }
116
117 if methodIndex < 0 {
118 for i := range service.Method {
119 printMethod(i)
120 }
121 } else {
122 printMethod(methodIndex)
123 if len(service.Method) > 1 {
124 p.Printf("// other methods were omitted.\n")
125 }
126 }
127 }
128
129 // Method prints a service method definition.
130 //
131 // If path is specified, leading comments are printed if found.
132 // See also comment in SourceCodeInfo.Location message in
133 // common/proto/google/descriptor/descriptor.proto.
134 func (p *printer) Method(method *descriptor.MethodDescriptorProto, path []int) {
135 p.MaybeLeadingComments(path)
136 p.Printf(
137 "rpc %s(%s) returns (%s) {};\n",
138 method.GetName(),
139 p.shorten(method.GetInputType()),
140 p.shorten(method.GetOutputType()),
141 )
142 }
143
144 var fieldTypeName = map[descriptor.FieldDescriptorProto_Type]string{
145 descriptor.FieldDescriptorProto_TYPE_DOUBLE: "double",
146 descriptor.FieldDescriptorProto_TYPE_FLOAT: "float",
147 descriptor.FieldDescriptorProto_TYPE_INT64: "int64",
148 descriptor.FieldDescriptorProto_TYPE_UINT64: "uint64",
149 descriptor.FieldDescriptorProto_TYPE_INT32: "int32",
150 descriptor.FieldDescriptorProto_TYPE_FIXED64: "fixed64",
151 descriptor.FieldDescriptorProto_TYPE_FIXED32: "fixed32",
152 descriptor.FieldDescriptorProto_TYPE_BOOL: "bool",
153 descriptor.FieldDescriptorProto_TYPE_STRING: "string",
154 descriptor.FieldDescriptorProto_TYPE_BYTES: "bytes",
155 descriptor.FieldDescriptorProto_TYPE_UINT32: "uint32",
156 descriptor.FieldDescriptorProto_TYPE_SFIXED32: "sfixed32",
157 descriptor.FieldDescriptorProto_TYPE_SFIXED64: "sfixed64",
158 descriptor.FieldDescriptorProto_TYPE_SINT32: "sint32",
159 descriptor.FieldDescriptorProto_TYPE_SINT64: "sint64",
160 }
161
162 // Field prints a field definition.
163 //
164 // If path is specified, leading comments are printed if found.
165 // See also comment in SourceCodeInfo.Location message in
166 // common/proto/google/descriptor/descriptor.proto.
167 func (p *printer) Field(field *descriptor.FieldDescriptorProto, path []int) {
168 p.MaybeLeadingComments(path)
169 if field.GetLabel() == descriptor.FieldDescriptorProto_LABEL_REPEATED {
170 p.Printf("repeated ")
171 }
172
173 typeName := fieldTypeName[field.GetType()]
174 if typeName == "" {
175 typeName = p.shorten(field.GetTypeName())
176 }
177 if typeName == "" {
178 typeName = "<unsupported type>"
179 }
180 p.Printf("%s %s = %d;\n", typeName, field.GetName(), field.GetNumber())
181 }
182
183 // Message prints a message definition.
184 //
185 // If path is specified, leading comments are printed if found.
186 // See also comment in SourceCodeInfo.Location message in
187 // common/proto/google/descriptor/descriptor.proto.
188 func (p *printer) Message(msg *descriptor.DescriptorProto, path []int) {
189 p.MaybeLeadingComments(path)
190 defer p.open("message %s", msg.GetName())()
191
192 for i := range msg.GetOneofDecl() {
193 p.OneOf(msg, i, path)
194 }
195
196 for i, f := range msg.Field {
197 if f.OneofIndex == nil {
198 var fieldPath []int
199 if len(path) > 0 {
200 fieldPath = append(path, descriptor.NumberDescri ptorProto_Field, i)
201 }
202 p.Field(msg.Field[i], fieldPath)
203 }
204 }
205 }
206
207 // OneOf prints a oneof definition.
208 //
209 // If path is specified, leading comments are printed if found.
210 // See also comment in SourceCodeInfo.Location message in
211 // common/proto/google/descriptor/descriptor.proto.
212 func (p *printer) OneOf(msg *descriptor.DescriptorProto, oneOfIndex int, msgPath []int) {
213 of := msg.GetOneofDecl()[oneOfIndex]
214 if len(msgPath) > 0 {
215 p.MaybeLeadingComments(append(msgPath, descriptor.NumberDescript orProto_OneOf, oneOfIndex))
216 }
217 defer p.open("oneof %s", of.GetName())()
218
219 for i, f := range msg.Field {
220 if f.OneofIndex != nil && int(f.GetOneofIndex()) == oneOfIndex {
221 var fieldPath []int
222 if len(msgPath) > 0 {
223 fieldPath = append(msgPath, descriptor.NumberDes criptorProto_Field, i)
224 }
225 p.Field(msg.Field[i], fieldPath)
226 }
227 }
228 }
229
230 // Enum prints an enum definition.
231 //
232 // If path is specified, leading comments are printed if found.
233 // See also comment in SourceCodeInfo.Location message in
234 // common/proto/google/descriptor/descriptor.proto.
235 func (p *printer) Enum(enum *descriptor.EnumDescriptorProto, path []int) {
236 p.MaybeLeadingComments(path)
237 defer p.open("enum %s", enum.GetName())()
238
239 for i, v := range enum.Value {
240 var valuePath []int
241 if len(path) > 0 {
242 valuePath = append(path, descriptor.NumberEnumDescriptor Proto_Value, i)
243 }
244 p.EnumValue(v, valuePath)
245 }
246 }
247
248 // EnumValue prints an enum value definition.
249 //
250 // If path is specified, leading comments are printed if found.
251 // See also comment in SourceCodeInfo.Location message in
252 // common/proto/google/descriptor/descriptor.proto.
253 func (p *printer) EnumValue(v *descriptor.EnumValueDescriptorProto, path []int) {
254 p.MaybeLeadingComments(path)
255 p.Printf("%s = %d;\n", v.GetName(), v.GetNumber())
256 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698