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  //