예제 #1
0
파일: vardecl.go 프로젝트: xwb1989/grind
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
	})
}
예제 #2
0
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
}