Esempio n. 1
0
func grindFunc(ctxt *grinder.Context, pkg *grinder.Package, edit *grinder.EditBuffer, fn *ast.FuncDecl) {
	if fn.Body == nil {
		return
	}
	blocks := block.Build(pkg.FileSet, fn.Body)
	ast.Inspect(fn.Body, func(x ast.Node) bool {
		var list []ast.Stmt
		switch x := x.(type) {
		default:
			return true
		case *ast.BlockStmt:
			list = x.List
		case *ast.CommClause:
			list = x.Body
		case *ast.CaseClause:
			list = x.Body
		}

		for i := 0; i < len(list); i++ {
			x := list[i]
			if grinder.IsTerminatingStmt(blocks, x) {
				end := i + 1
				for end < len(list) && !isGotoTarget(blocks, list[end]) {
					end++
				}
				if end > i+1 {
					edit.Delete(edit.End(x), edit.End(list[end-1]))
					i = end - 1 // after i++, next iteration starts at end
				}
			}
		}
		return true
	})
}
Esempio n. 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
}