func()

in plugin/modelgen/models.go [353:463]


func (m *Plugin) generateField(
	cfg *config.Config,
	binder *config.Binder,
	schemaType *ast.Definition,
	field *ast.FieldDefinition,
) (*Field, error) {
	var typ types.Type
	fieldDef := cfg.Schema.Types[field.Type.Name()]

	if cfg.Models.UserDefined(field.Type.Name()) {
		var err error
		typ, err = binder.FindTypeFromName(cfg.Models[field.Type.Name()].Model[0])
		if err != nil {
			return nil, err
		}
	} else {
		switch fieldDef.Kind {
		case ast.Scalar:
			// no user defined model, referencing a default scalar
			typ = types.NewNamed(
				types.NewTypeName(0, cfg.Model.Pkg(), "string", nil),
				nil,
				nil,
			)

		case ast.Interface, ast.Union:
			// no user defined model, referencing a generated interface type
			typ = types.NewNamed(
				types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
				types.NewInterfaceType([]*types.Func{}, []types.Type{}),
				nil,
			)

		case ast.Enum:
			// no user defined model, must reference a generated enum
			typ = types.NewNamed(
				types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
				nil,
				nil,
			)

		case ast.Object, ast.InputObject:
			// no user defined model, must reference a generated struct
			typ = types.NewNamed(
				types.NewTypeName(0, cfg.Model.Pkg(), templates.ToGo(field.Type.Name()), nil),
				types.NewStruct(nil, nil),
				nil,
			)

		default:
			panic(fmt.Errorf("unknown ast type %s", fieldDef.Kind))
		}
	}

	name := templates.ToGo(field.Name)
	if nameOverride := cfg.Models[schemaType.Name].Fields[field.Name].FieldName; nameOverride != "" {
		name = nameOverride
	}

	typ = binder.CopyModifiersFromAst(field.Type, typ)

	if cfg.StructFieldsAlwaysPointers {
		if isStruct(typ) && (fieldDef.Kind == ast.Object || fieldDef.Kind == ast.InputObject) {
			typ = types.NewPointer(typ)
		}
	}

	f := &Field{
		Name:        field.Name,
		GoName:      name,
		Type:        typ,
		Description: field.Description,
		Tag:         getStructTagFromField(cfg, field),
		Omittable:   cfg.NullableInputOmittable && schemaType.Kind == ast.InputObject && !field.Type.NonNull,
		IsResolver:  cfg.Models[schemaType.Name].Fields[field.Name].Resolver,
	}

	if omittable := cfg.Models[schemaType.Name].Fields[field.Name].Omittable; omittable != nil {
		f.Omittable = *omittable
	}

	if m.FieldHook != nil {
		mf, err := m.FieldHook(schemaType, field, f)
		if err != nil {
			return nil, fmt.Errorf("generror: field %v.%v: %w", schemaType.Name, field.Name, err)
		}
		f = mf
	}

	if f.IsResolver && cfg.OmitResolverFields {
		return nil, nil
	}

	if f.Omittable {
		if schemaType.Kind != ast.InputObject || field.Type.NonNull {
			return nil, fmt.Errorf("generror: field %v.%v: omittable is only applicable to nullable input fields", schemaType.Name, field.Name)
		}

		omittableType, err := binder.FindTypeFromName("github.com/99designs/gqlgen/graphql.Omittable")
		if err != nil {
			return nil, err
		}

		f.Type, err = binder.InstantiateType(omittableType, []types.Type{f.Type})
		if err != nil {
			return nil, fmt.Errorf("generror: field %v.%v: %w", schemaType.Name, field.Name, err)
		}
	}

	return f, nil
}