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  }