74 lines
1.6 KiB
Go
74 lines
1.6 KiB
Go
package spec
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"git.kmsign.ru/royalcat/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]
|
|
}
|
|
|
|
// ReferencingCode returns a string containing name of the referenced fields
|
|
// concatenating with period (.).
|
|
func (r FieldReference) ReferencingCode() string {
|
|
var fieldNames []string
|
|
for _, field := range r {
|
|
fieldNames = append(fieldNames, field.Name)
|
|
}
|
|
return strings.Join(fieldNames, ".")
|
|
}
|
|
|
|
type fieldResolver struct {
|
|
Structs map[string]code.Struct
|
|
}
|
|
|
|
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[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
|
|
}
|
|
}
|