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

     1  package json
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/zclconf/go-cty/cty"
     7  	"github.com/zclconf/go-cty/cty/function"
     8  )
     9  
    10  // Function is a description of the JSON representation of the signature of
    11  // a function callable from the Terraform language.
    12  type Function struct {
    13  	// Name is the leaf name of the function, without any namespace prefix.
    14  	Name string `json:"name"`
    15  
    16  	Params        []FunctionParam `json:"params"`
    17  	VariadicParam *FunctionParam  `json:"variadic_param,omitempty"`
    18  
    19  	// ReturnType is type constraint which is a static approximation of the
    20  	// possibly-dynamic return type of the function.
    21  	ReturnType json.RawMessage `json:"return_type"`
    22  
    23  	Description     string `json:"description,omitempty"`
    24  	DescriptionKind string `json:"description_kind,omitempty"`
    25  }
    26  
    27  // FunctionParam represents a single parameter to a function, as represented
    28  // by type Function.
    29  type FunctionParam struct {
    30  	// Name is a name for the function which is used primarily for
    31  	// documentation purposes, because function arguments are positional
    32  	// and therefore don't appear directly in configuration source code.
    33  	Name string `json:"name"`
    34  
    35  	// Type is a type constraint which is a static approximation of the
    36  	// possibly-dynamic type of the parameter. Particular functions may
    37  	// have additional requirements that a type constraint alone cannot
    38  	// represent.
    39  	Type json.RawMessage `json:"type"`
    40  
    41  	// Maybe some of the other fields in function.Parameter would be
    42  	// interesting to describe here too, but we'll wait to see if there
    43  	// is a use-case first.
    44  
    45  	Description     string `json:"description,omitempty"`
    46  	DescriptionKind string `json:"description_kind,omitempty"`
    47  }
    48  
    49  // DescribeFunction returns a description of the signature of the given cty
    50  // function, as a pointer to this package's serializable type Function.
    51  func DescribeFunction(name string, f function.Function) *Function {
    52  	ret := &Function{
    53  		Name: name,
    54  	}
    55  
    56  	params := f.Params()
    57  	ret.Params = make([]FunctionParam, len(params))
    58  	typeCheckArgs := make([]cty.Type, len(params), len(params)+1)
    59  	for i, param := range params {
    60  		ret.Params[i] = describeFunctionParam(&param)
    61  		typeCheckArgs[i] = param.Type
    62  	}
    63  	if varParam := f.VarParam(); varParam != nil {
    64  		descParam := describeFunctionParam(varParam)
    65  		ret.VariadicParam = &descParam
    66  		typeCheckArgs = append(typeCheckArgs, varParam.Type)
    67  	}
    68  
    69  	retType, err := f.ReturnType(typeCheckArgs)
    70  	if err != nil {
    71  		// Getting an error when type-checking with exactly the type constraints
    72  		// the function called for is weird, so we'll just treat it as if it
    73  		// has a dynamic return type instead, for our purposes here.
    74  		// One reason this can happen is for a function which has a variadic
    75  		// parameter but has logic inside it which considers it invalid to
    76  		// specify exactly one argument for that parameter (since that's what
    77  		// we did in typeCheckArgs as an approximation of a valid call above.)
    78  		retType = cty.DynamicPseudoType
    79  	}
    80  
    81  	if raw, err := retType.MarshalJSON(); err != nil {
    82  		// Again, we'll treat any errors as if the function is dynamically
    83  		// typed because it would be weird to get here.
    84  		ret.ReturnType = json.RawMessage(`"dynamic"`)
    85  	} else {
    86  		ret.ReturnType = json.RawMessage(raw)
    87  	}
    88  
    89  	// We don't currently have any sense of descriptions for functions and
    90  	// their parameters, so we'll just leave those fields unpopulated for now.
    91  
    92  	return ret
    93  }
    94  
    95  func describeFunctionParam(p *function.Parameter) FunctionParam {
    96  	ret := FunctionParam{
    97  		Name: p.Name,
    98  	}
    99  
   100  	if raw, err := p.Type.MarshalJSON(); err != nil {
   101  		// We'll treat any errors as if the function is dynamically
   102  		// typed because it would be weird to get here.
   103  		ret.Type = json.RawMessage(`"dynamic"`)
   104  	} else {
   105  		ret.Type = json.RawMessage(raw)
   106  	}
   107  
   108  	// We don't currently have any sense of descriptions for functions and
   109  	// their parameters, so we'll just leave those fields unpopulated for now.
   110  
   111  	return ret
   112  }