github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/analysis/edit/edit.go (about) 1 // Package edit contains helpers for creating suggested fixes. 2 package edit 3 4 import ( 5 "bytes" 6 "go/ast" 7 "go/format" 8 "go/token" 9 10 "github.com/amarpal/go-tools/pattern" 11 "golang.org/x/tools/go/analysis" 12 ) 13 14 // Ranger describes values that have a start and end position. 15 // In most cases these are either ast.Node or manually constructed ranges. 16 type Ranger interface { 17 Pos() token.Pos 18 End() token.Pos 19 } 20 21 // Range implements the Ranger interface. 22 type Range [2]token.Pos 23 24 func (r Range) Pos() token.Pos { return r[0] } 25 func (r Range) End() token.Pos { return r[1] } 26 27 // ReplaceWithString replaces a range with a string. 28 func ReplaceWithString(old Ranger, new string) analysis.TextEdit { 29 return analysis.TextEdit{ 30 Pos: old.Pos(), 31 End: old.End(), 32 NewText: []byte(new), 33 } 34 } 35 36 // ReplaceWithNode replaces a range with an AST node. 37 func ReplaceWithNode(fset *token.FileSet, old Ranger, new ast.Node) analysis.TextEdit { 38 buf := &bytes.Buffer{} 39 if err := format.Node(buf, fset, new); err != nil { 40 panic("internal error: " + err.Error()) 41 } 42 return analysis.TextEdit{ 43 Pos: old.Pos(), 44 End: old.End(), 45 NewText: buf.Bytes(), 46 } 47 } 48 49 // ReplaceWithPattern replaces a range with the result of executing a pattern. 50 func ReplaceWithPattern(fset *token.FileSet, old Ranger, new pattern.Pattern, state pattern.State) analysis.TextEdit { 51 r := pattern.NodeToAST(new.Root, state) 52 buf := &bytes.Buffer{} 53 format.Node(buf, fset, r) 54 return analysis.TextEdit{ 55 Pos: old.Pos(), 56 End: old.End(), 57 NewText: buf.Bytes(), 58 } 59 } 60 61 // Delete deletes a range of code. 62 func Delete(old Ranger) analysis.TextEdit { 63 return analysis.TextEdit{ 64 Pos: old.Pos(), 65 End: old.End(), 66 NewText: nil, 67 } 68 } 69 70 func Fix(msg string, edits ...analysis.TextEdit) analysis.SuggestedFix { 71 return analysis.SuggestedFix{ 72 Message: msg, 73 TextEdits: edits, 74 } 75 } 76 77 // Selector creates a new selector expression. 78 func Selector(x, sel string) *ast.SelectorExpr { 79 return &ast.SelectorExpr{ 80 X: &ast.Ident{Name: x}, 81 Sel: &ast.Ident{Name: sel}, 82 } 83 }