github.com/gotranspile/cxgo@v0.3.8-0.20240118201721-29871598a6a2/go_print.go (about) 1 package cxgo 2 3 import ( 4 "go/ast" 5 "go/format" 6 token2 "go/token" 7 "io" 8 "sort" 9 "strconv" 10 "strings" 11 12 "github.com/gotranspile/cxgo/libs" 13 ) 14 15 func PrintGo(w io.Writer, pkg string, decls []GoDecl, donotedit bool) error { 16 if donotedit { 17 w.Write([]byte("// Code generated by cxgo. DO NOT EDIT.\n\n")) 18 } 19 return format.Node(w, token2.NewFileSet(), &ast.File{ 20 Decls: decls, 21 Name: ident(pkg), 22 }) 23 } 24 25 type usageVisitor struct { 26 used map[string]struct{} 27 } 28 29 func (v *usageVisitor) Visit(n ast.Node) ast.Visitor { 30 switch n := n.(type) { 31 case *ast.Ident: 32 sub := strings.SplitN(n.Name, ".", 2) 33 if len(sub) == 2 { 34 v.used[sub[0]] = struct{}{} 35 } 36 } 37 return v 38 } 39 40 func goUsedImports(used map[string]struct{}, decls []GoDecl) { 41 for _, d := range decls { 42 ast.Walk(&usageVisitor{used: used}, d) 43 } 44 } 45 46 // ImportsFor generates import specs for well-known imports required for given declarations. 47 func ImportsFor(e *libs.Env, decls []GoDecl) []GoDecl { 48 used := make(map[string]struct{}) 49 goUsedImports(used, decls) 50 var list []string 51 for k := range used { 52 list = append(list, k) 53 } 54 sort.Strings(list) 55 var specs []ast.Spec 56 for _, name := range list { 57 path := e.ResolveImport(name) 58 specs = append(specs, &ast.ImportSpec{Path: &ast.BasicLit{ 59 Kind: token2.STRING, 60 Value: strconv.Quote(path), 61 }}) 62 } 63 if len(specs) == 0 { 64 return nil 65 } 66 return []GoDecl{ 67 &ast.GenDecl{ 68 Tok: token2.IMPORT, 69 Specs: specs, 70 }, 71 } 72 }