github.com/lheiskan/zebrapack@v4.1.1-0.20181107023619-e955d028f9bf+incompatible/parse/directives.go (about) 1 package parse 2 3 import ( 4 "fmt" 5 "github.com/glycerine/zebrapack/gen" 6 "go/ast" 7 "strings" 8 ) 9 10 const linePrefix = "//msgp:" 11 12 // func(args, fileset) 13 type directive func([]string, *FileSet) error 14 15 // func(passName, args, printer) 16 type passDirective func(gen.Method, []string, *gen.Printer) error 17 18 // map of all recognized directives 19 // 20 // to add a directive, define a func([]string, *FileSet) error 21 // and then add it to this list. 22 var directives = map[string]directive{ 23 "shim": applyShim, 24 "ignore": ignore, 25 "tuple": astuple, 26 } 27 28 var passDirectives = map[string]passDirective{ 29 "ignore": passignore, 30 } 31 32 func passignore(m gen.Method, text []string, p *gen.Printer) error { 33 pushstate(m.String()) 34 for _, a := range text { 35 p.ApplyDirective(m, gen.IgnoreTypename(a)) 36 infof("ignoring %s\n", a) 37 } 38 popstate() 39 return nil 40 } 41 42 // find all comment lines that begin with //msgp: 43 func yieldComments(c []*ast.CommentGroup) []string { 44 var out []string 45 for _, cg := range c { 46 for _, line := range cg.List { 47 if strings.HasPrefix(line.Text, linePrefix) { 48 out = append(out, strings.TrimPrefix(line.Text, linePrefix)) 49 } 50 } 51 } 52 return out 53 } 54 55 //msgp:shim {Type} as:{Newtype} using:{toFunc/fromFunc} 56 func applyShim(text []string, f *FileSet) error { 57 if len(text) != 4 { 58 return fmt.Errorf("shim directive should have 3 arguments; found %d", len(text)-1) 59 } 60 61 name := text[1] 62 be := gen.Ident(strings.TrimPrefix(strings.TrimSpace(text[2]), "as:"), false) // parse as::{base} 63 if name[0] == '*' { 64 name = name[1:] 65 be.Needsref(true) 66 } 67 be.Alias(name) 68 69 usestr := strings.TrimPrefix(strings.TrimSpace(text[3]), "using:") // parse using::{method/method} 70 71 methods := strings.Split(usestr, "/") 72 if len(methods) != 2 { 73 return fmt.Errorf("expected 2 using::{} methods; found %d (%q)", len(methods), text[3]) 74 } 75 76 be.ShimToBase = methods[0] 77 be.ShimFromBase = methods[1] 78 79 infof("%s -> %s\n", name, be.Value.String()) 80 f.findShim(name, be) 81 82 return nil 83 } 84 85 //msgp:ignore {TypeA} {TypeB}... 86 func ignore(text []string, f *FileSet) error { 87 if len(text) < 2 { 88 return nil 89 } 90 for _, item := range text[1:] { 91 name := strings.TrimSpace(item) 92 if _, ok := f.Identities[name]; ok { 93 delete(f.Identities, name) 94 infof("ignoring %s\n", name) 95 } 96 } 97 return nil 98 } 99 100 //msgp:tuple {TypeA} {TypeB}... 101 func astuple(text []string, f *FileSet) error { 102 if len(text) < 2 { 103 return nil 104 } 105 for _, item := range text[1:] { 106 name := strings.TrimSpace(item) 107 if el, ok := f.Identities[name]; ok { 108 if st, ok := el.(*gen.Struct); ok { 109 st.AsTuple = true 110 infoln(name) 111 } else { 112 warnf("%s: only structs can be tuples\n", name) 113 } 114 } 115 } 116 return nil 117 }