func initToDecl(ctxt *grinder.Context, pkg *grinder.Package, edit *grinder.EditBuffer, fn *ast.FuncDecl) { // Rewrite x := T{} (for struct or array type T) and x := (*T)(nil) to var x T. ast.Inspect(fn.Body, func(x ast.Node) bool { list := grinder.BlockList(x) for _, stmt := range list { as, ok := stmt.(*ast.AssignStmt) if !ok || len(as.Lhs) > 1 || as.Tok != token.DEFINE { continue } var typ string if t, ok := isNilPtr(pkg, edit, as.Rhs[0]); ok { typ = t } else if t, ok := isStructOrArrayLiteral(pkg, edit, as.Rhs[0]); ok { typ = t } if typ != "" { edit.Replace(stmt.Pos(), stmt.End(), "var "+as.Lhs[0].(*ast.Ident).Name+" "+typ) } } return true }) }
func findTargetBlock(pkg *grinder.Package, edit *grinder.EditBuffer, fn *ast.FuncDecl, blocks *block.Graph, labelname string) (target targetBlock, ok bool) { if debug { println("FINDTARGET", labelname) } lstmt := blocks.Label[labelname] if lstmt == nil { return } list := grinder.BlockList(blocks.Map[lstmt].Root) if list == nil { return } ulstmt := grinder.Unlabel(lstmt) for i := 0; i < len(list); i++ { if grinder.Unlabel(list[i]) == ulstmt { // Found statement. Find extent of block. if debug { println("FOUND") } end := i for ; ; end++ { if end >= len(list) { if debug { println("EARLY END") } // List ended without terminating statement. // Unless this is the top-most block, we can't hoist this code. if blocks.Map[lstmt].Root != fn.Body { return } // Top-most block. Implicit return at end of list. target.needReturn = true break } if end > i && grinder.IsGotoTarget(blocks, list[end]) { if debug { println("FOUND TARGET") } target.needGoto = list[end].(*ast.LabeledStmt).Label.Name break } if grinder.IsTerminatingStmt(blocks, list[end]) { if debug { println("TERMINATING") } end++ break } } if end <= i { if debug { println("NOTHING") } return } if debug { println("OK") } target.dead = i > 0 && grinder.IsTerminatingStmt(blocks, list[i-1]) target.start = lstmt.Pos() target.comment = edit.BeforeComments(target.start) target.endLabel = lstmt.Colon + 1 target.end = edit.End(list[end-1]) target.code = strings.TrimSpace(edit.TextAt(lstmt.Colon+1, target.end)) target.short = end == i+1 && (isReturn(grinder.Unlabel(list[i])) || isEmpty(grinder.Unlabel(list[i])) && target.needReturn) target.objs = gatherObjs(pkg, fn, lstmt.Pos(), list[i:end]) return target, true } } return }