Created
September 2, 2020 17:54
-
-
Save lavalamp/f9641969bfc5f327f6a89a70b2f4668a to your computer and use it in GitHub Desktop.
Change a "top level" name (e.g. a package reference) in a go file
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"go/ast" | |
"go/parser" | |
"go/printer" | |
"go/token" | |
"io/ioutil" | |
"log" | |
"os" | |
) | |
func main() { | |
from := os.Args[1] | |
to := os.Args[2] | |
file := os.Args[3] | |
fs := token.NewFileSet() | |
// Parse the file | |
fileAST, err := parser.ParseFile(fs, file, nil, parser.ParseComments) | |
if err != nil { | |
log.Printf("error: %v", file, err) | |
return | |
} | |
count, collision := modifyTopLevelRefs(fileAST, from, to) | |
if collision { | |
log.Fatalf("%q: colliding use of %q, aborting", file, to) | |
} | |
if count == 0 { | |
log.Printf("no uses of %q", from) | |
return | |
} | |
cfg := &printer.Config{ | |
Mode: printer.TabIndent | printer.UseSpaces, | |
Tabwidth: 8, | |
} | |
var outputBuffer bytes.Buffer | |
if err := cfg.Fprint(&outputBuffer, fs, fileAST); err != nil { | |
log.Fatalf("couldn't format: %v", err) | |
} | |
if err := ioutil.WriteFile(file, outputBuffer.Bytes(), os.ModePerm); err != nil { | |
log.Fatalf("failed to write file %q: %v", file, err) | |
} | |
} | |
func modifyTopLevelRefs(f *ast.File, from, to string) (count int, collision bool) { | |
ast.Walk(visitFn(func(n ast.Node) { | |
sel, ok := n.(*ast.SelectorExpr) | |
if !ok { | |
return | |
} | |
id, ok := sel.X.(*ast.Ident) | |
if !ok { | |
return | |
} | |
if id.Obj != nil { | |
return | |
} | |
if id.Name == to { | |
collision = true | |
} | |
if id.Name == from { | |
count++ | |
id.Name = to | |
} | |
}), f) | |
return | |
} | |
type visitFn func(node ast.Node) | |
func (fn visitFn) Visit(node ast.Node) ast.Visitor { | |
fn(node) | |
return fn | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Starting point was https://github.com/KSubedi/gomove and golang.org/x/tools/go/ast/astutil