edit.go raw
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 "golang.org/x/tools/go/analysis"
11 "honnef.co/go/tools/pattern"
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 }
84