mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			100 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
| package codegen
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"regexp"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/dave/dst"
 | |
| 	"github.com/dave/dst/dstutil"
 | |
| )
 | |
| 
 | |
| type prefixmod struct {
 | |
| 	prefix  string
 | |
| 	replace string
 | |
| 	rxp     *regexp.Regexp
 | |
| 	rxpsuff *regexp.Regexp
 | |
| }
 | |
| 
 | |
| // PrefixDropper returns a dstutil.ApplyFunc that removes the provided prefix
 | |
| // string when it appears as a leading sequence in type names, var names, and
 | |
| // comments in a generated Go file.
 | |
| func PrefixDropper(prefix string) dstutil.ApplyFunc {
 | |
| 	return (&prefixmod{
 | |
| 		prefix:  prefix,
 | |
| 		rxpsuff: regexp.MustCompile(fmt.Sprintf(`%s([a-zA-Z_]+)`, prefix)),
 | |
| 		rxp:     regexp.MustCompile(fmt.Sprintf(`%s([\s.,;-])`, prefix)),
 | |
| 	}).applyfunc
 | |
| }
 | |
| 
 | |
| func depoint(e dst.Expr) dst.Expr {
 | |
| 	if star, is := e.(*dst.StarExpr); is {
 | |
| 		return star.X
 | |
| 	}
 | |
| 	return e
 | |
| }
 | |
| 
 | |
| func (d prefixmod) applyfunc(c *dstutil.Cursor) bool {
 | |
| 	n := c.Node()
 | |
| 
 | |
| 	switch x := n.(type) {
 | |
| 	case *dst.ValueSpec:
 | |
| 		d.handleExpr(x.Type)
 | |
| 		for _, id := range x.Names {
 | |
| 			d.do(id)
 | |
| 		}
 | |
| 	case *dst.TypeSpec:
 | |
| 		// Always do typespecs
 | |
| 		d.do(x.Name)
 | |
| 	case *dst.Field:
 | |
| 		// Don't rename struct fields. We just want to rename type declarations, and
 | |
| 		// field value specifications that reference those types.
 | |
| 		d.handleExpr(x.Type)
 | |
| 	case *dst.File:
 | |
| 		for _, def := range x.Decls {
 | |
| 			comments := def.Decorations().Start.All()
 | |
| 			def.Decorations().Start.Clear()
 | |
| 			// For any reason, sometimes it retrieves the comment duplicated 🤷
 | |
| 			commentMap := make(map[string]bool)
 | |
| 			for _, c := range comments {
 | |
| 				if _, ok := commentMap[c]; !ok {
 | |
| 					commentMap[c] = true
 | |
| 					def.Decorations().Start.Append(d.rxpsuff.ReplaceAllString(c, "$1"))
 | |
| 					if d.replace != "" {
 | |
| 						def.Decorations().Start.Append(d.rxp.ReplaceAllString(c, d.replace+"$1"))
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return true
 | |
| }
 | |
| 
 | |
| func (d prefixmod) handleExpr(e dst.Expr) {
 | |
| 	// Deref a StarExpr, if there is one
 | |
| 	expr := depoint(e)
 | |
| 	switch x := expr.(type) {
 | |
| 	case *dst.Ident:
 | |
| 		d.do(x)
 | |
| 	case *dst.ArrayType:
 | |
| 		if id, is := depoint(x.Elt).(*dst.Ident); is {
 | |
| 			d.do(id)
 | |
| 		}
 | |
| 	case *dst.MapType:
 | |
| 		if id, is := depoint(x.Key).(*dst.Ident); is {
 | |
| 			d.do(id)
 | |
| 		}
 | |
| 		if id, is := depoint(x.Value).(*dst.Ident); is {
 | |
| 			d.do(id)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (d prefixmod) do(n *dst.Ident) {
 | |
| 	if n.Name != d.prefix {
 | |
| 		n.Name = strings.TrimPrefix(n.Name, d.prefix)
 | |
| 	} else if d.replace != "" {
 | |
| 		n.Name = d.replace
 | |
| 	}
 | |
| }
 |