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(¶m) 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 }