78 lines
1.7 KiB
Go
78 lines
1.7 KiB
Go
|
package generator
|
||
|
|
||
|
import (
|
||
|
"strings"
|
||
|
|
||
|
"github.com/jhump/protoreflect/desc"
|
||
|
"github.com/vektah/gqlparser/v2/ast"
|
||
|
any "google.golang.org/protobuf/types/known/anypb"
|
||
|
)
|
||
|
|
||
|
type ObjectDescriptor struct {
|
||
|
*ast.Definition
|
||
|
desc.Descriptor
|
||
|
|
||
|
types []*ObjectDescriptor
|
||
|
fields []*FieldDescriptor
|
||
|
fieldNames map[string]*FieldDescriptor
|
||
|
}
|
||
|
|
||
|
func (o *ObjectDescriptor) AsGraphql() *ast.Definition {
|
||
|
return o.Definition
|
||
|
}
|
||
|
|
||
|
func (o *ObjectDescriptor) uniqueName(f *desc.FieldDescriptor) string {
|
||
|
return strings.Title(f.GetName())
|
||
|
}
|
||
|
|
||
|
func (o *ObjectDescriptor) IsInput() bool {
|
||
|
return o.Kind == ast.InputObject
|
||
|
}
|
||
|
|
||
|
func (o *ObjectDescriptor) GetFields() []*FieldDescriptor {
|
||
|
return o.fields
|
||
|
}
|
||
|
|
||
|
func (o *ObjectDescriptor) GetTypes() []*ObjectDescriptor {
|
||
|
return o.types
|
||
|
}
|
||
|
|
||
|
func (o *ObjectDescriptor) IsMessage() bool {
|
||
|
_, ok := o.Descriptor.(*desc.MessageDescriptor)
|
||
|
return ok
|
||
|
}
|
||
|
|
||
|
// same isEmpty but for mortals
|
||
|
func IsEmpty(o *desc.MessageDescriptor) bool { return isEmpty(o, NewCallstack()) }
|
||
|
|
||
|
// make sure objects are fulled with all objects
|
||
|
func isEmpty(o *desc.MessageDescriptor, callstack Callstack) bool {
|
||
|
callstack.Push(o)
|
||
|
defer callstack.Pop(o)
|
||
|
|
||
|
if len(o.GetFields()) == 0 {
|
||
|
return true
|
||
|
}
|
||
|
for _, f := range o.GetFields() {
|
||
|
objType := f.GetMessageType()
|
||
|
if objType == nil {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// check if the call stack already contains a reference to this type and prevent it from calling itself again
|
||
|
if callstack.Has(objType) {
|
||
|
return true
|
||
|
}
|
||
|
if !isEmpty(objType, callstack) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
// TODO maybe not compare by strings
|
||
|
func IsAny(o *desc.MessageDescriptor) bool {
|
||
|
return string((&any.Any{}).ProtoReflect().Descriptor().FullName()) == o.GetFullyQualifiedName()
|
||
|
}
|