Exemplo n.º 1
0
func rewriteFnWithRecovers(body *ast.BlockStmt, fnType *ast.FuncType) (wrapped *ast.FuncLit) {
	// The formatting of the channel declaration is ugly, but it's presented this way here to show how it will look in the actual output.
	// As far as I know, I would need to set the token.Pos values for the left and right braces of the struct and interface type literals
	// in order to get them on one line, but I don't think I can do that without computing all of the other token.Pos values for everything
	// else I generate.
	// TODO: These identifiers will probably conflict if there is a nested function that also has unnamed outputs. Should probably make a better gensym.
	outputDecls, outputs := inputsOrOutputs(fnType.Results, idents.result)
	if len(outputs) > 0 {
		body.List = astPrintf(`%s = func() (%s) {%s}()`, outputs, fnType.Results, body.List)
	}
	body.List = astPrintf(`
		{{%s}}
		_r := make(chan chan interface {
		})
		recovers, panicChan := godebug.EnterFuncWithRecovers(_r, func(ctx *godebug.Context) {
			%s
		})
		for recoverChan := range recovers {
			recoverChan <- recover()
		}
		if panicVal, ok := <-panicChan; ok {
			panic(panicVal)
		}
		{{return %s}}`, outputDecls, body.List, outputs)
	body.Rbrace = token.NoPos // without this I was getting extra whitespace at the end of the function
	return wrapped
}
Exemplo n.º 2
0
func (lp *linePrinter) trimBlock(stmt *ast.BlockStmt) *ast.BlockStmt {
	if !lp.trim(stmt) {
		return lp.emptyBlock(stmt)
	}
	stmt.Rbrace = stmt.Lbrace
	return stmt
}