this program read itself, add the tag valid:MaxSize(2)
to the property structone.fieldone
, then prints the updated program to os.Stdout
.
package main
import (
"go/ast"
"go/printer"
"go/token"
"log"
"os"
"strings"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/loader"
)
type structone struct {
fieldone string
fieldtwo string
}
func main() {
var conf loader.Config
_, err := conf.FromArgs([]string{"."}, false)
if err != nil {
log.Fatal(err)
}
prog, err := conf.Load()
if err != nil {
log.Fatal(err)
}
astutil.Apply(prog.InitialPackages()[0].Files[0], addTag("structone.fieldone", "`valid:MaxSize(2)`"), nil)
printer.Fprint(os.Stdout, prog.Fset, prog.InitialPackages()[0].Files[0])
}
func addTag(p string, tag string) func(*astutil.Cursor) bool {
pp := strings.Split(p, ".")
sName := pp[0]
pName := pp[1]
return func(cursor *astutil.Cursor) bool {
n := cursor.Node()
if x, ok := n.(*ast.TypeSpec); ok {
return x.Name.Name == sName
} else if x, ok := n.(*ast.Field); ok {
for _, v := range x.Names {
if v.Name == pName {
x.Tag = &ast.BasicLit{
Value: tag,
Kind: token.STRING,
}
}
}
} else if _, ok := n.(*ast.File); ok {
return true
} else if _, ok := n.(*ast.GenDecl); ok {
return true
} else if _, ok := n.(*ast.TypeSpec); ok {
return true
} else if _, ok := n.(*ast.StructType); ok {
return true
} else if _, ok := n.(*ast.FieldList); ok {
return true
}
return false
}
}