github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonfunction/function.go (about)

     1  package jsonfunction
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/hashicorp/terraform/internal/tfdiags"
     8  	"github.com/zclconf/go-cty/cty"
     9  	"github.com/zclconf/go-cty/cty/function"
    10  )
    11  
    12  // FormatVersion represents the version of the json format and will be
    13  // incremented for any change to this format that requires changes to a
    14  // consuming parser.
    15  const FormatVersion = "1.0"
    16  
    17  // functions is the top-level object returned when exporting function signatures
    18  type functions struct {
    19  	FormatVersion string                        `json:"format_version"`
    20  	Signatures    map[string]*FunctionSignature `json:"function_signatures,omitempty"`
    21  }
    22  
    23  // FunctionSignature represents a function signature.
    24  type FunctionSignature struct {
    25  	// Description is an optional human-readable description
    26  	// of the function
    27  	Description string `json:"description,omitempty"`
    28  
    29  	// ReturnTypes is the ctyjson representation of the function's
    30  	// return types based on supplying all parameters using
    31  	// dynamic types. Functions can have dynamic return types.
    32  	ReturnType cty.Type `json:"return_type"`
    33  
    34  	// Parameters describes the function's fixed positional parameters.
    35  	Parameters []*parameter `json:"parameters,omitempty"`
    36  
    37  	// VariadicParameter describes the function's variadic
    38  	// parameters, if any are supported.
    39  	VariadicParameter *parameter `json:"variadic_parameter,omitempty"`
    40  }
    41  
    42  func newFunctions() *functions {
    43  	signatures := make(map[string]*FunctionSignature)
    44  	return &functions{
    45  		FormatVersion: FormatVersion,
    46  		Signatures:    signatures,
    47  	}
    48  }
    49  
    50  func Marshal(f map[string]function.Function) ([]byte, tfdiags.Diagnostics) {
    51  	var diags tfdiags.Diagnostics
    52  	signatures := newFunctions()
    53  
    54  	for name, v := range f {
    55  		if name == "can" {
    56  			signatures.Signatures[name] = marshalCan(v)
    57  		} else if name == "try" {
    58  			signatures.Signatures[name] = marshalTry(v)
    59  		} else {
    60  			signature, err := marshalFunction(v)
    61  			if err != nil {
    62  				diags = diags.Append(tfdiags.Sourceless(
    63  					tfdiags.Error,
    64  					fmt.Sprintf("Failed to serialize function %q", name),
    65  					err.Error(),
    66  				))
    67  			}
    68  			signatures.Signatures[name] = signature
    69  		}
    70  	}
    71  
    72  	if diags.HasErrors() {
    73  		return nil, diags
    74  	}
    75  
    76  	ret, err := json.Marshal(signatures)
    77  	if err != nil {
    78  		diags = diags.Append(tfdiags.Sourceless(
    79  			tfdiags.Error,
    80  			"Failed to serialize functions",
    81  			err.Error(),
    82  		))
    83  		return nil, diags
    84  	}
    85  	return ret, nil
    86  }
    87  
    88  func marshalFunction(f function.Function) (*FunctionSignature, error) {
    89  	var err error
    90  	var vp *parameter
    91  	if f.VarParam() != nil {
    92  		vp = marshalParameter(f.VarParam())
    93  	}
    94  
    95  	var p []*parameter
    96  	if len(f.Params()) > 0 {
    97  		p = marshalParameters(f.Params())
    98  	}
    99  
   100  	r, err := getReturnType(f)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	return &FunctionSignature{
   106  		Description:       f.Description(),
   107  		ReturnType:        r,
   108  		Parameters:        p,
   109  		VariadicParameter: vp,
   110  	}, nil
   111  }
   112  
   113  // marshalTry returns a static function signature for the try function.
   114  // We need this exception because the function implementation uses capsule
   115  // types that we can't marshal.
   116  func marshalTry(try function.Function) *FunctionSignature {
   117  	return &FunctionSignature{
   118  		Description: try.Description(),
   119  		ReturnType:  cty.DynamicPseudoType,
   120  		VariadicParameter: &parameter{
   121  			Name:        try.VarParam().Name,
   122  			Description: try.VarParam().Description,
   123  			IsNullable:  try.VarParam().AllowNull,
   124  			Type:        cty.DynamicPseudoType,
   125  		},
   126  	}
   127  }
   128  
   129  // marshalCan returns a static function signature for the can function.
   130  // We need this exception because the function implementation uses capsule
   131  // types that we can't marshal.
   132  func marshalCan(can function.Function) *FunctionSignature {
   133  	return &FunctionSignature{
   134  		Description: can.Description(),
   135  		ReturnType:  cty.Bool,
   136  		Parameters: []*parameter{
   137  			{
   138  				Name:        can.Params()[0].Name,
   139  				Description: can.Params()[0].Description,
   140  				IsNullable:  can.Params()[0].AllowNull,
   141  				Type:        cty.DynamicPseudoType,
   142  			},
   143  		},
   144  	}
   145  }