godog/pkg/formatters/ast/ast.go

129 строки
2,9 КиБ
Go

package ast
import (
"go/ast"
"go/format"
"go/parser"
"go/token"
"os"
"errors"
)
type ASTer struct {
pkg string
fname string
fset *token.FileSet
node *ast.File
}
func NewASTer() (*ASTer, error) {
a := &ASTer{}
pkg, err := получитьИмяGoПакетаВЭтойДире()
if err != nil {
return nil, err
}
a.pkg = pkg
err = a.найтиТестовыйФайл()
if err != nil {
return nil, err
}
return a, nil
}
func (a *ASTer) ДобавитьТестовуюФункцию(func_name string, ps Параметры) error {
return a.добавитьвФайлФункцию(func_name, ps)
}
func (a *ASTer) найтиТестовыйФайл() error {
a.сгенеритьИмяФайла()
_, err := os.Stat(a.fname)
return err
}
func (a *ASTer) сгенеритьИмяФайла() {
a.fname = a.pkg + "_test.go"
}
func (a *ASTer) добавитьвФайлФункцию(func_name string, ps Параметры) error {
err := a.спарситьФайлиДобавитьФункцию(func_name, ps)
if err != nil {
return err
}
return a.перезаписатьФайл()
}
func (a *ASTer) спарситьФайлиДобавитьФункцию(func_name string, ps Параметры) error {
err := a.спарситьФайл()
if err != nil {
return err
}
fun := a.создатьФункцию(func_name, ps)
a.добавитьФункциюЕслиНету(fun)
return nil
}
func (a *ASTer) добавитьФункциюЕслиНету(fun *ast.FuncDecl) {
for _, d := range a.node.Decls {
f, ok := d.(*ast.FuncDecl)
if !ok {
continue
}
if f.Name == nil {
continue
}
if f.Name.Name == fun.Name.Name {
return
}
}
a.node.Decls = append(a.node.Decls, fun)
}
func (a *ASTer) спарситьФайл() error {
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, a.fname, nil, parser.ParseComments)
a.fset = fset
a.node = node
return err
}
func (a *ASTer) создатьФункцию(func_name string, ps Параметры) *ast.FuncDecl {
f := &ast.FuncDecl{
Name: ast.NewIdent(func_name),
Type: &ast.FuncType{
Params: &ast.FieldList{},
},
Body: &ast.BlockStmt{},
}
a.добавитьПараметрыФункции(ps, f)
return f
}
func (a *ASTer) добавитьПараметрыФункции(ps Параметры, f *ast.FuncDecl) {
for _, p := range ps {
p := &ast.Field{
Names: []*ast.Ident{ast.NewIdent(p[0])},
Type: ast.NewIdent(p[1]),
}
f.Type.Params.List = append(f.Type.Params.List, p)
}
}
func (a *ASTer) перезаписатьФайл() error {
err := переименоватьФайлСоВременем(a.fname)
if err != nil {
return errors.Join(err, errors.New("cant backup orig file"))
}
f, err := os.Create(a.fname)
if err != nil {
return errors.Join(err, errors.New("cant rewrite orig file"))
}
defer f.Close()
return format.Node(f, a.fset, a.node)
}