github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/internal/typeparams/copytermlist.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build ignore 6 // +build ignore 7 8 // copytermlist.go copies the term list algorithm from GOROOT/src/go/types. 9 10 package main 11 12 import ( 13 "bytes" 14 "fmt" 15 "go/ast" 16 "go/format" 17 "go/parser" 18 "go/token" 19 "os" 20 "path/filepath" 21 "reflect" 22 "runtime" 23 "strings" 24 25 "github.com/powerman/golang-tools/go/ast/astutil" 26 ) 27 28 func main() { 29 if err := doCopy(); err != nil { 30 fmt.Fprintf(os.Stderr, "error copying from go/types: %v", err) 31 os.Exit(1) 32 } 33 } 34 35 func doCopy() error { 36 dir := filepath.Join(runtime.GOROOT(), "src", "go", "types") 37 for _, name := range []string{"typeterm.go", "termlist.go"} { 38 path := filepath.Join(dir, name) 39 fset := token.NewFileSet() 40 file, err := parser.ParseFile(fset, path, nil, parser.ParseComments) 41 if err != nil { 42 return err 43 } 44 file.Name.Name = "typeparams" 45 file.Doc = &ast.CommentGroup{List: []*ast.Comment{&ast.Comment{Text: "DO NOT MODIFY"}}} 46 var needImport bool 47 selectorType := reflect.TypeOf((*ast.SelectorExpr)(nil)) 48 astutil.Apply(file, func(c *astutil.Cursor) bool { 49 if id, _ := c.Node().(*ast.Ident); id != nil { 50 // Check if this ident should be qualified with types. For simplicity, 51 // assume the copied files do not themselves contain any exported 52 // symbols. 53 54 // As a simple heuristic, just verify that the ident may be replaced by 55 // a selector. 56 if !token.IsExported(id.Name) { 57 return false 58 } 59 v := reflect.TypeOf(c.Parent()).Elem() // ast nodes are all pointers 60 field, ok := v.FieldByName(c.Name()) 61 if !ok { 62 panic("missing field") 63 } 64 t := field.Type 65 if c.Index() > 0 { // => t is a slice 66 t = t.Elem() 67 } 68 if !selectorType.AssignableTo(t) { 69 return false 70 } 71 needImport = true 72 c.Replace(&ast.SelectorExpr{ 73 X: ast.NewIdent("types"), 74 Sel: ast.NewIdent(id.Name), 75 }) 76 } 77 return true 78 }, nil) 79 if needImport { 80 astutil.AddImport(fset, file, "go/types") 81 } 82 83 var b bytes.Buffer 84 if err := format.Node(&b, fset, file); err != nil { 85 return err 86 } 87 88 // Hack in the 'generated' byline. 89 content := b.String() 90 header := "// Code generated by copytermlist.go DO NOT EDIT.\n\npackage typeparams" 91 content = strings.Replace(content, "package typeparams", header, 1) 92 93 if err := os.WriteFile(name, []byte(content), 0644); err != nil { 94 return err 95 } 96 } 97 return nil 98 }