github.com/gotranspile/cxgo@v0.3.7/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) error {
    16  	return format.Node(w, token2.NewFileSet(), &ast.File{Decls: decls, Name: ident(pkg)})
    17  }
    18  
    19  type usageVisitor struct {
    20  	used map[string]struct{}
    21  }
    22  
    23  func (v *usageVisitor) Visit(n ast.Node) ast.Visitor {
    24  	switch n := n.(type) {
    25  	case *ast.Ident:
    26  		sub := strings.SplitN(n.Name, ".", 2)
    27  		if len(sub) == 2 {
    28  			v.used[sub[0]] = struct{}{}
    29  		}
    30  	}
    31  	return v
    32  }
    33  
    34  func goUsedImports(used map[string]struct{}, decls []GoDecl) {
    35  	for _, d := range decls {
    36  		ast.Walk(&usageVisitor{used: used}, d)
    37  	}
    38  }
    39  
    40  // ImportsFor generates import specs for well-known imports required for given declarations.
    41  func ImportsFor(e *libs.Env, decls []GoDecl) []GoDecl {
    42  	used := make(map[string]struct{})
    43  	goUsedImports(used, decls)
    44  	var list []string
    45  	for k := range used {
    46  		list = append(list, k)
    47  	}
    48  	sort.Strings(list)
    49  	var specs []ast.Spec
    50  	for _, name := range list {
    51  		path := e.ResolveImport(name)
    52  		specs = append(specs, &ast.ImportSpec{Path: &ast.BasicLit{
    53  			Kind:  token2.STRING,
    54  			Value: strconv.Quote(path),
    55  		}})
    56  	}
    57  	if len(specs) == 0 {
    58  		return nil
    59  	}
    60  	return []GoDecl{
    61  		&ast.GenDecl{
    62  			Tok:   token2.IMPORT,
    63  			Specs: specs,
    64  		},
    65  	}
    66  }