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 }
func (lp *linePrinter) trimBlock(stmt *ast.BlockStmt) *ast.BlockStmt { if !lp.trim(stmt) { return lp.emptyBlock(stmt) } stmt.Rbrace = stmt.Lbrace return stmt }