github.com/niko0xdev/gqlgen@v0.17.55-0.20240120102243-2ecff98c3e37/codegen/args.go (about)

     1  package codegen
     2  
     3  import (
     4  	"fmt"
     5  	"go/types"
     6  	"strings"
     7  
     8  	"github.com/vektah/gqlparser/v2/ast"
     9  
    10  	"github.com/niko0xdev/gqlgen/codegen/config"
    11  	"github.com/niko0xdev/gqlgen/codegen/templates"
    12  )
    13  
    14  type ArgSet struct {
    15  	Args     []*FieldArgument
    16  	FuncDecl string
    17  }
    18  
    19  type FieldArgument struct {
    20  	*ast.ArgumentDefinition
    21  	TypeReference *config.TypeReference
    22  	VarName       string      // The name of the var in go
    23  	Object        *Object     // A link back to the parent object
    24  	Default       interface{} // The default value
    25  	Directives    []*Directive
    26  	Value         interface{} // value set in Data
    27  }
    28  
    29  // ImplDirectives get not Builtin and location ARGUMENT_DEFINITION directive
    30  func (f *FieldArgument) ImplDirectives() []*Directive {
    31  	d := make([]*Directive, 0)
    32  	for i := range f.Directives {
    33  		if !f.Directives[i].Builtin && f.Directives[i].IsLocation(ast.LocationArgumentDefinition) {
    34  			d = append(d, f.Directives[i])
    35  		}
    36  	}
    37  
    38  	return d
    39  }
    40  
    41  func (f *FieldArgument) DirectiveObjName() string {
    42  	return "rawArgs"
    43  }
    44  
    45  func (f *FieldArgument) Stream() bool {
    46  	return f.Object != nil && f.Object.Stream
    47  }
    48  
    49  func (b *builder) buildArg(obj *Object, arg *ast.ArgumentDefinition) (*FieldArgument, error) {
    50  	tr, err := b.Binder.TypeReference(arg.Type, nil)
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	argDirs, err := b.getDirectives(arg.Directives)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	newArg := FieldArgument{
    60  		ArgumentDefinition: arg,
    61  		TypeReference:      tr,
    62  		Object:             obj,
    63  		VarName:            templates.ToGoPrivate(arg.Name),
    64  		Directives:         argDirs,
    65  	}
    66  
    67  	if arg.DefaultValue != nil {
    68  		newArg.Default, err = arg.DefaultValue.Value(nil)
    69  		if err != nil {
    70  			return nil, fmt.Errorf("default value is not valid: %w", err)
    71  		}
    72  	}
    73  
    74  	return &newArg, nil
    75  }
    76  
    77  func (b *builder) bindArgs(field *Field, sig *types.Signature, params *types.Tuple) ([]*FieldArgument, error) {
    78  	n := params.Len()
    79  	newArgs := make([]*FieldArgument, 0, len(field.Args))
    80  	// Accept variadic methods (i.e. have optional parameters).
    81  	if params.Len() > len(field.Args) && sig.Variadic() {
    82  		n = len(field.Args)
    83  	}
    84  nextArg:
    85  	for j := 0; j < n; j++ {
    86  		param := params.At(j)
    87  		for _, oldArg := range field.Args {
    88  			if strings.EqualFold(oldArg.Name, param.Name()) {
    89  				tr, err := b.Binder.TypeReference(oldArg.Type, param.Type())
    90  				if err != nil {
    91  					return nil, err
    92  				}
    93  				oldArg.TypeReference = tr
    94  
    95  				newArgs = append(newArgs, oldArg)
    96  				continue nextArg
    97  			}
    98  		}
    99  
   100  		// no matching arg found, abort
   101  		return nil, fmt.Errorf("arg %s not in schema", param.Name())
   102  	}
   103  
   104  	return newArgs, nil
   105  }
   106  
   107  func (d *Data) Args() map[string][]*FieldArgument {
   108  	ret := map[string][]*FieldArgument{}
   109  	for _, o := range d.Objects {
   110  		for _, f := range o.Fields {
   111  			if len(f.Args) > 0 {
   112  				ret[f.ArgsFunc()] = f.Args
   113  			}
   114  		}
   115  	}
   116  
   117  	for _, directive := range d.Directives() {
   118  		if len(directive.Args) > 0 {
   119  			ret[directive.ArgsFunc()] = directive.Args
   120  		}
   121  	}
   122  	return ret
   123  }