github.com/gopherjs/gopherjs@v1.19.0-beta1.0.20240506212314-27071a8796e4/compiler/typesutil/signature.go (about) 1 package typesutil 2 3 import ( 4 "fmt" 5 "go/types" 6 ) 7 8 // Signature is a helper that provides convenient access to function 9 // signature type information. 10 type Signature struct { 11 Sig *types.Signature 12 } 13 14 // RequiredParams returns the number of required parameters in the function signature. 15 func (st Signature) RequiredParams() int { 16 l := st.Sig.Params().Len() 17 if st.Sig.Variadic() { 18 return l - 1 // Last parameter is a slice of variadic params. 19 } 20 return l 21 } 22 23 // VariadicType returns the slice-type corresponding to the signature's variadic 24 // parameter, or nil of the signature is not variadic. With the exception of 25 // the special-case `append([]byte{}, "string"...)`, the returned type is 26 // `*types.Slice` and `.Elem()` method can be used to get the type of individual 27 // arguments. 28 func (st Signature) VariadicType() types.Type { 29 if !st.Sig.Variadic() { 30 return nil 31 } 32 return st.Sig.Params().At(st.Sig.Params().Len() - 1).Type() 33 } 34 35 // Param returns the expected argument type for the i'th argument position. 36 // 37 // This function is able to return correct expected types for variadic calls 38 // both when ellipsis syntax (e.g. myFunc(requiredArg, optionalArgSlice...)) 39 // is used and when optional args are passed individually. 40 // 41 // The returned types may differ from the actual argument expression types if 42 // there is an implicit type conversion involved (e.g. passing a struct into a 43 // function that expects an interface). 44 func (st Signature) Param(i int, ellipsis bool) types.Type { 45 if i < st.RequiredParams() { 46 return st.Sig.Params().At(i).Type() 47 } 48 if !st.Sig.Variadic() { 49 // This should never happen if the code was type-checked successfully. 50 panic(fmt.Errorf("tried to access parameter %d of a non-variadic signature %s", i, st.Sig)) 51 } 52 if ellipsis { 53 return st.VariadicType() 54 } 55 return st.VariadicType().(*types.Slice).Elem() 56 } 57 58 // HasResults returns true if the function signature returns something. 59 func (st Signature) HasResults() bool { 60 return st.Sig.Results().Len() > 0 61 } 62 63 // HasNamedResults returns true if the function signature returns something and 64 // returned results are names (e.g. `func () (val int, err error)`). 65 func (st Signature) HasNamedResults() bool { 66 return st.HasResults() && st.Sig.Results().At(0).Name() != "" 67 }