github.com/jmigpin/editor@v1.6.0/core/godebug/annotator.go (about) 1 package godebug 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/constant" 7 "go/token" 8 "go/types" 9 "math/big" 10 "sort" 11 "strconv" 12 "strings" 13 14 "github.com/jmigpin/editor/util/astut" 15 "github.com/jmigpin/editor/util/reflectutil" 16 ) 17 18 type Annotator struct { 19 fset *token.FileSet 20 21 typesInfo *types.Info 22 nodeAnnTypes map[ast.Node]AnnotationType 23 24 fileIndex int 25 debugPkgName string 26 debugVarPrefix string // will have integer appended 27 debugVarNameIndex int 28 debugLastIndex int // n indexes were used 29 builtDebugLineStmt bool // at least one debug stmt inserted 30 31 simpleTestMode bool // just testing annotator (no types) 32 } 33 34 func NewAnnotator(fset *token.FileSet) *Annotator { 35 ann := &Annotator{fset: fset} 36 // defaults for tests; used values are in annotatorset 37 ann.debugPkgName = "Σ" 38 ann.debugVarPrefix = "Σ" 39 return ann 40 } 41 42 //---------- 43 44 func (ann *Annotator) AnnotateAstFile(astFile *ast.File) { 45 ctx := &Ctx{} 46 ctx = ctx.withDebugIndex(0) 47 48 ann.vis(ctx, astFile) 49 50 // commented: setting astfile.comments to nil seems to fix things for the ast printer. 51 //ann.removeInnerFuncComments(astFile) 52 astFile.Comments = nil 53 54 ann.debugLastIndex = ann.correctDebugIndexes(astFile) 55 56 //fmt.Println("result----") 57 //ann.printNode(astFile) 58 } 59 60 //---------- 61 62 func (ann *Annotator) log(args ...interface{}) { 63 //log.Print(args...) 64 s := fmt.Sprint(args...) 65 s = strings.TrimRight(s, "\n") + "\n" 66 fmt.Print(s) 67 } 68 func (ann *Annotator) logf(f string, args ...interface{}) { 69 ann.log(fmt.Sprintf(f, args...)) 70 } 71 72 //---------- 73 74 func (ann *Annotator) vis(ctx *Ctx, v interface{}) { 75 switch t := v.(type) { 76 case nil: // nothing todo 77 case ast.Node: 78 ann.vis2(ctx, t) 79 case *[]ast.Stmt: 80 ann.visStmts(ctx, t) 81 default: 82 panic(fmt.Sprintf("todo: %T", t)) 83 } 84 } 85 86 // Should only be called throught vis() 87 func (ann *Annotator) vis2(ctx *Ctx, node ast.Node) { 88 //ann.logf("vis2 %T\n", node) 89 //ann.logf("vis2 %T (%v)\n", node, ann.sprintNode(node)) 90 91 // handle here for top level directives (ex: func decl) 92 ctx = ann.annotationBlockCtx(ctx, node) 93 if ctx.boolean(ctxIdNoAnnotations) { 94 ann.visNoAnnotations(ctx, node) 95 return 96 } 97 98 // build name: visit node if there is a function defined for it 99 name, err := reflectutil.TypeNameBase(node) 100 if err != nil { 101 return 102 } 103 res, err := reflectutil.InvokeByName(ann, "Vis"+name, ctx, node) 104 if err != nil { 105 ann.logf("todo: vis2: %v", err) 106 return 107 } 108 if len(res) != 0 { 109 panic(fmt.Sprintf("len of res not zero: %v", len(res))) 110 } 111 } 112 113 //---------- 114 115 func (ann *Annotator) visNoAnnotations(ctx *Ctx, n1 ast.Node) { 116 ast.Inspect(n1, func(n2 ast.Node) bool { 117 if n2 != n1 { 118 ctx2 := ann.annotationBlockCtx(ctx, n2) 119 if !ctx2.boolean(ctxIdNoAnnotations) { 120 ann.vis(ctx2, n2) 121 return false // done with noannotations 122 } 123 } 124 125 // special handling of a few nodes to setup the ctx in case annotations become enabled 126 switch t2 := n2.(type) { 127 case *ast.BlockStmt: 128 ann.vis(ctx, &t2.List) 129 return false 130 case *ast.CaseClause: 131 ann.vis(ctx, &t2.Body) // not a blockstmt 132 return false 133 case *ast.CommClause: 134 ann.vis(ctx, &t2.Body) // not a blockstmt 135 return false 136 137 case *ast.FuncDecl: 138 ctx2 := ctx.withFuncType(t2.Type) 139 ann.vis(ctx2, t2.Body) 140 return false 141 case *ast.FuncLit: 142 ctx2 := ctx.withFuncType(t2.Type) 143 ann.vis(ctx2, t2.Body) 144 return false 145 146 case *ast.DeclStmt: 147 ann.VisDeclStmt(ctx, t2) // sets ctx boolean 148 return false 149 150 // TODO: godebug directive in "else if" between "else" and "if"? 151 152 default: 153 return true // visit childs 154 } 155 }) 156 } 157 158 //---------- 159 160 // the resulting (res) "debug" expr for the given expr 161 func (ann *Annotator) resExpr(ctx *Ctx, e *ast.Expr) ast.Expr { 162 ctx = ctx.withExpr(e) 163 node := *e 164 165 //ann.logf("resExpr %T\n", node) 166 //ann.logf("resExpr %T (%v)\n", *e, ann.sprintNode2(node)) 167 168 // buildname: visit node if there is a function defined for it 169 name, err := reflectutil.TypeNameBase(node) 170 if err != nil { 171 return nilIdent() 172 } 173 res, err := reflectutil.InvokeByName(ann, "Res"+name, ctx, node) 174 if err != nil { 175 ann.logf("todo: resExpr: %v", err) 176 return nilIdent() 177 } 178 result := res[0].Interface().(ast.Expr) // must succeed 179 if result == nil { 180 return nilIdent() 181 } 182 return result 183 } 184 185 func (ann *Annotator) resExprs(ctx *Ctx, es *[]ast.Expr) ast.Expr { 186 ctx = ctx.withExprs(es) 187 w := []ast.Expr{} 188 for i := range *es { 189 ctx2 := ctx 190 e1 := &(*es)[i] 191 res := (ast.Expr)(nil) 192 if i == 0 && ctx2.boolean(ctxIdFirstArgIsType) { 193 ctx2 = ctx2.withBoolean(ctxIdInTypeArg, true) 194 } 195 res = ann.resExpr(ctx2, e1) 196 if res == nil { 197 res = nilIdent() 198 } 199 w = append(w, res) 200 } 201 if len(w) == 0 { 202 return nilIdent() 203 } 204 return ann.newDebugI(ctx, "IL", w...) 205 } 206 207 func (ann *Annotator) resFieldList(ctx *Ctx, fl *ast.FieldList) ast.Expr { 208 w := []ast.Expr{} 209 for _, f := range fl.List { 210 // set field name if it has no names (otherwise it won't output) 211 if len(f.Names) == 0 { 212 f.Names = append(f.Names, ann.newIdent(ctx)) 213 } 214 215 for i := range f.Names { 216 e1 := ast.Expr(f.Names[i]) 217 e := ann.resExpr(ctx, &e1) // e1 won't be replaceable (local var) 218 w = append(w, e) 219 } 220 } 221 if len(w) == 0 { 222 return nilIdent() 223 } 224 return ann.newDebugI(ctx, "IL", w...) 225 } 226 227 //---------- 228 //---------- 229 //---------- 230 231 func (ann *Annotator) VisFile(ctx *Ctx, file *ast.File) { 232 for _, d := range file.Decls { 233 ann.vis(ctx, d) 234 } 235 } 236 237 func (ann *Annotator) VisGenDecl(ctx *Ctx, gd *ast.GenDecl) { 238 switch gd.Tok { 239 case token.CONST: 240 // TODO: handle iota 241 case token.VAR: 242 // annotate only if inside decl stmt 243 // TODO: top level var decls that have a func lit assigned? 244 if !ctx.boolean(ctxIdInDeclStmt) { 245 break 246 } 247 248 if len(gd.Specs) >= 2 { 249 ann.splitGenDecl(ctx, gd) 250 } 251 for _, spec := range gd.Specs { 252 ann.vis(ctx, spec) 253 } 254 } 255 } 256 257 func (ann *Annotator) VisImportSpec(ctx *Ctx, is *ast.ImportSpec) { 258 } 259 260 func (ann *Annotator) VisDeclStmt(ctx *Ctx, ds *ast.DeclStmt) { 261 // DeclStmt is a decl in a stmt list => gendecl is only const/type/var 262 ctx = ctx.withBoolean(ctxIdInDeclStmt, true) 263 ann.vis(ctx, ds.Decl) 264 } 265 266 func (ann *Annotator) VisFuncDecl(ctx *Ctx, fd *ast.FuncDecl) { 267 // body can be nil (external func decls, only the header declared) 268 if fd.Body == nil { 269 return 270 } 271 272 //// don't annotate these functions to avoid endless loop recursion 273 //if fd.Recv != nil && fd.Body != nil && fd.Name.Name == "String" && len(fd.Type.Params.List) == 0 { 274 // return 275 //} 276 //if fd.Recv != nil && fd.Body != nil && fd.Name.Name == "Error" && len(fd.Type.Params.List) == 0 { 277 // return 278 //} 279 280 // visit body first to avoid annotating params insertions 281 ctx2 := ctx.withFuncType(fd.Type) 282 ann.vis(ctx2, fd.Body) 283 284 // visit params 285 ann.visFieldList(ctx, fd.Type.Params, fd.Body) 286 } 287 288 func (ann *Annotator) VisBlockStmt(ctx *Ctx, bs *ast.BlockStmt) { 289 ann.vis(ctx, &bs.List) 290 } 291 292 func (ann *Annotator) VisExprStmt(ctx *Ctx, es *ast.ExprStmt) { 293 ctx = ctx.withFixedDebugIndex() 294 xPos := es.X.Pos() 295 e := ann.resExpr(ctx, &es.X) 296 ctx3 := ctx.withInsertStmtAfter(true) 297 ann.insertDebugLine(ctx3, xPos, e) 298 } 299 300 func (ann *Annotator) VisAssignStmt(ctx *Ctx, as *ast.AssignStmt) { 301 ctx = ctx.withFixedDebugIndex() 302 303 asPos := as.Pos() 304 asTok := as.Tok 305 306 // right hand side 307 ctx3 := ctx 308 if len(as.Rhs) == 1 { 309 // ex: a:=b 310 // ex: a,ok:= m[b] 311 // ex: a,b,c:=f() 312 ctx3 = ctx3.withNResults(len(as.Lhs)) 313 } else { 314 // ex: a,b,c:=d,e,f // each of {d,e,f} return only 1 result 315 ctx3 = ctx3.withNResults(1) 316 } 317 rhs := ann.resExprs(ctx3, &as.Rhs) 318 319 // assign right hand side to a var before the main assign stmt 320 ctx5 := ctx.withInsertStmtAfter(false) 321 rhs2 := ann.assignToNewIdent(ctx5, rhs) 322 323 // simplify (don't show lhs since it's similar to rhs) 324 allSimple := false // ex: a++, a+=1 325 switch asTok { 326 case token.DEFINE, token.ASSIGN: 327 allSimple = true 328 if len(as.Rhs) == 1 { 329 if _, ok := as.Rhs[0].(*ast.TypeAssertExpr); ok { 330 allSimple = false 331 } 332 } 333 } 334 if allSimple { 335 for _, e := range as.Lhs { 336 if !isIdentOrSelectorOfIdents(e) { 337 allSimple = false 338 break 339 } 340 } 341 } 342 if allSimple { 343 ann.insertDebugLine(ctx, asPos, rhs2) 344 return 345 } 346 347 // left hand side 348 // ex: a[i] // returns 1 result 349 // ex: a,b,c:= // each expr returns 1 result to be debugged 350 ctx4 := ctx 351 ctx4 = ctx.withInsertStmtAfter(true) 352 ctx4 = ctx4.withNResults(1) 353 ctx4 = ctx4.withBoolean(ctxIdExprInLhs, true) 354 lhs := ann.resExprs(ctx4, &as.Lhs) 355 356 ctx = ctx.withInsertStmtAfter(true) 357 opbl := basicLitInt(int(asTok)) 358 ce3 := ann.newDebugI(ctx, "IA", lhs, opbl, rhs2) 359 ann.insertDebugLine(ctx, asPos, ce3) 360 } 361 362 func (ann *Annotator) VisReturnStmt(ctx *Ctx, rs *ast.ReturnStmt) { 363 ft, ok := ctx.funcType() 364 if !ok { 365 return 366 } 367 368 // functype number of results to return 369 nres := ft.Results.NumFields() 370 if nres == 0 { 371 // show debug step 372 ce := ann.newDebugI(ctx, "ISt") 373 ann.insertDebugLine(ctx, rs.Pos(), ce) 374 return 375 } 376 377 // naked return (have nres>0), use results ids 378 if len(rs.Results) == 0 { 379 var w []ast.Expr 380 for _, f := range ft.Results.List { 381 for _, id := range f.Names { 382 w = append(w, id) 383 } 384 } 385 rs.Results = w 386 } 387 388 // visit results 389 pos := rs.Pos() 390 ctx2 := ctx 391 ctx2 = ctx2.withFixedDebugIndex() 392 if len(rs.Results) > 1 { // each return expr returns 1 result 393 ctx2 = ctx2.withNResults(1) 394 } else { 395 ctx2 = ctx2.withNResults(nres) 396 } 397 e2 := ann.resExprs(ctx2, &rs.Results) 398 399 ann.insertDebugLine(ctx2, pos, e2) 400 } 401 402 func (ann *Annotator) VisTypeSwitchStmt(ctx *Ctx, tss *ast.TypeSwitchStmt) { 403 ctx = ctx.withFixedDebugIndex() 404 if ok := ann.wrapInitInBlockAndVisit(ctx, tss, &tss.Init); ok { 405 return 406 } 407 408 // visiting tss.assign stmt would enter into the stmt exprstmt that always inserts the stmt after; this case needs the stmt insert before 409 e2 := (*ast.Expr)(nil) 410 switch t := tss.Assign.(type) { 411 case *ast.ExprStmt: 412 e2 = &t.X 413 case *ast.AssignStmt: 414 if len(t.Rhs) == 1 { 415 e2 = &t.Rhs[0] 416 } 417 } 418 if e2 != nil { 419 pos := (*e2).Pos() 420 ctx2 := ctx 421 ctx2 = ctx2.withFixedDebugIndex() 422 ctx2 = ctx2.withInsertStmtAfter(false) 423 e := ann.resExpr(ctx2, e2) 424 ann.insertDebugLine(ctx2, pos, e) 425 } 426 427 ctx3 := ctx.withNilFixedDebugIndex() 428 ann.vis(ctx3, tss.Body) 429 } 430 431 func (ann *Annotator) VisSwitchStmt(ctx *Ctx, ss *ast.SwitchStmt) { 432 ctx = ctx.withFixedDebugIndex() 433 if ok := ann.wrapInitInBlockAndVisit(ctx, ss, &ss.Init); ok { 434 return 435 } 436 437 if ss.Tag != nil { 438 tagPos := ss.Tag.Pos() 439 ctx3 := ctx 440 ctx3 = ctx3.withNResults(1) // ex: switch f1() // f1 has 1 result 441 e := ann.resExpr(ctx3, &ss.Tag) 442 ann.insertDebugLine(ctx3, tagPos, e) 443 } 444 445 // reset fixed debug index to visit the body since it has several stmts 446 ctx2 := ctx.withNilFixedDebugIndex() 447 ann.vis(ctx2, ss.Body) 448 } 449 450 func (ann *Annotator) VisIfStmt(ctx *Ctx, is *ast.IfStmt) { 451 ctx = ctx.withFixedDebugIndex() 452 if ok := ann.wrapInitInBlockAndVisit(ctx, is, &is.Init); ok { 453 return 454 } 455 456 // condition 457 isPos := is.Cond.Pos() 458 ctx2 := ctx 459 ctx2 = ctx2.withNResults(1) 460 ctx2 = ctx2.withInsertStmtAfter(false) 461 e := ann.resExpr(ctx2, &is.Cond) 462 ann.insertDebugLine(ctx2, isPos, e) 463 464 // reset fixed debug index to visit the body since it has several stmts 465 ctx3 := ctx.withNilFixedDebugIndex() 466 ann.vis(ctx3, is.Body) 467 468 switch is.Else.(type) { 469 case *ast.IfStmt: // "else if ..." 470 // wrap in block stmt to visit "if" stmt 471 bs := &ast.BlockStmt{List: []ast.Stmt{is.Else}} 472 is.Else = bs 473 } 474 ann.vis(ctx3, is.Else) 475 } 476 477 func (ann *Annotator) VisForStmt(ctx *Ctx, fs *ast.ForStmt) { 478 ctx = ctx.withFixedDebugIndex() 479 if ok := ann.wrapInitInBlockAndVisit(ctx, fs, &fs.Init); ok { 480 return 481 } 482 483 // visit the body first to avoid annotating inserted stmts of cond/post later 484 ctx7 := ctx.withNilFixedDebugIndex() 485 ann.vis(ctx7, fs.Body) 486 487 if fs.Cond != nil { 488 fsBodyCtx := ctx.withStmts(&fs.Body.List) 489 condPos := fs.Cond.Pos() 490 491 e := ann.resExpr(fsBodyCtx, &fs.Cond) 492 ann.insertDebugLine(fsBodyCtx, condPos, e) 493 494 // create ifstmt to break the loop 495 ue := &ast.UnaryExpr{Op: token.NOT, X: fs.Cond} // negate 496 is := &ast.IfStmt{If: fs.Pos(), Cond: ue, Body: &ast.BlockStmt{}} 497 fs.Cond = nil // clear forstmt condition 498 fsBodyCtx.insertStmt(is) 499 isBodyCtx := ctx.withStmts(&is.Body.List) 500 501 // insert break inside ifstmt 502 brk := &ast.BranchStmt{Tok: token.BREAK} 503 isBodyCtx.insertStmt(brk) 504 } 505 506 if fs.Post != nil { 507 fsBodyCtx := ctx.withStmts(&fs.Body.List) // TODO: review 508 509 // init flag var to run post stmt 510 flagVar := ann.newIdent(ctx) 511 as4 := ann.newAssignStmt11(flagVar, &ast.Ident{Name: "false"}) 512 ctx.insertStmt(as4) 513 514 // inside the forloop: ifstmt to know if the post stmt can run 515 is := &ast.IfStmt{Body: &ast.BlockStmt{}} 516 is.Cond = flagVar 517 fsBodyCtx.insertStmt(is) 518 isBodyCtx := ctx.withStmts(&is.Body.List) 519 520 // move fs.Post to inside the ifstmt 521 isBodyCtx.insertStmt(fs.Post) 522 fs.Post = nil 523 524 // visit ifstmt body that now contains the post stmt 525 ann.vis(ctx, is.Body) 526 527 // insert stmt that sets the flag to true 528 as5 := ann.newAssignStmt11(flagVar, &ast.Ident{Name: "true"}) 529 as5.Tok = token.ASSIGN 530 fsBodyCtx.insertStmt(as5) 531 } 532 } 533 534 func (ann *Annotator) VisRangeStmt(ctx *Ctx, rs *ast.RangeStmt) { 535 ctx = ctx.withFixedDebugIndex() 536 537 xPos := rs.X.Pos() 538 rsTok := rs.Tok 539 540 // range stmt 541 ctx3 := ctx.withNResults(1) 542 x := ann.resExpr(ctx3, &rs.X) 543 //ann.insertDebugLine(ctx3, xPos, x) 544 545 // length of x (insert before for stmt) 546 e5 := &ast.CallExpr{Fun: ast.NewIdent("len"), Args: []ast.Expr{rs.X}} 547 e6 := ann.newDebugI(ctx, "IVr", e5) 548 e7 := ann.assignToNewIdent(ctx, e6) // var is of type item 549 550 // first debug line (entering the loop) 551 e11 := ann.newDebugIL(ctx, e7, x) 552 ann.insertDebugLine(ctx, xPos, e11) 553 554 // visit the body first to avoid annotating inserted stmts 555 ctx6 := ctx.withNilFixedDebugIndex() 556 ann.vis(ctx6, rs.Body) 557 558 // key and value 559 kvPos := token.Pos(0) 560 rsBodyCtx := ctx.withStmts(&rs.Body.List) 561 kves := []ast.Expr{} 562 if rs.Key != nil { 563 kvPos = rs.Key.Pos() 564 e2 := ann.resExpr(rsBodyCtx, &rs.Key) 565 kves = append(kves, e2) 566 } 567 if rs.Value != nil { 568 if kvPos == 0 { 569 kvPos = rs.Value.Pos() 570 } 571 e2 := ann.resExpr(rsBodyCtx, &rs.Value) 572 kves = append(kves, e2) 573 } 574 575 if len(kves) > 0 { 576 ctx5 := rsBodyCtx 577 opbl := basicLitInt(int(rsTok)) 578 rhs := ann.newDebugI(ctx5, "IL", []ast.Expr{e7}...) 579 lhs := ann.newDebugI(ctx5, "IL", kves...) 580 e9 := ann.newDebugI(ctx5, "IA", lhs, opbl, rhs) 581 ann.insertDebugLine(ctx5, kvPos, e9) 582 } 583 } 584 585 func (ann *Annotator) VisIncDecStmt(ctx *Ctx, ids *ast.IncDecStmt) { 586 ctx = ctx.withFixedDebugIndex() 587 idsPos := ids.X.Pos() 588 idsTok := ids.Tok 589 590 // value before 591 e1 := ann.resExpr(ctx, &ids.X) 592 l1 := ann.newDebugI(ctx, "IL", e1) 593 ctx3 := ctx.withInsertStmtAfter(false) 594 l1before := ann.assignToNewIdent(ctx3, l1) 595 596 // value after 597 ctx2 := ctx.withInsertStmtAfter(true) 598 e2 := ann.resExpr(ctx2, &ids.X) 599 l2 := ann.newDebugI(ctx, "IL", e2) 600 601 opbl := basicLitInt(int(idsTok)) 602 ce3 := ann.newDebugI(ctx2, "IA", l2, opbl, l1before) 603 ann.insertDebugLine(ctx2, idsPos, ce3) 604 } 605 606 func (ann *Annotator) VisLabeledStmt(ctx *Ctx, ls *ast.LabeledStmt) { 607 // Problem: 608 // - label1: ; // inserting empty stmt breaks compilation 609 // for { break label1 } // compile error: invalid break label 610 // - using block stmts won't work 611 // label1: 612 // { for { break label1} } // compile error 613 // No way to insert debug stmts between the label and the stmt. 614 // Just make a debug step with "label" where a warning can be shown. 615 616 if ls.Stmt == nil { 617 return 618 } 619 620 switch ls.Stmt.(type) { 621 case *ast.ForStmt, *ast.RangeStmt, *ast.SwitchStmt, *ast.TypeSwitchStmt: 622 // can't insert stmts between the label and the stmt (alters program) 623 624 ctx = ctx.withLabeledStmt(ls) 625 ann.vis(ctx, ls.Stmt) 626 default: 627 // use empty stmt to insert stmts between label and stmt 628 stmt := ls.Stmt 629 ls.Stmt = &ast.EmptyStmt{} 630 631 // insert stmt before, consider stmt done 632 ctx3 := ctx.withInsertStmtAfter(false) 633 ctx3.insertStmt(ls) 634 635 // replace stmt and continue visit 636 ctx.replaceStmt(stmt) 637 ann.vis(ctx, stmt) 638 } 639 } 640 641 func (ann *Annotator) VisBranchStmt(ctx *Ctx, bs *ast.BranchStmt) { 642 ce := ann.newDebugI(ctx, "IBr") 643 ann.insertDebugLine(ctx, bs.Pos(), ce) 644 } 645 646 func (ann *Annotator) VisDeferStmt(ctx *Ctx, ds *ast.DeferStmt) { 647 ann.visDeferStmt2(ctx, &ds.Call) 648 } 649 func (ann *Annotator) VisGoStmt(ctx *Ctx, gs *ast.GoStmt) { 650 ann.visDeferStmt2(ctx, &gs.Call) 651 } 652 func (ann *Annotator) visDeferStmt2(ctx *Ctx, cep **ast.CallExpr) { 653 ctx = ctx.withCallExpr(cep) 654 ce := *cep 655 656 funPos := ce.Fun.Pos() 657 658 // assign arguments to tmp variables 659 if len(ce.Args) > 0 { 660 //args2 := make([]ast.Expr, len(ce.Args)) 661 //copy(args2, ce.Args) 662 //ids := ann.assignToNewIdents2(ctx, len(ce.Args), args2...) 663 for i, e := range ce.Args { 664 if ann.canAssignToVar(ctx, e) { 665 id := ann.assignToNewIdent(ctx, e) 666 ce.Args[i] = id 667 } 668 //else { 669 //ce.Args[i] = ids[i] 670 //} 671 } 672 } 673 674 ctx = ctx.withFixedDebugIndex() 675 676 // handle funclit 677 ceFunIsFuncLit := false 678 switch ce.Fun.(type) { 679 case *ast.FuncLit: 680 ceFunIsFuncLit = true 681 ctx3 := ctx.withNResults(1) 682 fun := ann.resExpr(ctx3, &ce.Fun) 683 ann.insertDebugLine(ctx, funPos, fun) 684 } 685 686 // replace func call with wrapped function 687 fl2 := &ast.FuncLit{ 688 Type: &ast.FuncType{ 689 Params: &ast.FieldList{}, 690 }, 691 Body: &ast.BlockStmt{ 692 List: []ast.Stmt{&ast.ExprStmt{X: ce}}, 693 }, 694 } 695 ce2 := &ast.CallExpr{Fun: fl2} 696 ctx.replaceCallExpr(ce2) 697 698 // temporary switch names for better debug line 699 if ceFunIsFuncLit { 700 if id, ok := ce.Fun.(*ast.Ident); ok { 701 name := id.Name 702 id.Name = "f" 703 defer func() { id.Name = name }() 704 } 705 } 706 707 // visit block with the func call to insert debug stmts inside 708 ann.vis(ctx, fl2.Body) 709 } 710 711 func (ann *Annotator) VisValueSpec(ctx *Ctx, vs *ast.ValueSpec) { 712 // ex: var a, b int = 1, 2 713 // ex: var a, b = f() 714 if len(vs.Values) > 0 { 715 pos := vs.Pos() 716 nres := len(vs.Names) 717 if len(vs.Values) >= 2 { 718 nres = 1 719 } 720 ctx2 := ctx 721 ctx2 = ctx2.withFixedDebugIndex() 722 ctx2 = ctx2.withNResults(nres) 723 e := ann.resExprs(ctx2, &vs.Values) 724 ann.insertDebugLine(ctx2, pos, e) 725 } 726 } 727 728 func (ann *Annotator) VisSelectStmt(ctx *Ctx, ss *ast.SelectStmt) { 729 // debug step to show it has entered the select statement 730 e1 := ann.newDebugI(ctx, "ISt") 731 ann.insertDebugLine(ctx, ss.Pos(), e1) 732 733 ann.vis(ctx, ss.Body) 734 } 735 736 func (ann *Annotator) VisCaseClause(ctx *Ctx, cc *ast.CaseClause) { 737 // visit body 738 ann.vis(ctx, &cc.Body) 739 740 // debug step showing the case was entered 741 ctx2 := ctx.withStmts(&cc.Body) 742 ce := ann.newDebugI(ctx2, "ISt") 743 ann.insertDebugLine(ctx2, cc.Case, ce) 744 } 745 746 func (ann *Annotator) VisCommClause(ctx *Ctx, cc *ast.CommClause) { 747 // visit body first to avoid annotating inserted stmts 748 ann.vis(ctx, &cc.Body) 749 750 // debug step showing the case was entered 751 ctx2 := ctx.withStmts(&cc.Body) 752 e1 := ann.newDebugI(ctx2, "ISt") 753 ann.insertDebugLine(ctx2, cc.Case, e1) 754 } 755 756 func (ann *Annotator) VisSendStmt(ctx *Ctx, ss *ast.SendStmt) { 757 pos := ss.Pos() 758 759 ctx2 := ctx.withNResults(1) 760 val := ann.resExpr(ctx2, &ss.Value) 761 762 ctx3 := ctx.withInsertStmtAfter(true) 763 ch := ann.resExpr(ctx3, &ss.Chan) 764 765 ce := ann.newDebugI(ctx, "IS", ch, val) 766 ann.insertDebugLine(ctx3, pos, ce) 767 } 768 769 //---------- 770 771 func (ann *Annotator) visStmts(ctx *Ctx, stmts *[]ast.Stmt) { 772 ctx2 := ctx.withStmts(stmts) 773 for stmt := ctx2.curStmt(); stmt != nil; stmt = ctx2.nextStmt() { 774 // handle here to enabled/disable next stmts in this list 775 ctx2 = ann.annotationBlockCtx(ctx2, stmt) 776 777 ann.vis(ctx2, stmt) 778 } 779 } 780 781 // NOTE: mostly used for params (fixed debug index) 782 func (ann *Annotator) visFieldList(ctx *Ctx, fl *ast.FieldList, body *ast.BlockStmt) { 783 if len(fl.List) == 0 { 784 return 785 } 786 ctx2 := ctx 787 ctx2 = ctx2.withStmts(&body.List) 788 ctx2 = ctx2.withFixedDebugIndex() 789 e1 := ann.resFieldList(ctx2, fl) 790 ann.insertDebugLine(ctx2, fl.Opening, e1) 791 } 792 793 //---------- 794 //---------- 795 //---------- 796 797 func (ann *Annotator) ResCallExpr(ctx *Ctx, ce *ast.CallExpr) ast.Expr { 798 cePos := ce.Pos() 799 800 // handle fun expr 801 isFuncLit := false 802 isPanic := false 803 isFirstArgType := false 804 switch t := ce.Fun.(type) { 805 case *ast.Ident: 806 // handle builtin funcs 807 switch t.Name { 808 case "panic": 809 if ann.isBuiltin(t) { 810 isPanic = true 811 } 812 case "new", "make": 813 if ann.isBuiltin(t) { 814 isFirstArgType = true 815 } 816 } 817 case *ast.FuncLit: 818 isFuncLit = true 819 } 820 821 // visit fun expr 822 ctx5 := ctx.withNResults(1) 823 ctx5 = ctx5.withBoolean(ctxIdNameInsteadOfValue, true) 824 fx := ann.resExpr(ctx5, &ce.Fun) 825 if isFuncLit { 826 ann.insertDebugLine(ctx, cePos, fx) // show step 827 fx = ann.newDebugIVsBl(ctx, "f") // continue with simple name 828 } 829 830 // visit args 831 ctx2 := ctx 832 ctx2 = ctx2.withNResults(1) // each arg returns 1 result 833 ctx2 = ctx2.withBoolean(ctxIdFirstArgIsType, isFirstArgType) 834 args := ann.resExprs(ctx2, &ce.Args) 835 836 // show stepping in (insert before func call) 837 args2 := append([]ast.Expr{fx}, args) 838 e4 := ann.newDebugI(ctx, "ICe", args2...) 839 ann.insertDebugLine(ctx, cePos, e4) 840 841 // avoid "line unreachable" compiler errors 842 if isPanic { 843 return afterPanicIdent() 844 } 845 846 result := ann.solveNResults(ctx, ce) 847 //if ctx.boolean(ctxIdNameInsteadOfValue) { 848 // result = nilIdent() 849 //} 850 851 return ann.newDebugI(ctx, "IC", e4, result) 852 } 853 854 func (ann *Annotator) ResBasicLit(ctx *Ctx, bl *ast.BasicLit) ast.Expr { 855 return ann.newDebugIVi(ctx, bl) 856 } 857 858 func (ann *Annotator) ResIdent(ctx *Ctx, id *ast.Ident) ast.Expr { 859 if id.Name == "_" { 860 return ann.newDebugI(ctx, "IAn") 861 } 862 if ctx.boolean(ctxIdInTypeArg) { 863 return ann.resType(ctx, id) 864 } 865 if ctx.boolean(ctxIdNameInsteadOfValue) { 866 return ann.newDebugIVsBl(ctx, id.Name) 867 } 868 return ann.newDebugIVi(ctx, id) 869 } 870 871 func (ann *Annotator) ResUnaryExpr(ctx *Ctx, ue *ast.UnaryExpr) ast.Expr { 872 xPos := ue.X.Pos() 873 874 ctx2 := ctx 875 if ue.Op == token.AND { 876 ctx2 = ctx2.withTakingVarAddress(ue.X) 877 } 878 x := ann.resExpr(ctx2, &ue.X) 879 880 opbl := basicLitInt(int(ue.Op)) 881 e4 := ann.newDebugI(ctx, "IUe", opbl, x) 882 if ue.Op == token.ARROW { 883 ann.insertDebugLine(ctx, xPos, e4) 884 } 885 886 result := ann.solveNResults(ctx, ue) 887 888 return ann.newDebugI(ctx, "IU", e4, result) 889 } 890 891 func (ann *Annotator) ResFuncLit(ctx *Ctx, fl *ast.FuncLit) ast.Expr { 892 ctx0 := ctx // for the last return 893 ctx = ctx.withResetForFuncLit() 894 895 // visit body first to avoid annotating params insertions 896 ctx3 := ctx 897 ctx3 = ctx3.withFuncType(fl.Type) 898 ann.vis(ctx3, fl.Body) 899 900 // visit params 901 ann.visFieldList(ctx, fl.Type.Params, fl.Body) 902 903 return ann.solveNResults(ctx0, fl) 904 } 905 906 func (ann *Annotator) ResSelectorExpr(ctx *Ctx, se *ast.SelectorExpr) ast.Expr { 907 if ctx.boolean(ctxIdInTypeArg) { 908 return ann.resType(ctx, se) 909 } 910 911 // simplify 912 if isIdentOrSelectorOfIdents(se) { 913 if ctx.boolean(ctxIdNameInsteadOfValue) { 914 return ann.newDebugIVsBl(ctx, se.Sel.Name) 915 } 916 return ann.newDebugIVi(ctx, se) 917 } 918 919 //xPos := se.X.Pos() 920 ctx4 := ctx.withNResults(1) //.withNameInsteadOfValue(false) 921 x := ann.resExpr(ctx4, &se.X) 922 //ann.insertDebugLine(ctx4, xPos, x) 923 924 sel := ast.Expr(nil) 925 if ctx.boolean(ctxIdNameInsteadOfValue) { 926 sel = ann.newDebugIVsBl(ctx, se.Sel.Name) 927 } else { 928 sel = ann.newDebugIVi(ctx, se) 929 } 930 return ann.newDebugI(ctx, "ISel", x, sel) 931 932 //ctx3 := ctx.withExpr(&se.X).withNResults(1) 933 //result := ann.solveNResults(ctx3, se.X) 934 935 //return ann.newDebugItem(ctx, "ISel", result, sel) 936 } 937 938 func (ann *Annotator) ResCompositeLit(ctx *Ctx, cl *ast.CompositeLit) ast.Expr { 939 // NOTE: not doing cl.Type 940 e := ann.resExprs(ctx, &cl.Elts) 941 return ann.newDebugI(ctx, "ILit", e) 942 } 943 944 func (ann *Annotator) ResKeyValueExpr(ctx *Ctx, kv *ast.KeyValueExpr) ast.Expr { 945 k := ast.Expr(nil) 946 if id, ok := kv.Key.(*ast.Ident); ok { 947 bl := basicLitStringQ(id.Name) 948 k = ann.newDebugI(ctx, "IVs", bl) 949 } else { 950 k = ann.resExpr(ctx, &kv.Key) 951 } 952 v := ann.resExpr(ctx, &kv.Value) 953 return ann.newDebugI(ctx, "IKV", k, v) 954 } 955 956 func (ann *Annotator) ResTypeAssertExpr(ctx *Ctx, tae *ast.TypeAssertExpr) ast.Expr { 957 // tae.Type!=nil is "t,ok:=X.(<type>)" 958 // tae.Type==nil is "switch X.(type)" 959 isSwitch := tae.Type == nil 960 961 ctx2 := ctx 962 ctx2 = ctx2.withNResults(1) // ex: f().(type) // f() returns 1 result 963 x := ann.resExpr(ctx2, &tae.X) 964 965 // simplify 966 if !isSwitch { 967 return x 968 } 969 970 xt := ann.newDebugI(ctx, "IVt", tae.X) 971 return ann.newDebugI(ctx, "ITA", x, xt) 972 } 973 974 func (ann *Annotator) ResParenExpr(ctx *Ctx, pe *ast.ParenExpr) ast.Expr { 975 x := ann.resExpr(ctx, &pe.X) 976 return ann.newDebugI(ctx, "IP", x) 977 } 978 979 func (ann *Annotator) ResIndexExpr(ctx *Ctx, ie *ast.IndexExpr) ast.Expr { 980 // ex: a,b=c[i],d[j] 981 // ex: a,ok:=m[f1()] // map access, more then 1 result 982 983 isSimple := isIdentOrSelectorOfIdents(ie.X) 984 985 ctx2 := ctx.withBoolean(ctxIdNameInsteadOfValue, true) 986 x := ann.resExpr(ctx2, &ie.X) 987 988 // wrap in parenthesis 989 if !isSimple { 990 x = ann.newDebugIP(ctx, x) 991 } 992 993 // Index expr 994 ctx3 := ctx 995 ctx3 = ctx3.withNResults(1) // ex: a[f()] // f() returns 1 result 996 ctx3 = ctx3.withInsertStmtAfter(false) // ex: a[f()] // f() must be before 997 ctx3 = ctx3.withBoolean(ctxIdExprInLhs, false) // ex: a[f()] // allow to replace f() 998 ix := ann.resExpr(ctx3, &ie.Index) 999 1000 result := ann.solveNResults(ctx, ie) 1001 1002 return ann.newDebugI(ctx, "II", x, ix, result) 1003 } 1004 1005 func (ann *Annotator) ResSliceExpr(ctx *Ctx, se *ast.SliceExpr) ast.Expr { 1006 isSimple := isIdentOrSelectorOfIdents(se.X) 1007 1008 ctx2 := ctx.withBoolean(ctxIdNameInsteadOfValue, true) 1009 x := ann.resExpr(ctx2, &se.X) 1010 1011 // wrap in parenthesis 1012 if !isSimple { 1013 x = ann.newDebugIP(ctx, x) 1014 } 1015 1016 // index expr 1017 ix := []ast.Expr{} 1018 for _, e := range []*ast.Expr{&se.Low, &se.High, &se.Max} { 1019 r := ann.resExpr(ctx, e) 1020 ix = append(ix, r) 1021 } 1022 1023 result := ann.solveNResults(ctx, se) 1024 1025 // slice3: 2 colons present 1026 s := "false" 1027 if se.Slice3 { 1028 s = "true" 1029 } 1030 slice3Bl := basicLitString(s) 1031 1032 return ann.newDebugI(ctx, "II2", x, ix[0], ix[1], ix[2], slice3Bl, result) 1033 } 1034 1035 func (ann *Annotator) ResStarExpr(ctx *Ctx, se *ast.StarExpr) ast.Expr { 1036 if ann.isType(se) { 1037 return ann.resType(ctx, se) 1038 } 1039 1040 // ex: *a=1 1041 ctx = ctx.withNResults(1) 1042 1043 x := ann.resExpr(ctx, &se.X) 1044 //return x 1045 1046 result := ann.solveNResults(ctx, se) 1047 1048 opbl := basicLitInt(int(token.MUL)) 1049 e2 := ann.newDebugI(ctx, "IUe", opbl, x) 1050 return ann.newDebugI(ctx, "IU", e2, result) 1051 } 1052 1053 func (ann *Annotator) ResMapType(ctx *Ctx, mt *ast.MapType) ast.Expr { 1054 return ann.resType(ctx, mt) 1055 } 1056 func (ann *Annotator) ResChanType(ctx *Ctx, ct *ast.ChanType) ast.Expr { 1057 return ann.resType(ctx, ct) 1058 } 1059 func (ann *Annotator) ResArrayType(ctx *Ctx, at *ast.ArrayType) ast.Expr { 1060 return ann.resType(ctx, at) 1061 } 1062 func (ann *Annotator) ResInterfaceType(ctx *Ctx, it *ast.InterfaceType) ast.Expr { 1063 return ann.resType(ctx, it) 1064 } 1065 1066 //---------- 1067 1068 func (ann *Annotator) ResBinaryExpr(ctx *Ctx, be *ast.BinaryExpr) ast.Expr { 1069 ctx = ctx.withNResults(1) 1070 switch be.Op { 1071 case token.LAND, token.LOR: 1072 return ann.resBinaryExprAndOr(ctx, be) 1073 default: 1074 return ann.resBinaryExpr2(ctx, be) 1075 } 1076 } 1077 func (ann *Annotator) resBinaryExpr2(ctx *Ctx, be *ast.BinaryExpr) ast.Expr { 1078 x := ann.resExpr(ctx, &be.X) 1079 y := ann.resExpr(ctx, &be.Y) 1080 result := ann.solveNResults(ctx, be) 1081 opbl := basicLitInt(int(be.Op)) 1082 return ann.newDebugI(ctx, "IB", x, opbl, y, result) 1083 } 1084 func (ann *Annotator) resBinaryExprAndOr(ctx *Ctx, be *ast.BinaryExpr) ast.Expr { 1085 // ex: f1() || f2() // f2 should not be called if f1 is true 1086 // ex: f1() && f2() // f2 should not be called if f1 is false 1087 1088 x := ann.resExpr(ctx, &be.X) 1089 1090 // init result var with be.X 1091 resVar := ast.Expr(ann.newIdent(ctx)) 1092 as4 := ann.newAssignStmt11(resVar, be.X) 1093 as4.Tok = token.DEFINE 1094 ctx.insertStmt(as4) 1095 // replace expr with result var 1096 ctx.replaceExpr(resVar) 1097 1098 // init y result var (in case be.Y doesn't run) 1099 ybl := ann.newDebugIVsBl(ctx, "?") 1100 yRes := ann.assignToNewIdent(ctx, ybl) 1101 1102 // x condition based on being "&&" or "||" 1103 xCond := resVar 1104 if be.Op == token.LOR { 1105 xCond = &ast.UnaryExpr{Op: token.NOT, X: xCond} 1106 } 1107 1108 // ifstmt to test x result to decide whether to run y 1109 is := &ast.IfStmt{If: be.Pos(), Body: &ast.BlockStmt{}} 1110 is.Cond = xCond 1111 ctx.insertStmt(is) 1112 isBodyCtx := ctx.withStmts(&is.Body.List) 1113 1114 y := ann.resExpr(isBodyCtx, &be.Y) 1115 1116 // (inside ifstmt) assign debug result to y 1117 as3 := ann.newAssignStmt11(yRes, y) 1118 as3.Tok = token.ASSIGN 1119 isBodyCtx.insertStmt(as3) 1120 1121 // inside ifstmt: assign be.Y to result var 1122 as2 := ann.newAssignStmt11(resVar, be.Y) 1123 as2.Tok = token.ASSIGN 1124 isBodyCtx.insertStmt(as2) 1125 1126 opbl := basicLitInt(int(be.Op)) 1127 resVar2 := ann.newDebugIVi(ctx, resVar) 1128 return ann.newDebugI(ctx, "IB", x, opbl, yRes, resVar2) 1129 } 1130 1131 //---------- 1132 //---------- 1133 //---------- 1134 1135 // Mostly gets the expression into a var(s) to be able to use the result without calculating it twice. Ex: don't double call f(). 1136 func (ann *Annotator) solveNResults(ctx *Ctx, e ast.Expr) ast.Expr { 1137 // ex: a, b = c[i], d[j] // 1 result for each expr 1138 // ex: a, ok := c[f1()] // map access, more then 1 result 1139 // ex: a[i]=b // can't replace a[i] 1140 // ex: a:=&b[i] -> d0:=b[i];a:=&d0 // d0 wrong address 1141 1142 nres := ctx.nResults() 1143 if nres == 0 { 1144 return nilIdent() // ex: f1() // with no return value 1145 } 1146 1147 if !ann.canAssignToVar(ctx, e) { 1148 return ann.newDebugIVi(ctx, e) 1149 } 1150 1151 if ce, ok := e.(*ast.CallExpr); ok { 1152 if typ, ok := ann.typev(ce); ok { 1153 switch t := typ.Type.(type) { 1154 case *types.Tuple: 1155 nres = t.Len() 1156 } 1157 } 1158 } 1159 1160 if nres >= 2 { 1161 ids := ann.assignToNewIdents2(ctx, nres, e) 1162 ctx.replaceExprs(ids) 1163 ids2 := ann.wrapInIVi(ctx, ids...) 1164 return ann.newDebugIL(ctx, ids2...) 1165 } 1166 1167 ctx = ctx.withInsertStmtAfter(false) 1168 1169 // TODO: review 1170 //if ctx.exprOnLhs() { 1171 // // get address of the expression to replace 1172 // ue := &ast.UnaryExpr{Op: token.AND, X: e} 1173 // e2 := ann.assignToNewIdent2(ctx, ue) 1174 // se := &ast.StarExpr{X: e2} 1175 // ctx.replaceExpr(se) 1176 // return ann.newDebugItem(ctx, "IVi", e2) 1177 //} 1178 1179 e2 := ann.assignToNewIdent(ctx, e) 1180 ctx.replaceExpr(e2) 1181 return ann.newDebugIVi(ctx, e2) 1182 } 1183 1184 //---------- 1185 1186 func (ann *Annotator) newDebugIVi(ctx *Ctx, e ast.Expr) ast.Expr { 1187 if s, ok := ann.isBigConst(e); ok { 1188 return ann.newDebugIVsBl(ctx, s) 1189 } 1190 return ann.newDebugI(ctx, "IVi", e) 1191 } 1192 func (ann *Annotator) newDebugIVsBl(ctx *Ctx, s string) ast.Expr { 1193 return ann.newDebugI(ctx, "IVs", basicLitStringQ(s)) 1194 } 1195 func (ann *Annotator) newDebugIL(ctx *Ctx, es ...ast.Expr) ast.Expr { 1196 return ann.newDebugI(ctx, "IL", es...) 1197 } 1198 func (ann *Annotator) newDebugIP(ctx *Ctx, e ast.Expr) ast.Expr { 1199 return ann.newDebugI(ctx, "IP", e) 1200 } 1201 1202 func (ann *Annotator) wrapInIVi(ctx *Ctx, es ...ast.Expr) []ast.Expr { 1203 ivs := []ast.Expr{} 1204 for _, e := range es { 1205 e2 := ann.newDebugIVi(ctx, e) 1206 ivs = append(ivs, e2) 1207 } 1208 return ivs 1209 } 1210 1211 func (ann *Annotator) newDebugI(ctx *Ctx, fname string, es ...ast.Expr) ast.Expr { 1212 se := &ast.SelectorExpr{ 1213 X: ast.NewIdent(ann.debugPkgName), 1214 Sel: ast.NewIdent(fname), 1215 } 1216 ce := &ast.CallExpr{Fun: se, Args: es} 1217 1218 // TODO: handle this where they are called? 1219 // assign to var because these are called more then once 1220 assign := false 1221 switch fname { 1222 case "ICe", "IUe": 1223 assign = true 1224 } 1225 if assign { 1226 return ann.assignToNewIdent(ctx, ce) 1227 } 1228 1229 return ce 1230 } 1231 1232 //---------- 1233 1234 func (ann *Annotator) insertDebugLine(ctx *Ctx, pos token.Pos, expr ast.Expr) { 1235 if isAfterPanicIdent(expr) { 1236 return 1237 } 1238 stmt := ann.newDebugLine(ctx, pos, expr) 1239 ctx.insertStmt(stmt) 1240 } 1241 func (ann *Annotator) newDebugLine(ctx *Ctx, pos token.Pos, expr ast.Expr) ast.Stmt { 1242 se := &ast.SelectorExpr{ 1243 X: ast.NewIdent(ann.debugPkgName), 1244 Sel: ast.NewIdent("Line"), 1245 } 1246 args := []ast.Expr{ 1247 basicLitInt(ann.fileIndex), 1248 basicLitInt(ctx.nextDebugIndex()), 1249 basicLitInt(ann.fset.Position(pos).Offset), 1250 expr, 1251 } 1252 es := &ast.ExprStmt{X: &ast.CallExpr{Fun: se, Args: args}} 1253 ann.builtDebugLineStmt = true 1254 return es 1255 } 1256 1257 //---------- 1258 1259 func (ann *Annotator) assignToNewIdent(ctx *Ctx, expr ast.Expr) ast.Expr { 1260 return ann.assignToNewIdents2(ctx, 1, expr)[0] 1261 } 1262 func (ann *Annotator) assignToNewIdents2(ctx *Ctx, nIds int, exprs ...ast.Expr) []ast.Expr { 1263 ids := []ast.Expr{} 1264 for i := 0; i < nIds; i++ { 1265 id := ann.newIdent(ctx) 1266 1267 // have id use expr position 1268 k := i 1269 if len(exprs) == 1 { 1270 k = 0 1271 } 1272 id.NamePos = exprs[k].Pos() 1273 1274 ids = append(ids, id) 1275 } 1276 as := ann.newAssignStmt(ids, exprs) 1277 ctx.insertStmt(as) 1278 return ids 1279 } 1280 1281 //---------- 1282 1283 func (ann *Annotator) newAssignStmt11(lhs, rhs ast.Expr) *ast.AssignStmt { 1284 return ann.newAssignStmt([]ast.Expr{lhs}, []ast.Expr{rhs}) 1285 } 1286 func (ann *Annotator) newAssignStmt(lhs, rhs []ast.Expr) *ast.AssignStmt { 1287 return &ast.AssignStmt{Tok: token.DEFINE, Lhs: lhs, Rhs: rhs} 1288 } 1289 1290 //---------- 1291 1292 func (ann *Annotator) newIdent(ctx *Ctx) *ast.Ident { 1293 return &ast.Ident{Name: ann.newVarName(ctx)} 1294 } 1295 func (ann *Annotator) newVarName(ctx *Ctx) string { 1296 s := fmt.Sprintf("%s%d", ann.debugVarPrefix, ann.debugVarNameIndex) 1297 ann.debugVarNameIndex++ 1298 return s 1299 } 1300 1301 //---------- 1302 1303 // assigning the expr to a var could create a var of different type, 1304 // if the expr is on the left-hand-side, it could alter program behavior if the original destination doesn't get the value 1305 func (ann *Annotator) canAssignToVar(ctx *Ctx, e ast.Expr) bool { 1306 if ann.isType(e) { 1307 return false 1308 } 1309 if ann.isConst(e) { 1310 return false 1311 } 1312 if isNilIdent(e) { 1313 return false 1314 } 1315 1316 // TODO: review 1317 if e2, ok := ctx.takingVarAddress(); ok { 1318 if e2 == e { 1319 return false 1320 } 1321 } 1322 1323 switch t := e.(type) { 1324 case *ast.BasicLit: 1325 return false 1326 case *ast.CallExpr: 1327 return true 1328 case *ast.FuncLit: 1329 return true 1330 case *ast.TypeAssertExpr: 1331 return true 1332 case *ast.ParenExpr: 1333 return ann.canAssignToVar(ctx, t.X) 1334 case *ast.StarExpr: 1335 return !ctx.boolean(ctxIdExprInLhs) && !ann.isType(t.X) 1336 case *ast.SelectorExpr: 1337 // could be a const in a pkg (pkg.const1) 1338 //return !ann.isType(t.Sel) && !ann.isConst(t.Sel) 1339 return ann.canAssignToVar(ctx, t.Sel) 1340 case *ast.Ident: 1341 //return !ann.isType(t) && !ann.isConst(t) 1342 return true 1343 case *ast.IndexExpr, *ast.SliceExpr: 1344 // ex: a[i]=b // can't replace a[i] // TODO: it could with an address but that can't be done here 1345 return !ctx.boolean(ctxIdExprInLhs) 1346 1347 case *ast.BinaryExpr: 1348 switch t.Op { 1349 // depend on one being assignable (both could be consts) 1350 case 1351 token.ADD, // + 1352 token.SUB, // - 1353 token.MUL, // * 1354 token.QUO, // / 1355 token.REM, // % 1356 1357 token.AND, // & 1358 token.OR, // | 1359 token.XOR, // ^ 1360 //token.SHL, // << // depend on left arg only 1361 //token.SHR, // >> // depend on left arg only 1362 token.AND_NOT: // &^ 1363 return ann.canAssignToVar(ctx, t.X) || ann.canAssignToVar(ctx, t.Y) 1364 1365 // depend on the left arg 1366 case token.SHL, // << 1367 token.SHR: // >> 1368 return ann.canAssignToVar(ctx, t.X) 1369 1370 default: 1371 // ex: a>b 1372 return true 1373 } 1374 1375 case *ast.UnaryExpr: 1376 switch t.Op { 1377 case token.AND, // ex: &a 1378 token.ARROW: // ex: <-a 1379 return true 1380 case token.ADD, // ex: 1+(+2) 1381 token.SUB, // ex: 1+(-2) 1382 token.XOR, // ex: ^a 1383 token.NOT: // ex: !a 1384 return ann.canAssignToVar(ctx, t.X) // can be a const 1385 } 1386 1387 default: 1388 fmt.Printf("todo: canassigntovar: %T", e) 1389 } 1390 return false 1391 } 1392 1393 //---------- 1394 1395 func (ann *Annotator) wrapInitInBlockAndVisit(ctx *Ctx, stmt ast.Stmt, initStmt *ast.Stmt) bool { 1396 if *initStmt == nil { 1397 return false 1398 } 1399 1400 if _, ok := ctx.labeledStmt(); ok { 1401 // setup debug msg 1402 bls := basicLitStringQ("init not annotated due to label stmt") 1403 ce := ann.newDebugI(ctx, "ILa", bls) 1404 ann.insertDebugLine(ctx, stmt.Pos(), ce) 1405 return false 1406 } 1407 1408 // wrap in blockstmt to have vars that belong only to init 1409 bs := &ast.BlockStmt{} 1410 bs.List = append(bs.List, *initStmt, stmt) 1411 //ctx.nilifyStmt(initStmt) 1412 *initStmt = nil 1413 ctx.replaceStmt(bs) 1414 1415 ann.vis(ctx, bs) 1416 1417 return true 1418 } 1419 1420 //func (ann *Annotator) wrapInBlockIfInit(ctx *Ctx, stmt ast.Stmt, initStmt *ast.Stmt) (*Ctx, bool) { 1421 // if *initStmt == nil { 1422 // return nil, false 1423 // } 1424 1425 // //if _, ok := ctx.labeledStmt(); ok { 1426 // // // setup debug msg 1427 // // bls := basicLitStringQ("init not annotated due to label stmt") 1428 // // ce := ann.newDebugItem(ctx, "ILa", bls) 1429 // // ann.insertDebugLine(ctx, stmt.Pos(), ce) 1430 // // return false 1431 // //} 1432 1433 // // wrap in blockstmt to have vars that belong only to init 1434 // bs := &ast.BlockStmt{} 1435 // bs.List = append(bs.List, *initStmt, stmt) 1436 // *initStmt = nil 1437 // ctx.replaceStmt(bs) 1438 1439 // ctx2 := ctx.withStmts(&bs.List) 1440 // ann.vis(ctx2, bs) 1441 1442 // return true 1443 //} 1444 1445 //---------- 1446 1447 //func (ann *Annotator) castStringToItem(ctx *Ctx, v string) ast.Expr { 1448 // se := &ast.SelectorExpr{ 1449 // X: ast.NewIdent(ann.debugPkgName), 1450 // Sel: ast.NewIdent("Item"), 1451 // } 1452 // bl := basicLitStringQ(v) 1453 // return &ast.CallExpr{Fun: se, Args: []ast.Expr{bl}} 1454 //} 1455 1456 func (ann *Annotator) resType(ctx *Ctx, e ast.Expr) ast.Expr { 1457 //str := "type" 1458 //switch t := e.(type) { 1459 //case *ast.InterfaceType: 1460 //case *ast.MapType: 1461 // str = "map" 1462 //case *ast.ArrayType: 1463 // str = "array" 1464 // if t.Len == nil { 1465 // str = "slice" 1466 // } 1467 //case *ast.SelectorExpr: 1468 // str = "type" 1469 //} 1470 1471 return ann.newDebugIVsBl(ctx, "T") 1472 } 1473 1474 //---------- 1475 1476 func (ann *Annotator) splitGenDecl(ctx *Ctx, gd *ast.GenDecl) { 1477 // keep to reset later 1478 si := ctx.stmtsIter() 1479 after := si.after 1480 1481 ctx2 := ctx.withInsertStmtAfter(true) 1482 for _, spec := range gd.Specs { 1483 gd2 := &ast.GenDecl{Tok: gd.Tok, Specs: []ast.Spec{spec}} 1484 stmt := &ast.DeclStmt{Decl: gd2} 1485 ctx2.insertStmt(stmt) 1486 } 1487 // reset counter to have the other specs be visited 1488 si.after = after 1489 // clear gd stmt, will output as "var ()" 1490 gd.Specs = nil 1491 } 1492 1493 //---------- 1494 1495 func (ann *Annotator) annotationBlockCtx(ctx *Ctx, n ast.Node) *Ctx { 1496 // TODO: catches "godebug" directives surrounded with blank lines? 1497 1498 // catch "godebug" directive at the top of this node 1499 on, ok := ann.annotationBlockOn(n) 1500 1501 // if annotating only blocks, start with no annotations 1502 // TODO: confusing? there is no other way having only a block being annotated and don't annotate the rest 1503 if ok && on { 1504 if _, ok2 := n.(*ast.File); ok2 { 1505 on = false 1506 } 1507 } 1508 1509 if ok && ctx.boolean(ctxIdNoAnnotations) != !on { 1510 return ctx.withBoolean(ctxIdNoAnnotations, !on) 1511 } 1512 return ctx 1513 } 1514 1515 // Returns (on/off, ok) 1516 func (ann *Annotator) annotationBlockOn(n ast.Node) (bool, bool) { 1517 if ann.nodeAnnTypes == nil { 1518 return false, false 1519 } 1520 at, ok := ann.nodeAnnTypes[n] 1521 if !ok { 1522 return false, false 1523 } 1524 switch at { 1525 case AnnotationTypeOff: 1526 return false, true 1527 case AnnotationTypeBlock: 1528 return true, true 1529 default: 1530 return false, false 1531 } 1532 } 1533 1534 //---------- 1535 1536 func (ann *Annotator) isType(e ast.Expr) bool { 1537 if ann.simpleTestMode { 1538 return false 1539 } 1540 tv, ok := ann.typev(e) 1541 return ok && tv.IsType() 1542 } 1543 1544 func (ann *Annotator) isBuiltin(e ast.Expr) bool { 1545 if ann.simpleTestMode { 1546 return true 1547 } 1548 tv, ok := ann.typev(e) 1549 return ok && tv.IsBuiltin() 1550 } 1551 1552 //// ex: fn() is not addressable (can't do "&fn()", only a:=fn(); &a) 1553 //func (ann *Annotator) isAddressable(e ast.Expr) bool { 1554 // tv, ok := ann.typev(e) 1555 // return ok && tv.Addressable() 1556 //} 1557 1558 func (ann *Annotator) isConst(e ast.Expr) bool { 1559 if ann.simpleTestMode { 1560 //if id, ok := e.(*ast.Ident); ok { 1561 // isVar := strings.HasPrefix(id.Name, ann.debugVarPrefix) 1562 // return !isVar 1563 //} 1564 return false 1565 } 1566 1567 tv, ok := ann.typev(e) 1568 return ok && tv.Value != nil 1569 1570 //if !ok || tv.Value == nil { 1571 // return false 1572 //} 1573 //switch tv.Value.Kind() { 1574 //case constant.Int, constant.Float, constant.Complex: 1575 // return true 1576 //default: 1577 // return false 1578 //} 1579 } 1580 1581 func (ann *Annotator) isBigConst(e ast.Expr) (string, bool) { 1582 // handles big constants: 1583 // _=uint64(1<<64 - 1) 1584 // _=uint64(math.MaxUint64) 1585 // the annotator would generate IV(1<<64), which will give a compile error since "1<<64" overflows an int (consts are assigned to int by default) 1586 1587 tv, ok := ann.typev(e) 1588 if !ok || tv.Value == nil { 1589 return "", false 1590 } 1591 u := constant.Val(tv.Value) 1592 switch t := u.(type) { 1593 case *big.Int, *big.Float, *big.Rat: 1594 return fmt.Sprintf("%s", t), true 1595 } 1596 return "", false 1597 } 1598 1599 func (ann *Annotator) typev(e ast.Expr) (types.TypeAndValue, bool) { 1600 if ann.typesInfo == nil { 1601 return types.TypeAndValue{}, false 1602 } 1603 tv, ok := ann.typesInfo.Types[e] 1604 return tv, ok 1605 } 1606 1607 //---------- 1608 1609 // Correct debugindexes to have the numbers attributed in order at compile time. Allows assuming an ordered slice (debugindex/textindex) in the editor. 1610 func (ann *Annotator) correctDebugIndexes(n ast.Node) int { 1611 1612 type lineInfo struct { 1613 lineCE *ast.CallExpr 1614 oldDebugIndex int 1615 byteIndex int // fset position offset (for sort) 1616 seenCount int 1617 } 1618 seenCount := 0 1619 lines := []*lineInfo{} 1620 1621 // collect all calls to debug.Line() 1622 ast.Inspect(n, func(n2 ast.Node) bool { 1623 // find line callexpr 1624 ce := (*ast.CallExpr)(nil) 1625 switch t2 := n2.(type) { 1626 case *ast.CallExpr: 1627 ce2 := t2 1628 if se, ok := ce2.Fun.(*ast.SelectorExpr); ok { 1629 if id, ok := se.X.(*ast.Ident); ok { 1630 if id.Name == ann.debugPkgName && se.Sel.Name == "Line" { 1631 ce = ce2 1632 } 1633 } 1634 } 1635 } 1636 if ce == nil { 1637 return true // continue 1638 } 1639 1640 // debugindex 1641 di, err := strconv.Atoi(ce.Args[1].(*ast.BasicLit).Value) 1642 if err != nil { 1643 panic(err) 1644 } 1645 // fset offset position (byteindex) 1646 byteIndex, err := strconv.Atoi(ce.Args[2].(*ast.BasicLit).Value) 1647 if err != nil { 1648 panic(err) 1649 } 1650 // keep 1651 li := &lineInfo{ 1652 lineCE: ce, 1653 oldDebugIndex: di, 1654 byteIndex: byteIndex, 1655 seenCount: seenCount, 1656 } 1657 seenCount++ 1658 1659 lines = append(lines, li) 1660 1661 return true 1662 }) 1663 1664 // sort debug lines by byteindex (fset offset) 1665 sort.Slice(lines, func(a, b int) bool { 1666 va, vb := lines[a], lines[b] 1667 if va.byteIndex == vb.byteIndex { 1668 // the one seen first while visiting the ast 1669 return va.seenCount < vb.seenCount 1670 } 1671 return va.byteIndex < vb.byteIndex 1672 }) 1673 1674 // setup new debug indexes 1675 di := 0 1676 m := map[int]int{} // [textIndex]debugIndex 1677 for _, li := range lines { // visited by byteindex order 1678 di2 := di 1679 // check if this debugIndex was already seen 1680 if di3, ok := m[li.oldDebugIndex]; ok { 1681 di2 = di3 1682 } else { 1683 // assign new debug index 1684 di2 = di 1685 m[li.oldDebugIndex] = di 1686 di++ 1687 } 1688 1689 // assign final debug index 1690 li.lineCE.Args[1] = basicLitInt(di2) 1691 } 1692 1693 return di 1694 } 1695 1696 //---------- 1697 1698 func (ann *Annotator) removeInnerFuncComments(astFile *ast.File) { 1699 // ensure comments are not in between stmts in the middle of declarations inside functions (solves test100) 1700 // Other comments stay in place since they might be needed (build comments, "c" package comments, ...) 1701 u := astFile.Comments[:0] // use already allocated mem 1702 for _, cg := range astFile.Comments { // all comments 1703 keep := true 1704 1705 // check if inside func decl 1706 for _, d := range astFile.Decls { 1707 if _, ok := d.(*ast.FuncDecl); !ok { 1708 continue 1709 } 1710 if d.Pos() > cg.End() { // passed comment 1711 break 1712 } 1713 in := cg.Pos() >= d.Pos() && cg.Pos() < d.End() 1714 if in { 1715 keep = false 1716 break 1717 } 1718 } 1719 1720 if keep { 1721 u = append(u, cg) 1722 } 1723 } 1724 astFile.Comments = u 1725 } 1726 1727 //---------- 1728 1729 func (ann *Annotator) sprintNode(n ast.Node) string { 1730 return astut.SprintNode(ann.fset, n) 1731 } 1732 func (ann *Annotator) printNode(n ast.Node) { 1733 fmt.Println(ann.sprintNode(n)) 1734 } 1735 1736 //---------- 1737 1738 //func (ann *Annotator) wrapInParenIfNotSimple(ctx *Ctx, e ast.Expr) ast.Expr { 1739 // if !isSimple(e) { 1740 // return ann.newDebugIP(ctx, e) 1741 // } 1742 // return e 1743 //} 1744 1745 //---------- 1746 //---------- 1747 //---------- 1748 1749 //func isSimple(e ast.Expr) bool { 1750 // return isIdentOrSelectorOfIdents(e) 1751 //} 1752 1753 func isIdentOrSelectorOfIdents(e ast.Expr) bool { 1754 switch t := e.(type) { 1755 case *ast.Ident: 1756 return true 1757 case *ast.SelectorExpr: 1758 return isIdentOrSelectorOfIdents(t.X) 1759 } 1760 // ex: (a+b).Fn() 1761 return false 1762 } 1763 1764 //---------- 1765 1766 var _emptyExpr = &ast.Ident{Name: "*emptyExpr*"} 1767 1768 func emptyExpr() ast.Expr { return _emptyExpr } 1769 1770 //---------- 1771 1772 func nilIdent() *ast.Ident { 1773 return &ast.Ident{Name: "nil"} 1774 } 1775 func isNilIdent(e ast.Expr) bool { 1776 return isIdentWithName(e, "nil") 1777 } 1778 1779 func anonIdent() *ast.Ident { 1780 return &ast.Ident{Name: "_"} 1781 } 1782 func isAnonIdent(e ast.Expr) bool { 1783 return isIdentWithName(e, "_") 1784 } 1785 1786 func afterPanicIdent() *ast.Ident { 1787 return &ast.Ident{Name: "after panic"} 1788 } 1789 func isAfterPanicIdent(e ast.Expr) bool { 1790 return isIdentWithName(e, "after panic") 1791 } 1792 1793 func isIdentWithName(e ast.Expr, name string) bool { 1794 id, ok := e.(*ast.Ident) 1795 return ok && id.Name == name 1796 } 1797 1798 //---------- 1799 1800 func basicLitString(v string) *ast.BasicLit { 1801 s := strings.ReplaceAll(v, "%", "%%") 1802 return &ast.BasicLit{Kind: token.STRING, Value: s} 1803 } 1804 func basicLitStringQ(v string) *ast.BasicLit { // quoted 1805 s := strings.ReplaceAll(v, "%", "%%") 1806 return &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("%q", s)} 1807 } 1808 func basicLitInt(v int) *ast.BasicLit { 1809 return &ast.BasicLit{Kind: token.INT, Value: fmt.Sprintf("%d", v)} 1810 }