github.com/jmigpin/editor@v1.6.0/core/godebug/comments.go (about) 1 package godebug 2 3 import ( 4 "go/ast" 5 "go/token" 6 "sort" 7 ) 8 9 // https://github.com/golang/go/issues/20744 10 11 // Comment nodes mapped to the following relevant node. Used for godebug directives. 12 func commentsWithNodes(fset *token.FileSet, topNode ast.Node, cgs []*ast.CommentGroup) (res []*CommentWithNode) { 13 14 // ensure it is sorted (sanity check) 15 sort.Slice(cgs, func(a, b int) bool { 16 return cgs[a].Pos() < cgs[b].Pos() 17 }) 18 19 k := -1 20 next := func() *ast.CommentGroup { 21 k++ 22 if k < len(cgs) { 23 return cgs[k] 24 } 25 return nil 26 } 27 cur := next() // current 28 ast.Inspect(topNode, func(n ast.Node) bool { 29 if cur == nil { 30 return false 31 } 32 n2 := (ast.Node)(nil) 33 switch n.(type) { 34 case ast.Stmt, ast.Decl, ast.Spec: // relevant node 35 n2 = n 36 } 37 if n2 == nil { 38 return true 39 } 40 // catch first node after the comment 41 for n2.Pos() > cur.Pos() { 42 for _, c := range cur.List { 43 u := &CommentWithNode{c, n2} 44 res = append(res, u) 45 } 46 cur = next() 47 if cur == nil { 48 break 49 } 50 } 51 return true 52 }) 53 return res 54 } 55 56 type CommentWithNode struct { 57 Comment *ast.Comment 58 Node ast.Node 59 } 60 61 //---------- 62 63 //func annOptNodesMap2(fset *token.FileSet, astFile *ast.File, opts []*AnnotationOpt) map[*AnnotationOpt]ast.Node { 64 // m := map[*AnnotationOpt]ast.Node{} 65 // if len(opts) == 0 { 66 // return m 67 // } 68 69 // sort.Slice(opts, func(a, b int) bool { 70 // return opts[a].Comment.Pos() < opts[b].Comment.Pos() 71 // }) 72 73 // k := -1 74 // nextOpt := func() *AnnotationOpt { 75 // k++ 76 // if k < len(opts) { 77 // return opts[k] 78 // } 79 // return nil 80 // } 81 // cur := nextOpt() // current 82 // ast.Inspect(astFile, func(n ast.Node) bool { 83 // // catch first node after the comment 84 85 // if cur == nil { 86 // return false 87 // } 88 // n2 := (ast.Node)(nil) 89 // switch n.(type) { 90 // case ast.Stmt, ast.Decl, ast.Spec: 91 // n2 = n 92 // } 93 // if n2 != nil { 94 // if n2.Pos() > cur.Comment.Pos() { 95 // m[cur] = n2 96 // cur.Node = n2 97 // cur = nextOpt() 98 // } 99 // } 100 // return true 101 // }) 102 103 // // fill rest of nodes with astfile 104 // for ; cur != nil; cur = nextOpt() { 105 // m[cur] = astFile 106 // cur.Node = astFile 107 // } 108 109 // return m 110 //} 111 112 //---------- 113 114 //// commented: attaches to previous comments 115 //func annOptNodesMap1(fset *token.FileSet, astFile *ast.File, opts []*AnnotationOpt) map[*AnnotationOpt]ast.Node { 116 // // wrap comments in commentgroups to use ast.NewCommentMap 117 // cgs := []*ast.CommentGroup{} 118 // cmap := map[*ast.CommentGroup]*AnnotationOpt{} 119 // for _, opt := range opts { 120 // cg := &ast.CommentGroup{List: []*ast.Comment{opt.Comment}} 121 // cgs = append(cgs, cg) 122 // cmap[cg] = opt 123 // } 124 // // map annotations to nodes 125 // nmap := ast.NewCommentMap(fset, astFile, cgs) 126 // optm := map[*AnnotationOpt]ast.Node{} 127 // for n, cgs := range nmap { 128 // cg := cgs[0] 129 // opt, ok := cmap[cg] 130 // if ok { 131 // opt.Node = n 132 // optm[opt] = n 133 // } 134 // } 135 // // annotations that have no node, will have astFile as node 136 // for opt := range optm { 137 // if opt.Node == nil { 138 // opt.Node = astFile 139 // optm[opt] = astFile 140 // } 141 // } 142 // return optm 143 //}