"array.go": nil,
"api_predicates.go": nil,
"basic.go": nil,
- "chan.go": nil,
- "const.go": func(f *ast.File) { fixTokenPos(f) },
- "context.go": nil,
- "context_test.go": nil,
- "errsupport.go": nil,
- "gccgosizes.go": nil,
- "gcsizes.go": func(f *ast.File) { renameIdents(f, "IsSyncAtomicAlign64->_IsSyncAtomicAlign64") },
- "hilbert_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"`, `"go/types"`) },
- "infer.go": func(f *ast.File) {
- fixTokenPos(f)
- fixInferSig(f)
+ "builtins.go": func(f *ast.File) {
+ renameImportPath(f, `"cmd/compile/internal/syntax"`, `"go/ast"`)
+ renameIdents(f, "syntax->ast")
+ renameSelectors(f, "ArgList->Args")
+ fixSelValue(f)
+ fixAtPosCall(f)
},
+ "chan.go": nil,
+ "const.go": func(f *ast.File) { fixTokenPos(f) },
+ "context.go": nil,
+ "context_test.go": nil,
+ "errsupport.go": nil,
+ "gccgosizes.go": nil,
+ "gcsizes.go": func(f *ast.File) { renameIdents(f, "IsSyncAtomicAlign64->_IsSyncAtomicAlign64") },
+ "hilbert_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"`, `"go/types"`) },
+ "infer.go": func(f *ast.File) { fixTokenPos(f); fixInferSig(f) },
// "initorder.go": fixErrErrorfCall, // disabled for now due to unresolved error_ use implications for gopls
"instantiate.go": func(f *ast.File) { fixTokenPos(f); fixCheckErrorfCall(f) },
"instantiate_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"`, `"go/types"`) },
"lookup.go": func(f *ast.File) { fixTokenPos(f) },
"main_test.go": nil,
"map.go": nil,
- "named.go": func(f *ast.File) { fixTokenPos(f); fixTraceSel(f) },
+ "named.go": func(f *ast.File) { fixTokenPos(f); renameSelectors(f, "Trace->_Trace") },
"object.go": func(f *ast.File) { fixTokenPos(f); renameIdents(f, "NewTypeNameLazy->_NewTypeNameLazy") },
"object_test.go": func(f *ast.File) { renameImportPath(f, `"cmd/compile/internal/types2"`, `"go/types"`) },
"objset.go": nil,
"package.go": nil,
"pointer.go": nil,
"predicates.go": nil,
- "scope.go": func(f *ast.File) {
- fixTokenPos(f)
- renameIdents(f, "Squash->squash", "InsertLazy->_InsertLazy")
- },
- "selection.go": nil,
- "sizes.go": func(f *ast.File) { renameIdents(f, "IsSyncAtomicAlign64->_IsSyncAtomicAlign64") },
- "slice.go": nil,
- "subst.go": func(f *ast.File) { fixTokenPos(f); fixTraceSel(f) },
- "termlist.go": nil,
- "termlist_test.go": nil,
- "tuple.go": nil,
- "typelists.go": nil,
- "typeparam.go": nil,
- "typeterm_test.go": nil,
- "typeterm.go": nil,
- "under.go": nil,
- "unify.go": fixSprintf,
- "universe.go": fixGlobalTypVarDecl,
- "util_test.go": fixTokenPos,
- "validtype.go": nil,
+ "scope.go": func(f *ast.File) { fixTokenPos(f); renameIdents(f, "Squash->squash", "InsertLazy->_InsertLazy") },
+ "selection.go": nil,
+ "sizes.go": func(f *ast.File) { renameIdents(f, "IsSyncAtomicAlign64->_IsSyncAtomicAlign64") },
+ "slice.go": nil,
+ "subst.go": func(f *ast.File) { fixTokenPos(f); renameSelectors(f, "Trace->_Trace") },
+ "termlist.go": nil,
+ "termlist_test.go": nil,
+ "tuple.go": nil,
+ "typelists.go": nil,
+ "typeparam.go": nil,
+ "typeterm_test.go": nil,
+ "typeterm.go": nil,
+ "under.go": nil,
+ "unify.go": fixSprintf,
+ "universe.go": fixGlobalTypVarDecl,
+ "util_test.go": fixTokenPos,
+ "validtype.go": nil,
}
// TODO(gri) We should be able to make these rewriters more configurable/composable.
// For now this is a good starting point.
-// renameIdent renames identifiers: each renames entry is of the form from->to.
-// Note: This doesn't change the use of the identifiers in comments.
-func renameIdents(f *ast.File, renames ...string) {
- var list [][]string
+// A renameMap maps old names to new names.
+type renameMap map[string]string
+
+// makeRenameMap returns a renameMap populates from renames entries of the form "from->to".
+func makeRenameMap(renames ...string) renameMap {
+ m := make(renameMap)
for _, r := range renames {
s := strings.Split(r, "->")
if len(s) != 2 {
panic("invalid rename entry: " + r)
}
- list = append(list, s)
+ m[s[0]] = s[1]
}
+ return m
+}
+
+// rename renames the given name if a corresponding rename exists in m.
+func (m renameMap) rename(name *string) {
+ if new, ok := m[*name]; ok {
+ *name = new
+ }
+}
+
+// renameIdents renames identifiers: each renames entry is of the form "from->to".
+// Note: This doesn't change the use of the identifiers in comments.
+func renameIdents(f *ast.File, renames ...string) {
+ m := makeRenameMap(renames...)
ast.Inspect(f, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.Ident:
- for _, r := range list {
- if n.Name == r[0] {
- n.Name = r[1]
- }
- }
+ m.rename(&n.Name)
return false
}
return true
})
}
+// renameSelectors is like renameIdents but only looks at selectors.
+func renameSelectors(f *ast.File, renames ...string) {
+ m := makeRenameMap(renames...)
+ ast.Inspect(f, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.SelectorExpr:
+ m.rename(&n.Sel.Name)
+ return false
+ }
+ return true
+ })
+
+}
+
// renameImportPath renames an import path.
func renameImportPath(f *ast.File, from, to string) {
ast.Inspect(f, func(n ast.Node) bool {
}
case *ast.SelectorExpr:
// rewrite syntax.Pos to token.Pos
- if x, _ := n.X.(*ast.Ident); x != nil && x.Name == "syntax" && n.Sel.Name == "Pos" {
+ if x := asIdent(n.X, "syntax"); x != nil && n.Sel.Name == "Pos" {
x.Name = "token"
return false
}
})
}
+// fixSelValue updates the selector Sel.Value to Sel.Name.
+func fixSelValue(f *ast.File) {
+ ast.Inspect(f, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.SelectorExpr:
+ if n.Sel.Name == "Value" {
+ if selx, _ := n.X.(*ast.SelectorExpr); selx != nil && selx.Sel.Name == "Sel" {
+ n.Sel.Name = "Name"
+ return false
+ }
+ }
+ }
+ return true
+ })
+}
+
// fixInferSig updates the Checker.infer signature to use a positioner instead of a token.Position
// as first argument, renames the argument from "pos" to "posn", and updates a few internal uses of
// "pos" to "posn" and "posn.Pos()" respectively.
switch selx.Sel.Name {
case "renameTParams":
// rewrite check.renameTParams(pos, ... ) to check.renameTParams(posn.Pos(), ... )
- if ident, _ := n.Args[0].(*ast.Ident); ident != nil && ident.Name == "pos" {
+ if isIdent(n.Args[0], "pos") {
pos := n.Args[0].Pos()
fun := &ast.SelectorExpr{X: newIdent(pos, "posn"), Sel: newIdent(pos, "Pos")}
arg := &ast.CallExpr{Fun: fun, Lparen: pos, Args: nil, Ellipsis: token.NoPos, Rparen: pos}
}
case "errorf":
// rewrite check.errorf(pos, ...) to check.errorf(posn, ...)
- if ident, _ := n.Args[0].(*ast.Ident); ident != nil && ident.Name == "pos" {
+ if isIdent(n.Args[0], "pos") {
pos := n.Args[0].Pos()
arg := newIdent(pos, "posn")
n.Args[0] = arg
}
case "allowVersion":
// rewrite check.allowVersion(..., pos, ...) to check.allowVersion(..., posn, ...)
- if ident, _ := n.Args[1].(*ast.Ident); ident != nil && ident.Name == "pos" {
+ if isIdent(n.Args[1], "pos") {
pos := n.Args[1].Pos()
arg := newIdent(pos, "posn")
n.Args[1] = arg
})
}
+// fixAtPosCall updates calls of the form atPos(x) to x.Pos() in argument lists of (check).dump calls.
+// TODO(gri) can we avoid this and just use atPos consistently in go/types and types2?
+func fixAtPosCall(f *ast.File) {
+ ast.Inspect(f, func(n ast.Node) bool {
+ switch n := n.(type) {
+ case *ast.CallExpr:
+ if selx, _ := n.Fun.(*ast.SelectorExpr); selx != nil && selx.Sel.Name == "dump" {
+ for i, arg := range n.Args {
+ if call, _ := arg.(*ast.CallExpr); call != nil {
+ // rewrite xxx.dump(..., atPos(x), ...) to xxx.dump(..., x.Pos(), ...)
+ if isIdent(call.Fun, "atPos") {
+ pos := call.Args[0].Pos()
+ fun := &ast.SelectorExpr{X: call.Args[0], Sel: newIdent(pos, "Pos")}
+ n.Args[i] = &ast.CallExpr{Fun: fun, Lparen: pos, Rparen: pos}
+ return false
+ }
+ }
+ }
+ }
+ }
+ return true
+ })
+}
+
// fixErrErrorfCall updates calls of the form err.errorf(obj, ...) to err.errorf(obj.Pos(), ...).
func fixErrErrorfCall(f *ast.File) {
ast.Inspect(f, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.CallExpr:
if selx, _ := n.Fun.(*ast.SelectorExpr); selx != nil {
- if ident, _ := selx.X.(*ast.Ident); ident != nil && ident.Name == "err" {
+ if isIdent(selx.X, "err") {
switch selx.Sel.Name {
case "errorf":
// rewrite err.errorf(obj, ... ) to err.errorf(obj.Pos(), ... )
if ident, _ := n.Args[0].(*ast.Ident); ident != nil && ident.Name == "obj" {
pos := n.Args[0].Pos()
fun := &ast.SelectorExpr{X: ident, Sel: newIdent(pos, "Pos")}
- arg := &ast.CallExpr{Fun: fun, Lparen: pos, Args: nil, Ellipsis: token.NoPos, Rparen: pos}
- n.Args[0] = arg
+ n.Args[0] = &ast.CallExpr{Fun: fun, Lparen: pos, Rparen: pos}
return false
}
}
switch n := n.(type) {
case *ast.CallExpr:
if selx, _ := n.Fun.(*ast.SelectorExpr); selx != nil {
- if ident, _ := selx.X.(*ast.Ident); ident != nil && ident.Name == "check" {
+ if isIdent(selx.X, "check") {
switch selx.Sel.Name {
case "errorf":
// rewrite check.errorf(pos, ... ) to check.errorf(atPos(pos), ... )
- if ident, _ := n.Args[0].(*ast.Ident); ident != nil && ident.Name == "pos" {
+ if ident := asIdent(n.Args[0], "pos"); ident != nil {
pos := n.Args[0].Pos()
fun := newIdent(pos, "atPos")
- arg := &ast.CallExpr{Fun: fun, Lparen: pos, Args: []ast.Expr{ident}, Ellipsis: token.NoPos, Rparen: pos}
- n.Args[0] = arg
+ n.Args[0] = &ast.CallExpr{Fun: fun, Lparen: pos, Args: []ast.Expr{ident}, Rparen: pos}
return false
}
}
})
}
-// fixTraceSel renames uses of x.Trace to x.trace, where x for any x with a Trace field.
-func fixTraceSel(f *ast.File) {
- ast.Inspect(f, func(n ast.Node) bool {
- switch n := n.(type) {
- case *ast.SelectorExpr:
- // rewrite x.Trace to x._Trace (for Config.Trace)
- if n.Sel.Name == "Trace" {
- n.Sel.Name = "_Trace"
- return false
- }
- }
- return true
- })
-}
-
// fixGlobalTypVarDecl changes the global Typ variable from an array to a slice
// (in types2 we use an array for efficiency, in go/types it's a slice and we
// cannot change that).
ast.Inspect(f, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.CallExpr:
- if fun, _ := n.Fun.(*ast.Ident); fun != nil && fun.Name == "sprintf" && len(n.Args) >= 4 /* ... args */ {
+ if isIdent(n.Fun, "sprintf") && len(n.Args) >= 4 /* ... args */ {
n.Args = insert(n.Args, 1, newIdent(n.Args[1].Pos(), "nil"))
return false
}
})
}
+// asIdent returns x as *ast.Ident if it is an identifier with the given name.
+func asIdent(x ast.Node, name string) *ast.Ident {
+ if ident, _ := x.(*ast.Ident); ident != nil && ident.Name == name {
+ return ident
+ }
+ return nil
+}
+
+// isIdent reports whether x is an identifier with the given name.
+func isIdent(x ast.Node, name string) bool {
+ return asIdent(x, name) != nil
+}
+
// newIdent returns a new identifier with the given position and name.
func newIdent(pos token.Pos, name string) *ast.Ident {
id := ast.NewIdent(name)