Test Failed
Push — main ( 973aa1...436074 )
by Christian
02:37
created

protoreflect.Kind.String   F

Complexity

Conditions 20

Size

Total Lines 40
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 20
eloc 40
nop 0
dl 0
loc 40
rs 0
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like protoreflect.Kind.String often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
// Copyright 2018 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
5
// Package protoreflect provides interfaces to dynamically manipulate messages.
6
//
7
// This package includes type descriptors which describe the structure of types
8
// defined in proto source files and value interfaces which provide the
9
// ability to examine and manipulate the contents of messages.
10
//
11
//
12
// Protocol Buffer Descriptors
13
//
14
// Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor)
15
// are immutable objects that represent protobuf type information.
16
// They are wrappers around the messages declared in descriptor.proto.
17
// Protobuf descriptors alone lack any information regarding Go types.
18
//
19
// Enums and messages generated by this module implement Enum and ProtoMessage,
20
// where the Descriptor and ProtoReflect.Descriptor accessors respectively
21
// return the protobuf descriptor for the values.
22
//
23
// The protobuf descriptor interfaces are not meant to be implemented by
24
// user code since they might need to be extended in the future to support
25
// additions to the protobuf language.
26
// The "google.golang.org/protobuf/reflect/protodesc" package converts between
27
// google.protobuf.DescriptorProto messages and protobuf descriptors.
28
//
29
//
30
// Go Type Descriptors
31
//
32
// A type descriptor (e.g., EnumType or MessageType) is a constructor for
33
// a concrete Go type that represents the associated protobuf descriptor.
34
// There is commonly a one-to-one relationship between protobuf descriptors and
35
// Go type descriptors, but it can potentially be a one-to-many relationship.
36
//
37
// Enums and messages generated by this module implement Enum and ProtoMessage,
38
// where the Type and ProtoReflect.Type accessors respectively
39
// return the protobuf descriptor for the values.
40
//
41
// The "google.golang.org/protobuf/types/dynamicpb" package can be used to
42
// create Go type descriptors from protobuf descriptors.
43
//
44
//
45
// Value Interfaces
46
//
47
// The Enum and Message interfaces provide a reflective view over an
48
// enum or message instance. For enums, it provides the ability to retrieve
49
// the enum value number for any concrete enum type. For messages, it provides
50
// the ability to access or manipulate fields of the message.
51
//
52
// To convert a proto.Message to a protoreflect.Message, use the
53
// former's ProtoReflect method. Since the ProtoReflect method is new to the
54
// v2 message interface, it may not be present on older message implementations.
55
// The "github.com/golang/protobuf/proto".MessageReflect function can be used
56
// to obtain a reflective view on older messages.
57
//
58
//
59
// Relationships
60
//
61
// The following diagrams demonstrate the relationships between
62
// various types declared in this package.
63
//
64
//
65
//	                       ┌───────────────────────────────────┐
66
//	                       V                                   │
67
//	   ┌────────────── New(n) ─────────────┐                   │
68
//	   │                                   │                   │
69
//	   │      ┌──── Descriptor() ──┐       │  ┌── Number() ──┐ │
70
//	   │      │                    V       V  │              V │
71
//	╔════════════╗  ╔════════════════╗  ╔════════╗  ╔════════════╗
72
//	║  EnumType  ║  ║ EnumDescriptor ║  ║  Enum  ║  ║ EnumNumber ║
73
//	╚════════════╝  ╚════════════════╝  ╚════════╝  ╚════════════╝
74
//	      Λ           Λ                   │ │
75
//	      │           └─── Descriptor() ──┘ │
76
//	      │                                 │
77
//	      └────────────────── Type() ───────┘
78
//
79
// • An EnumType describes a concrete Go enum type.
80
// It has an EnumDescriptor and can construct an Enum instance.
81
//
82
// • An EnumDescriptor describes an abstract protobuf enum type.
83
//
84
// • An Enum is a concrete enum instance. Generated enums implement Enum.
85
//
86
//
87
//	  ┌──────────────── New() ─────────────────┐
88
//	  │                                        │
89
//	  │         ┌─── Descriptor() ─────┐       │   ┌── Interface() ───┐
90
//	  │         │                      V       V   │                  V
91
//	╔═════════════╗  ╔═══════════════════╗  ╔═════════╗  ╔══════════════╗
92
//	║ MessageType ║  ║ MessageDescriptor ║  ║ Message ║  ║ ProtoMessage ║
93
//	╚═════════════╝  ╚═══════════════════╝  ╚═════════╝  ╚══════════════╝
94
//	       Λ           Λ                      │ │  Λ                  │
95
//	       │           └──── Descriptor() ────┘ │  └─ ProtoReflect() ─┘
96
//	       │                                    │
97
//	       └─────────────────── Type() ─────────┘
98
//
99
// • A MessageType describes a concrete Go message type.
100
// It has a MessageDescriptor and can construct a Message instance.
101
//
102
// • A MessageDescriptor describes an abstract protobuf message type.
103
//
104
// • A Message is a concrete message instance. Generated messages implement
105
// ProtoMessage, which can convert to/from a Message.
106
//
107
//
108
//	      ┌── TypeDescriptor() ──┐    ┌───── Descriptor() ─────┐
109
//	      │                      V    │                        V
110
//	╔═══════════════╗  ╔═════════════════════════╗  ╔═════════════════════╗
111
//	║ ExtensionType ║  ║ ExtensionTypeDescriptor ║  ║ ExtensionDescriptor ║
112
//	╚═══════════════╝  ╚═════════════════════════╝  ╚═════════════════════╝
113
//	      Λ                      │   │ Λ                      │ Λ
114
//	      └─────── Type() ───────┘   │ └─── may implement ────┘ │
115
//	                                 │                          │
116
//	                                 └────── implements ────────┘
117
//
118
// • An ExtensionType describes a concrete Go implementation of an extension.
119
// It has an ExtensionTypeDescriptor and can convert to/from
120
// abstract Values and Go values.
121
//
122
// • An ExtensionTypeDescriptor is an ExtensionDescriptor
123
// which also has an ExtensionType.
124
//
125
// • An ExtensionDescriptor describes an abstract protobuf extension field and
126
// may not always be an ExtensionTypeDescriptor.
127
package protoreflect
128
129
import (
130
	"fmt"
131
	"strings"
132
133
	"google.golang.org/protobuf/encoding/protowire"
134
	"google.golang.org/protobuf/internal/pragma"
135
)
136
137
type doNotImplement pragma.DoNotImplement
138
139
// ProtoMessage is the top-level interface that all proto messages implement.
140
// This is declared in the protoreflect package to avoid a cyclic dependency;
141
// use the proto.Message type instead, which aliases this type.
142
type ProtoMessage interface{ ProtoReflect() Message }
143
144
// Syntax is the language version of the proto file.
145
type Syntax syntax
146
147
type syntax int8 // keep exact type opaque as the int type may change
148
149
const (
150
	Proto2 Syntax = 2
151
	Proto3 Syntax = 3
152
)
153
154
// IsValid reports whether the syntax is valid.
155
func (s Syntax) IsValid() bool {
156
	switch s {
157
	case Proto2, Proto3:
158
		return true
159
	default:
160
		return false
161
	}
162
}
163
164
// String returns s as a proto source identifier (e.g., "proto2").
165
func (s Syntax) String() string {
166
	switch s {
167
	case Proto2:
168
		return "proto2"
169
	case Proto3:
170
		return "proto3"
171
	default:
172
		return fmt.Sprintf("<unknown:%d>", s)
173
	}
174
}
175
176
// GoString returns s as a Go source identifier (e.g., "Proto2").
177
func (s Syntax) GoString() string {
178
	switch s {
179
	case Proto2:
180
		return "Proto2"
181
	case Proto3:
182
		return "Proto3"
183
	default:
184
		return fmt.Sprintf("Syntax(%d)", s)
185
	}
186
}
187
188
// Cardinality determines whether a field is optional, required, or repeated.
189
type Cardinality cardinality
190
191
type cardinality int8 // keep exact type opaque as the int type may change
192
193
// Constants as defined by the google.protobuf.Cardinality enumeration.
194
const (
195
	Optional Cardinality = 1 // appears zero or one times
196
	Required Cardinality = 2 // appears exactly one time; invalid with Proto3
197
	Repeated Cardinality = 3 // appears zero or more times
198
)
199
200
// IsValid reports whether the cardinality is valid.
201
func (c Cardinality) IsValid() bool {
202
	switch c {
203
	case Optional, Required, Repeated:
204
		return true
205
	default:
206
		return false
207
	}
208
}
209
210
// String returns c as a proto source identifier (e.g., "optional").
211
func (c Cardinality) String() string {
212
	switch c {
213
	case Optional:
214
		return "optional"
215
	case Required:
216
		return "required"
217
	case Repeated:
218
		return "repeated"
219
	default:
220
		return fmt.Sprintf("<unknown:%d>", c)
221
	}
222
}
223
224
// GoString returns c as a Go source identifier (e.g., "Optional").
225
func (c Cardinality) GoString() string {
226
	switch c {
227
	case Optional:
228
		return "Optional"
229
	case Required:
230
		return "Required"
231
	case Repeated:
232
		return "Repeated"
233
	default:
234
		return fmt.Sprintf("Cardinality(%d)", c)
235
	}
236
}
237
238
// Kind indicates the basic proto kind of a field.
239
type Kind kind
240
241
type kind int8 // keep exact type opaque as the int type may change
242
243
// Constants as defined by the google.protobuf.Field.Kind enumeration.
244
const (
245
	BoolKind     Kind = 8
246
	EnumKind     Kind = 14
247
	Int32Kind    Kind = 5
248
	Sint32Kind   Kind = 17
249
	Uint32Kind   Kind = 13
250
	Int64Kind    Kind = 3
251
	Sint64Kind   Kind = 18
252
	Uint64Kind   Kind = 4
253
	Sfixed32Kind Kind = 15
254
	Fixed32Kind  Kind = 7
255
	FloatKind    Kind = 2
256
	Sfixed64Kind Kind = 16
257
	Fixed64Kind  Kind = 6
258
	DoubleKind   Kind = 1
259
	StringKind   Kind = 9
260
	BytesKind    Kind = 12
261
	MessageKind  Kind = 11
262
	GroupKind    Kind = 10
263
)
264
265
// IsValid reports whether the kind is valid.
266
func (k Kind) IsValid() bool {
267
	switch k {
268
	case BoolKind, EnumKind,
269
		Int32Kind, Sint32Kind, Uint32Kind,
270
		Int64Kind, Sint64Kind, Uint64Kind,
271
		Sfixed32Kind, Fixed32Kind, FloatKind,
272
		Sfixed64Kind, Fixed64Kind, DoubleKind,
273
		StringKind, BytesKind, MessageKind, GroupKind:
274
		return true
275
	default:
276
		return false
277
	}
278
}
279
280
// String returns k as a proto source identifier (e.g., "bool").
281
func (k Kind) String() string {
282
	switch k {
283
	case BoolKind:
284
		return "bool"
285
	case EnumKind:
286
		return "enum"
287
	case Int32Kind:
288
		return "int32"
289
	case Sint32Kind:
290
		return "sint32"
291
	case Uint32Kind:
292
		return "uint32"
293
	case Int64Kind:
294
		return "int64"
295
	case Sint64Kind:
296
		return "sint64"
297
	case Uint64Kind:
298
		return "uint64"
299
	case Sfixed32Kind:
300
		return "sfixed32"
301
	case Fixed32Kind:
302
		return "fixed32"
303
	case FloatKind:
304
		return "float"
305
	case Sfixed64Kind:
306
		return "sfixed64"
307
	case Fixed64Kind:
308
		return "fixed64"
309
	case DoubleKind:
310
		return "double"
311
	case StringKind:
312
		return "string"
313
	case BytesKind:
314
		return "bytes"
315
	case MessageKind:
316
		return "message"
317
	case GroupKind:
318
		return "group"
319
	default:
320
		return fmt.Sprintf("<unknown:%d>", k)
321
	}
322
}
323
324
// GoString returns k as a Go source identifier (e.g., "BoolKind").
325
func (k Kind) GoString() string {
326
	switch k {
327
	case BoolKind:
328
		return "BoolKind"
329
	case EnumKind:
330
		return "EnumKind"
331
	case Int32Kind:
332
		return "Int32Kind"
333
	case Sint32Kind:
334
		return "Sint32Kind"
335
	case Uint32Kind:
336
		return "Uint32Kind"
337
	case Int64Kind:
338
		return "Int64Kind"
339
	case Sint64Kind:
340
		return "Sint64Kind"
341
	case Uint64Kind:
342
		return "Uint64Kind"
343
	case Sfixed32Kind:
344
		return "Sfixed32Kind"
345
	case Fixed32Kind:
346
		return "Fixed32Kind"
347
	case FloatKind:
348
		return "FloatKind"
349
	case Sfixed64Kind:
350
		return "Sfixed64Kind"
351
	case Fixed64Kind:
352
		return "Fixed64Kind"
353
	case DoubleKind:
354
		return "DoubleKind"
355
	case StringKind:
356
		return "StringKind"
357
	case BytesKind:
358
		return "BytesKind"
359
	case MessageKind:
360
		return "MessageKind"
361
	case GroupKind:
362
		return "GroupKind"
363
	default:
364
		return fmt.Sprintf("Kind(%d)", k)
365
	}
366
}
367
368
// FieldNumber is the field number in a message.
369
type FieldNumber = protowire.Number
370
371
// FieldNumbers represent a list of field numbers.
372
type FieldNumbers interface {
373
	// Len reports the number of fields in the list.
374
	Len() int
375
	// Get returns the ith field number. It panics if out of bounds.
376
	Get(i int) FieldNumber
377
	// Has reports whether n is within the list of fields.
378
	Has(n FieldNumber) bool
379
380
	doNotImplement
381
}
382
383
// FieldRanges represent a list of field number ranges.
384
type FieldRanges interface {
385
	// Len reports the number of ranges in the list.
386
	Len() int
387
	// Get returns the ith range. It panics if out of bounds.
388
	Get(i int) [2]FieldNumber // start inclusive; end exclusive
389
	// Has reports whether n is within any of the ranges.
390
	Has(n FieldNumber) bool
391
392
	doNotImplement
393
}
394
395
// EnumNumber is the numeric value for an enum.
396
type EnumNumber int32
397
398
// EnumRanges represent a list of enum number ranges.
399
type EnumRanges interface {
400
	// Len reports the number of ranges in the list.
401
	Len() int
402
	// Get returns the ith range. It panics if out of bounds.
403
	Get(i int) [2]EnumNumber // start inclusive; end inclusive
404
	// Has reports whether n is within any of the ranges.
405
	Has(n EnumNumber) bool
406
407
	doNotImplement
408
}
409
410
// Name is the short name for a proto declaration. This is not the name
411
// as used in Go source code, which might not be identical to the proto name.
412
type Name string // e.g., "Kind"
413
414
// IsValid reports whether s is a syntactically valid name.
415
// An empty name is invalid.
416
func (s Name) IsValid() bool {
417
	return consumeIdent(string(s)) == len(s)
418
}
419
420
// Names represent a list of names.
421
type Names interface {
422
	// Len reports the number of names in the list.
423
	Len() int
424
	// Get returns the ith name. It panics if out of bounds.
425
	Get(i int) Name
426
	// Has reports whether s matches any names in the list.
427
	Has(s Name) bool
428
429
	doNotImplement
430
}
431
432
// FullName is a qualified name that uniquely identifies a proto declaration.
433
// A qualified name is the concatenation of the proto package along with the
434
// fully-declared name (i.e., name of parent preceding the name of the child),
435
// with a '.' delimiter placed between each Name.
436
//
437
// This should not have any leading or trailing dots.
438
type FullName string // e.g., "google.protobuf.Field.Kind"
439
440
// IsValid reports whether s is a syntactically valid full name.
441
// An empty full name is invalid.
442
func (s FullName) IsValid() bool {
443
	i := consumeIdent(string(s))
444
	if i < 0 {
445
		return false
446
	}
447
	for len(s) > i {
448
		if s[i] != '.' {
449
			return false
450
		}
451
		i++
452
		n := consumeIdent(string(s[i:]))
453
		if n < 0 {
454
			return false
455
		}
456
		i += n
457
	}
458
	return true
459
}
460
461
func consumeIdent(s string) (i int) {
462
	if len(s) == 0 || !isLetter(s[i]) {
463
		return -1
464
	}
465
	i++
466
	for len(s) > i && isLetterDigit(s[i]) {
467
		i++
468
	}
469
	return i
470
}
471
func isLetter(c byte) bool {
472
	return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
473
}
474
func isLetterDigit(c byte) bool {
475
	return isLetter(c) || ('0' <= c && c <= '9')
476
}
477
478
// Name returns the short name, which is the last identifier segment.
479
// A single segment FullName is the Name itself.
480
func (n FullName) Name() Name {
481
	if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
482
		return Name(n[i+1:])
483
	}
484
	return Name(n)
485
}
486
487
// Parent returns the full name with the trailing identifier removed.
488
// A single segment FullName has no parent.
489
func (n FullName) Parent() FullName {
490
	if i := strings.LastIndexByte(string(n), '.'); i >= 0 {
491
		return n[:i]
492
	}
493
	return ""
494
}
495
496
// Append returns the qualified name appended with the provided short name.
497
//
498
// Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid
499
func (n FullName) Append(s Name) FullName {
500
	if n == "" {
501
		return FullName(s)
502
	}
503
	return n + "." + FullName(s)
504
}
505