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  }