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