repogen/internal/spec/field.go

64 lines
1.3 KiB
Go

package spec
import (
"strings"
"github.com/sunboyy/repogen/internal/code"
)
// FieldReference is a reference path to access to the field
type FieldReference []code.StructField
// ReferencedField returns the last struct field
func (r FieldReference) ReferencedField() code.StructField {
return r[len(r)-1]
}
type fieldResolver struct {
Structs code.Structs
}
func (r fieldResolver) ResolveStructField(structModel code.Struct, tokens []string) (FieldReference, bool) {
fieldName := strings.Join(tokens, "")
field, ok := structModel.Fields.ByName(fieldName)
if ok {
return FieldReference{field}, true
}
for i := len(tokens) - 1; i > 0; i-- {
fieldName := strings.Join(tokens[:i], "")
field, ok := structModel.Fields.ByName(fieldName)
if !ok {
continue
}
fieldSimpleType, ok := getSimpleType(field.Type)
if !ok {
continue
}
childStruct, ok := r.Structs.ByName(fieldSimpleType.Code())
if !ok {
continue
}
fields, ok := r.ResolveStructField(childStruct, tokens[i:])
if !ok {
continue
}
return append(FieldReference{field}, fields...), true
}
return nil, false
}
func getSimpleType(t code.Type) (code.SimpleType, bool) {
switch t := t.(type) {
case code.SimpleType:
return t, true
case code.PointerType:
return getSimpleType(t.ContainedType)
default:
return "", false
}
}