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: ¶meter{ 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 }