package source
import (
)
var Update bool
func () {
flag.BoolVar(&Update, "update", false, "update golden values")
}
var ErrNotFound = fmt.Errorf("failed to find variable for update of golden value")
func ( int, , interface{}) error {
, , , := runtime.Caller( + 1)
if ! {
return errors.New("failed to get call stack")
}
debug("call stack position: %s:%d", , )
:= token.NewFileSet()
, := parser.ParseFile(, , nil, parser.AllErrors|parser.ParseComments)
if != nil {
return fmt.Errorf("failed to parse source file %s: %w", , )
}
, := getCallExprArgs(, , )
if != nil {
return fmt.Errorf("call from %s:%d: %w", , , )
}
if len() < 3 {
debug("not enough arguments %d: %v",
len(), debugFormatNode{Node: &ast.CallExpr{Args: }})
return ErrNotFound
}
, := getIdentForExpectedValueArg()
if < 0 || == nil {
debug("no arguments started with the word 'expected': %v",
debugFormatNode{Node: &ast.CallExpr{Args: }})
return ErrNotFound
}
:=
if == 1 {
=
}
, := .(string)
if ! {
debug("value must be type string, got %T", )
return ErrNotFound
}
return UpdateVariable(, , , , )
}
func (
string,
*token.FileSet,
*ast.File,
*ast.Ident,
string,
) error {
:= .Obj
if == nil {
return ErrNotFound
}
if .Kind != ast.Con && .Kind != ast.Var {
debug("can only update var and const, found %v", .Kind)
return ErrNotFound
}
switch decl := .Decl.(type) {
case *ast.ValueSpec:
if len(.Names) != 1 {
debug("more than one name in ast.ValueSpec")
return ErrNotFound
}
.Values[0] = &ast.BasicLit{
Kind: token.STRING,
Value: "`" + + "`",
}
case *ast.AssignStmt:
if len(.Lhs) != 1 {
debug("more than one name in ast.AssignStmt")
return ErrNotFound
}
.Rhs[0] = &ast.BasicLit{
Kind: token.STRING,
Value: "`" + + "`",
}
default:
debug("can only update *ast.ValueSpec, found %T", .Decl)
return ErrNotFound
}
var bytes.Buffer
if := format.Node(&, , ); != nil {
return fmt.Errorf("failed to format file after update: %w", )
}
, := os.Create()
if != nil {
return fmt.Errorf("failed to open file %v: %w", , )
}
if _, = .Write(.Bytes()); != nil {
return fmt.Errorf("failed to write file %v: %w", , )
}
if := .Sync(); != nil {
return fmt.Errorf("failed to sync file %v: %w", , )
}
return nil
}
func ( []ast.Expr) (int, *ast.Ident) {
for := 1; < 3; ++ {
switch e := [].(type) {
case *ast.Ident:
if strings.HasPrefix(strings.ToLower(.Name), "expected") {
return ,
}
}
}
return -1, nil
}