|
| 1 | +// Copyright (C) 2019-2022, Xiongfa Li. |
| 2 | +// @author xiongfa.li |
| 3 | +// @version V1.0 |
| 4 | +// Description: |
| 5 | + |
| 6 | +package generator |
| 7 | + |
| 8 | +import ( |
| 9 | + "fmt" |
| 10 | + "io" |
| 11 | + "k8s.io/gengo/args" |
| 12 | + "k8s.io/gengo/examples/set-gen/sets" |
| 13 | + "k8s.io/gengo/generator" |
| 14 | + "k8s.io/gengo/namer" |
| 15 | + "k8s.io/gengo/types" |
| 16 | + "k8s.io/klog/v2" |
| 17 | + "path/filepath" |
| 18 | + "strings" |
| 19 | +) |
| 20 | + |
| 21 | +const ( |
| 22 | + delimiterLeft = "{{" |
| 23 | + delimiterRight = "}}" |
| 24 | +) |
| 25 | + |
| 26 | +var ( |
| 27 | + gobatisImports = []string{"github.com/xfali/gobatis"} |
| 28 | +) |
| 29 | + |
| 30 | +type gobatisAnnotion struct { |
| 31 | + rawTypeName string |
| 32 | + body string |
| 33 | +} |
| 34 | + |
| 35 | +type gobatisAnnotions map[string]*gobatisAnnotion |
| 36 | + |
| 37 | +type gobatisGen struct { |
| 38 | + name string |
| 39 | + prefix string |
| 40 | + targetPkg string |
| 41 | + pkg *types.Package |
| 42 | + imports namer.ImportTracker |
| 43 | +} |
| 44 | + |
| 45 | +func NameSystems() namer.NameSystems { |
| 46 | + return namer.NameSystems{ |
| 47 | + "public": namer.NewPrivateNamer(0, ""), |
| 48 | + "raw": namer.NewRawNamer("", nil), |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +func DefaultNameSystem() string { |
| 53 | + return "public" |
| 54 | +} |
| 55 | + |
| 56 | +func checkEnable(annotation string, comments []string) bool { |
| 57 | + key := annotation + "enable" |
| 58 | + for _, c := range comments { |
| 59 | + if strings.HasPrefix(c, key) { |
| 60 | + return true |
| 61 | + } |
| 62 | + } |
| 63 | + return false |
| 64 | +} |
| 65 | + |
| 66 | +func GenPackages(ctx *generator.Context, args *args.GeneratorArgs) generator.Packages { |
| 67 | + inputs := sets.NewString(ctx.Inputs...) |
| 68 | + pkgs := generator.Packages{} |
| 69 | + annotation := args.CustomArgs.(fmt.Stringer).String() |
| 70 | + |
| 71 | + boilerplate, err := args.LoadGoBoilerplate() |
| 72 | + if err != nil { |
| 73 | + klog.Warningf("LoadGoBoilerplate failed: %v. ", err) |
| 74 | + boilerplate = nil |
| 75 | + } |
| 76 | + header := []byte(fmt.Sprintf("// +build !%s\n\n", args.GeneratedBuildTag)) |
| 77 | + if boilerplate != nil { |
| 78 | + header = append(header, boilerplate...) |
| 79 | + } |
| 80 | + |
| 81 | + for i, dir := range inputs { |
| 82 | + klog.V(5).Infof("Parsing pkg %s\n", dir) |
| 83 | + pkg := ctx.Universe[i] |
| 84 | + if pkg == nil { |
| 85 | + continue |
| 86 | + } |
| 87 | + for _, i := range pkg.Imports { |
| 88 | + ctx.AddDirectory(i.Path) |
| 89 | + } |
| 90 | + |
| 91 | + if !checkEnable(annotation, pkg.Comments) { |
| 92 | + continue |
| 93 | + } |
| 94 | + |
| 95 | + klog.V(5).Infof("Generating package %s...\n", dir) |
| 96 | + |
| 97 | + pkgs = append(pkgs, &generator.DefaultPackage{ |
| 98 | + PackageName: strings.Split(filepath.Base(pkg.Path), ".")[0], |
| 99 | + PackagePath: pkg.Path, |
| 100 | + HeaderText: header, |
| 101 | + GeneratorFunc: func(context *generator.Context) []generator.Generator { |
| 102 | + return []generator.Generator{ |
| 103 | + NewGobatisGenerator(args.OutputFileBaseName, annotation, pkg), |
| 104 | + } |
| 105 | + }, |
| 106 | + FilterFunc: func(context *generator.Context, i *types.Type) bool { |
| 107 | + return i.Name.Package == pkg.Path |
| 108 | + }, |
| 109 | + }) |
| 110 | + } |
| 111 | + return pkgs |
| 112 | +} |
| 113 | + |
| 114 | +func NewGobatisGenerator(name, prefix string, pkg *types.Package) *gobatisGen { |
| 115 | + ret := &gobatisGen{ |
| 116 | + name: name, |
| 117 | + prefix: prefix, |
| 118 | + pkg: pkg, |
| 119 | + imports: generator.NewImportTracker(), |
| 120 | + } |
| 121 | + |
| 122 | + return ret |
| 123 | +} |
| 124 | + |
| 125 | +// The name of this generator. Will be included in generated comments. |
| 126 | +func (g *gobatisGen) Name() string { |
| 127 | + return g.name |
| 128 | +} |
| 129 | + |
| 130 | +// Filter should return true if this generator cares about this type. |
| 131 | +// (otherwise, GenerateType will not be called.) |
| 132 | +// |
| 133 | +// Filter is called before any of the generator's other functions; |
| 134 | +// subsequent calls will get a context with only the types that passed |
| 135 | +// this filter. |
| 136 | +func (g *gobatisGen) Filter(ctx *generator.Context, t *types.Type) bool { |
| 137 | + return true |
| 138 | +} |
| 139 | + |
| 140 | +// If this generator needs special namers, return them here. These will |
| 141 | +// override the original namers in the context if there is a collision. |
| 142 | +// You may return nil if you don't need special names. These names will |
| 143 | +// be available in the context passed to the rest of the generator's |
| 144 | +// functions. |
| 145 | +// |
| 146 | +// A use case for this is to return a namer that tracks imports. |
| 147 | +func (g *gobatisGen) Namers(ctx *generator.Context) namer.NameSystems { |
| 148 | + return namer.NameSystems{ |
| 149 | + "raw": namer.NewRawNamer(g.targetPkg, g.imports), |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +// Init should write an init function, and any other content that's not |
| 154 | +// generated per-type. (It's not intended for generator specific |
| 155 | +// initialization! Do that when your Package constructs the |
| 156 | +// Generators.) |
| 157 | +func (g *gobatisGen) Init(ctx *generator.Context, w io.Writer) error { |
| 158 | + return nil |
| 159 | +} |
| 160 | + |
| 161 | +// Finalize should write finish up functions, and any other content that's not |
| 162 | +// generated per-type. |
| 163 | +func (g *gobatisGen) Finalize(ctx *generator.Context, w io.Writer) error { |
| 164 | + return nil |
| 165 | +} |
| 166 | + |
| 167 | +// PackageVars should emit an array of variable lines. They will be |
| 168 | +// placed in a var ( ... ) block. There's no need to include a leading |
| 169 | +// \t or trailing \n. |
| 170 | +func (g *gobatisGen) PackageVars(ctx *generator.Context) []string { |
| 171 | + return nil |
| 172 | +} |
| 173 | + |
| 174 | +// PackageConsts should emit an array of constant lines. They will be |
| 175 | +// placed in a const ( ... ) block. There's no need to include a leading |
| 176 | +// \t or trailing \n. |
| 177 | +func (g *gobatisGen) PackageConsts(ctx *generator.Context) []string { |
| 178 | + return nil |
| 179 | +} |
| 180 | + |
| 181 | +// GenerateType should emit the code for a particular type. |
| 182 | +func (g *gobatisGen) GenerateType(ctx *generator.Context, t *types.Type, w io.Writer) error { |
| 183 | + sw := generator.NewSnippetWriter(w, ctx, delimiterLeft, delimiterRight) |
| 184 | + sw = sw |
| 185 | + return nil |
| 186 | +} |
| 187 | + |
| 188 | +func parseAnnotations(annotation string, t *types.Type) gobatisAnnotions { |
| 189 | + //ret := gobatisAnnotions{} |
| 190 | + //t.CommentLines |
| 191 | + return nil |
| 192 | +} |
| 193 | + |
| 194 | +// Imports should return a list of necessary imports. They will be |
| 195 | +// formatted correctly. You do not need to include quotation marks, |
| 196 | +// return only the package name; alternatively, you can also return |
| 197 | +// imports in the format `name "path/to/pkg"`. Imports will be called |
| 198 | +// after Init, PackageVars, PackageConsts, and GenerateType, to allow |
| 199 | +// you to keep track of what imports you actually need. |
| 200 | +func (g *gobatisGen) Imports(ctx *generator.Context) []string { |
| 201 | + imports := g.imports.ImportLines() |
| 202 | + imports = append(imports, gobatisImports...) |
| 203 | + return imports |
| 204 | +} |
| 205 | + |
| 206 | +// Preferred file name of this generator, not including a path. It is |
| 207 | +// allowed for multiple generators to use the same filename, but it's |
| 208 | +// up to you to make sure they don't have colliding import names. |
| 209 | +// TODO: provide per-file import tracking, removing the requirement |
| 210 | +// that generators coordinate.. |
| 211 | +func (g *gobatisGen) Filename() string { |
| 212 | + return g.name + ".go" |
| 213 | +} |
| 214 | + |
| 215 | +// A registered file type in the context to generate this file with. If |
| 216 | +// the FileType is not found in the context, execution will stop. |
| 217 | +func (g *gobatisGen) FileType() string { |
| 218 | + return generator.GolangFileType |
| 219 | +} |
0 commit comments