github.com/ipld/go-ipld-prime@v0.21.0/schema/gen/go/templateUtil.go (about) 1 package gengo 2 3 import ( 4 "io" 5 "strings" 6 "text/template" 7 8 "github.com/ipld/go-ipld-prime/datamodel" 9 "github.com/ipld/go-ipld-prime/testutil" 10 ) 11 12 func doTemplate(tmplstr string, w io.Writer, adjCfg *AdjunctCfg, data interface{}) { 13 tmpl := template.Must(template.New(""). 14 Funcs(template.FuncMap{ 15 16 // These methods are used for symbol munging and appear constantly, so they need to be short. 17 // (You could also get at them through `.AdjCfg`, but going direct saves some screen real estate.) 18 "TypeSymbol": adjCfg.TypeSymbol, 19 "FieldSymbolLower": adjCfg.FieldSymbolLower, 20 "FieldSymbolUpper": adjCfg.FieldSymbolUpper, 21 "MaybeUsesPtr": adjCfg.MaybeUsesPtr, 22 "Comments": adjCfg.Comments, 23 24 // The whole AdjunctConfig can be accessed. 25 // Access methods like UnionMemlayout through this, as e.g. `.AdjCfg.UnionMemlayout`. 26 "AdjCfg": func() *AdjunctCfg { return adjCfg }, 27 28 // "dot" is a dummy value that's equal to the original `.` expression, but stays there. 29 // Use this if you're inside a range or other feature that shifted the dot and you want the original. 30 // (This may seem silly, but empirically, I found myself writing a dummy line to store the value of dot before endering a range clause >20 times; that's plenty.) 31 "dot": func() interface{} { return data }, 32 33 "KindPrim": func(k datamodel.Kind) string { 34 switch k { 35 case datamodel.Kind_Map: 36 panic("this isn't useful for non-scalars") 37 case datamodel.Kind_List: 38 panic("this isn't useful for non-scalars") 39 case datamodel.Kind_Null: 40 panic("this isn't useful for null") 41 case datamodel.Kind_Bool: 42 return "bool" 43 case datamodel.Kind_Int: 44 return "int64" 45 case datamodel.Kind_Float: 46 return "float64" 47 case datamodel.Kind_String: 48 return "string" 49 case datamodel.Kind_Bytes: 50 return "[]byte" 51 case datamodel.Kind_Link: 52 return "datamodel.Link" 53 default: 54 panic("invalid enumeration value!") 55 } 56 }, 57 "Kind": func(s string) datamodel.Kind { 58 switch s { 59 case "map": 60 return datamodel.Kind_Map 61 case "list": 62 return datamodel.Kind_List 63 case "null": 64 return datamodel.Kind_Null 65 case "bool": 66 return datamodel.Kind_Bool 67 case "int": 68 return datamodel.Kind_Int 69 case "float": 70 return datamodel.Kind_Float 71 case "string": 72 return datamodel.Kind_String 73 case "bytes": 74 return datamodel.Kind_Bytes 75 case "link": 76 return datamodel.Kind_Link 77 default: 78 panic("invalid enumeration value!") 79 } 80 }, 81 "KindSymbol": func(k datamodel.Kind) string { 82 switch k { 83 case datamodel.Kind_Map: 84 return "datamodel.Kind_Map" 85 case datamodel.Kind_List: 86 return "datamodel.Kind_List" 87 case datamodel.Kind_Null: 88 return "datamodel.Kind_Null" 89 case datamodel.Kind_Bool: 90 return "datamodel.Kind_Bool" 91 case datamodel.Kind_Int: 92 return "datamodel.Kind_Int" 93 case datamodel.Kind_Float: 94 return "datamodel.Kind_Float" 95 case datamodel.Kind_String: 96 return "datamodel.Kind_String" 97 case datamodel.Kind_Bytes: 98 return "datamodel.Kind_Bytes" 99 case datamodel.Kind_Link: 100 return "datamodel.Kind_Link" 101 default: 102 panic("invalid enumeration value!") 103 } 104 }, 105 "add": func(a, b int) int { return a + b }, 106 "title": func(s string) string { return strings.Title(s) }, //lint:ignore SA1019 cases.Title doesn't work for this 107 }). 108 Parse(testutil.Dedent(tmplstr))) 109 if err := tmpl.Execute(w, data); err != nil { 110 panic(err) 111 } 112 } 113 114 // We really need to do some more composable stuff around here. 115 // Generators should probably be carrying down their own doTemplate methods that curry customizations. 116 // E.g., map generators would benefit hugely from being able to make a clause for "entTypeStrung", "mTypeStrung", etc. 117 // 118 // Open question: how exactly? Should some of this stuff should be composed by: 119 // - composing template fragments; 120 // - amending the funcmap; 121 // - computing the whole result and injecting it as a string; 122 // - ... combinations of the above? 123 // Adding to the complexity of the question is that sometimes we want to be 124 // doing composition inside the output (e.g. DRY by functions in the result, 125 // rather than by DRY'ing the templates). 126 // Best practice to make this evolve nicely is not at all obvious to this author. 127 //