func CodeStyleType(typeString string) string {
	s := strings.TrimLeft(typeString, "*")
	starNum := len(typeString) - len(s)
	s = s[strings.LastIndex(s, "/")+1:]
	return strings.Repeat("*", starNum) + s
}
CodeStyleType converts *a/b/c.T to *c.T
package tools
import (
	"bytes"
	"errors"
	"go/ast"
	"go/token"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"github.com/henrylee2cn/aster/internal/imports"
	"github.com/henrylee2cn/goutil"
)
func MkdirAll(path string, perm ...os.FileMode) error {
	return goutil.MkdirAll(path, perm...)
}
func WriteFile(filename string, data []byte, perm ...os.FileMode) error {
	return goutil.WriteFile(filename, data, perm...)
}
func RewriteFile(name string, fn func(content []byte) (newContent []byte, err error)) error {
	return goutil.RewriteFile(name, fn)
}
func ReplaceFile(fset *token.FileSet, node ast.Node, newCode string) error {
	f := fset.File(node.Pos())
	if f == nil {
		return errors.New("the node does not exist")
	}
	filename := f.Name()
	start := f.Offset(node.Pos())
	end := f.Offset(node.End())
	return goutil.ReplaceFile(filename, start, end, newCode)
}
type Options = imports.Options
func FormatFile(filename string, content []byte, opt *Options) error {
	return RewriteFile(filename, func(c []byte) ([]byte, error) {
		if len(content) > 0 {
			c = content
		}
		return Format(filename, c, opt)
	})
}
func Format(filename string, src interface{}, opt *Options) ([]byte, error) {
	b, err := ReadSourceBytes(src)
	if err != nil {
		return nil, err
	}
	return imports.Process(filename, b, nil)
}
var pkglineRegexp = regexp.MustCompile("\n*package[\t ]+([^/\n]+)[/\n]")
func ChangePkgName(code string, pkgname string) string {
	s := strings.TrimSpace(pkglineRegexp.FindString(code))
	s = strings.TrimSpace(strings.TrimRight(s, "/"))
	if s == "" {
		return code
	}
	return strings.Replace(code, s, "package "+pkgname, 1)
}
func PkgName(filenameOrDirectory string, src interface{}) (string, error) {
	if src == nil {
		existed, isDir := goutil.FileExist(filenameOrDirectory)
		if !existed {
			return "", errors.New("file or directory is not existed")
		}
		if isDir {
			err := filepath.Walk(filenameOrDirectory, func(path string, f os.FileInfo, err error) error {
				if err != nil || f.IsDir() {
					return nil
				}
				if strings.HasSuffix(path, ".go") {
					filenameOrDirectory = path
					return errors.New("")
				}
				return nil
			})
			if err == nil || err.Error() != "" {
				return "", err
			}
		}
	}
	b, err := ReadSource(filenameOrDirectory, src)
	if err != nil {
		return "", err
	}
	r := pkglineRegexp.FindSubmatch(b)
	if len(r) < 2 {
		return "", nil
	}
	return goutil.BytesToString(bytes.TrimSpace(r[1])), nil
}
func ReadSource(filename string, src interface{}) ([]byte, error) {
	b, err := ReadSourceBytes(src)
	if err != nil {
		return nil, err
	}
	if b != nil {
		return b, nil
	}
	return ioutil.ReadFile(filename)
}
func ReadSourceBytes(src interface{}) ([]byte, error) {
	switch s := src.(type) {
	case nil:
		return nil, nil
	case string:
		return []byte(s), nil
	case []byte:
		return s, nil
	case *bytes.Buffer:
		if s != nil {
			return s.Bytes(), nil
		}
	case io.Reader:
		return ioutil.ReadAll(s)
	}
	return nil, errors.New("invalid source")
}