whatcanGOwrong
This commit is contained in:
+1
@@ -0,0 +1 @@
|
||||
testdata/out.got
|
||||
+485
@@ -0,0 +1,485 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Bundle creates a single-source-file version of a source package
|
||||
// suitable for inclusion in a particular target package.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// bundle [-o file] [-dst path] [-pkg name] [-prefix p] [-import old=new] [-tags build_constraints] <src>
|
||||
//
|
||||
// The src argument specifies the import path of the package to bundle.
|
||||
// The bundling of a directory of source files into a single source file
|
||||
// necessarily imposes a number of constraints.
|
||||
// The package being bundled must not use cgo; must not use conditional
|
||||
// file compilation, whether with build tags or system-specific file names
|
||||
// like code_amd64.go; must not depend on any special comments, which
|
||||
// may not be preserved; must not use any assembly sources;
|
||||
// must not use renaming imports; and must not use reflection-based APIs
|
||||
// that depend on the specific names of types or struct fields.
|
||||
//
|
||||
// By default, bundle writes the bundled code to standard output.
|
||||
// If the -o argument is given, bundle writes to the named file
|
||||
// and also includes a “//go:generate” comment giving the exact
|
||||
// command line used, for regenerating the file with “go generate.”
|
||||
//
|
||||
// Bundle customizes its output for inclusion in a particular package, the destination package.
|
||||
// By default bundle assumes the destination is the package in the current directory,
|
||||
// but the destination package can be specified explicitly using the -dst option,
|
||||
// which takes an import path as its argument.
|
||||
// If the source package imports the destination package, bundle will remove
|
||||
// those imports and rewrite any references to use direct references to the
|
||||
// corresponding symbols.
|
||||
// Bundle also must write a package declaration in the output and must
|
||||
// choose a name to use in that declaration.
|
||||
// If the -pkg option is given, bundle uses that name.
|
||||
// Otherwise, the name of the destination package is used.
|
||||
// Build constraints for the generated file can be specified using the -tags option.
|
||||
//
|
||||
// To avoid collisions, bundle inserts a prefix at the beginning of
|
||||
// every package-level const, func, type, and var identifier in src's code,
|
||||
// updating references accordingly. The default prefix is the package name
|
||||
// of the source package followed by an underscore. The -prefix option
|
||||
// specifies an alternate prefix.
|
||||
//
|
||||
// Occasionally it is necessary to rewrite imports during the bundling
|
||||
// process. The -import option, which may be repeated, specifies that
|
||||
// an import of "old" should be rewritten to import "new" instead.
|
||||
//
|
||||
// # Example
|
||||
//
|
||||
// Bundle archive/zip for inclusion in cmd/dist:
|
||||
//
|
||||
// cd $GOROOT/src/cmd/dist
|
||||
// bundle -o zip.go archive/zip
|
||||
//
|
||||
// Bundle golang.org/x/net/http2 for inclusion in net/http,
|
||||
// prefixing all identifiers by "http2" instead of "http2_", and
|
||||
// including a "!nethttpomithttp2" build constraint:
|
||||
//
|
||||
// cd $GOROOT/src/net/http
|
||||
// bundle -o h2_bundle.go -prefix http2 -tags '!nethttpomithttp2' golang.org/x/net/http2
|
||||
//
|
||||
// Update the http2 bundle in net/http:
|
||||
//
|
||||
// go generate net/http
|
||||
//
|
||||
// Update all bundles in the standard library:
|
||||
//
|
||||
// go generate -run bundle std
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
var (
|
||||
outputFile = flag.String("o", "", "write output to `file` (default standard output)")
|
||||
dstPath = flag.String("dst", ".", "set destination import `path`")
|
||||
pkgName = flag.String("pkg", "", "set destination package `name`")
|
||||
prefix = flag.String("prefix", "&_", "set bundled identifier prefix to `p` (default is \"&_\", where & stands for the original name)")
|
||||
buildTags = flag.String("tags", "", "the build constraints to be inserted into the generated file")
|
||||
|
||||
importMap = map[string]string{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Var(flagFunc(addImportMap), "import", "rewrite import using `map`, of form old=new (can be repeated)")
|
||||
}
|
||||
|
||||
func addImportMap(s string) {
|
||||
if strings.Count(s, "=") != 1 {
|
||||
log.Fatal("-import argument must be of the form old=new")
|
||||
}
|
||||
i := strings.Index(s, "=")
|
||||
old, new := s[:i], s[i+1:]
|
||||
if old == "" || new == "" {
|
||||
log.Fatal("-import argument must be of the form old=new; old and new must be non-empty")
|
||||
}
|
||||
importMap[old] = new
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "Usage: bundle [options] <src>\n")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetPrefix("bundle: ")
|
||||
log.SetFlags(0)
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
args := flag.Args()
|
||||
if len(args) != 1 {
|
||||
usage()
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
cfg := &packages.Config{Mode: packages.NeedName}
|
||||
pkgs, err := packages.Load(cfg, *dstPath)
|
||||
if err != nil {
|
||||
log.Fatalf("cannot load destination package: %v", err)
|
||||
}
|
||||
if packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {
|
||||
log.Fatalf("failed to load destination package")
|
||||
}
|
||||
if *pkgName == "" {
|
||||
*pkgName = pkgs[0].Name
|
||||
}
|
||||
|
||||
code, err := bundle(args[0], pkgs[0].PkgPath, *pkgName, *prefix, *buildTags)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if *outputFile != "" {
|
||||
err := os.WriteFile(*outputFile, code, 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
_, err := os.Stdout.Write(code)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// isStandardImportPath is copied from cmd/go in the standard library.
|
||||
func isStandardImportPath(path string) bool {
|
||||
i := strings.Index(path, "/")
|
||||
if i < 0 {
|
||||
i = len(path)
|
||||
}
|
||||
elem := path[:i]
|
||||
return !strings.Contains(elem, ".")
|
||||
}
|
||||
|
||||
var testingOnlyPackagesConfig *packages.Config
|
||||
|
||||
func bundle(src, dst, dstpkg, prefix, buildTags string) ([]byte, error) {
|
||||
// Load the initial package.
|
||||
cfg := &packages.Config{}
|
||||
if testingOnlyPackagesConfig != nil {
|
||||
*cfg = *testingOnlyPackagesConfig
|
||||
} else {
|
||||
// Bypass default vendor mode, as we need a package not available in the
|
||||
// std module vendor folder.
|
||||
cfg.Env = append(os.Environ(), "GOFLAGS=-mod=mod")
|
||||
}
|
||||
cfg.Mode = packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo
|
||||
pkgs, err := packages.Load(cfg, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if packages.PrintErrors(pkgs) > 0 || len(pkgs) != 1 {
|
||||
return nil, fmt.Errorf("failed to load source package")
|
||||
}
|
||||
pkg := pkgs[0]
|
||||
|
||||
if strings.Contains(prefix, "&") {
|
||||
prefix = strings.Replace(prefix, "&", pkg.Syntax[0].Name.Name, -1)
|
||||
}
|
||||
|
||||
objsToUpdate := make(map[types.Object]bool)
|
||||
var rename func(from types.Object)
|
||||
rename = func(from types.Object) {
|
||||
if !objsToUpdate[from] {
|
||||
objsToUpdate[from] = true
|
||||
|
||||
// Renaming a type that is used as an embedded field
|
||||
// requires renaming the field too. e.g.
|
||||
// type T int // if we rename this to U..
|
||||
// var s struct {T}
|
||||
// print(s.T) // ...this must change too
|
||||
if _, ok := from.(*types.TypeName); ok {
|
||||
for id, obj := range pkg.TypesInfo.Uses {
|
||||
if obj == from {
|
||||
if field := pkg.TypesInfo.Defs[id]; field != nil {
|
||||
rename(field)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rename each package-level object.
|
||||
scope := pkg.Types.Scope()
|
||||
for _, name := range scope.Names() {
|
||||
rename(scope.Lookup(name))
|
||||
}
|
||||
|
||||
var out bytes.Buffer
|
||||
if buildTags != "" {
|
||||
fmt.Fprintf(&out, "//go:build %s\n", buildTags)
|
||||
}
|
||||
|
||||
fmt.Fprintf(&out, "// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.\n")
|
||||
if *outputFile != "" && buildTags == "" {
|
||||
fmt.Fprintf(&out, "//go:generate bundle %s\n", strings.Join(quoteArgs(os.Args[1:]), " "))
|
||||
} else {
|
||||
fmt.Fprintf(&out, "// $ bundle %s\n", strings.Join(os.Args[1:], " "))
|
||||
}
|
||||
fmt.Fprintf(&out, "\n")
|
||||
|
||||
// Concatenate package comments from all files...
|
||||
for _, f := range pkg.Syntax {
|
||||
if doc := f.Doc.Text(); strings.TrimSpace(doc) != "" {
|
||||
for _, line := range strings.Split(doc, "\n") {
|
||||
fmt.Fprintf(&out, "// %s\n", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
// ...but don't let them become the actual package comment.
|
||||
fmt.Fprintln(&out)
|
||||
|
||||
fmt.Fprintf(&out, "package %s\n\n", dstpkg)
|
||||
|
||||
// BUG(adonovan,shurcooL): bundle may generate incorrect code
|
||||
// due to shadowing between identifiers and imported package names.
|
||||
//
|
||||
// The generated code will either fail to compile or
|
||||
// (unlikely) compile successfully but have different behavior
|
||||
// than the original package. The risk of this happening is higher
|
||||
// when the original package has renamed imports (they're typically
|
||||
// renamed in order to resolve a shadow inside that particular .go file).
|
||||
|
||||
// TODO(adonovan,shurcooL):
|
||||
// - detect shadowing issues, and either return error or resolve them
|
||||
// - preserve comments from the original import declarations.
|
||||
|
||||
// pkgStd and pkgExt are sets of printed import specs. This is done
|
||||
// to deduplicate instances of the same import name and path.
|
||||
var pkgStd = make(map[string]bool)
|
||||
var pkgExt = make(map[string]bool)
|
||||
for _, f := range pkg.Syntax {
|
||||
for _, imp := range f.Imports {
|
||||
path, err := strconv.Unquote(imp.Path.Value)
|
||||
if err != nil {
|
||||
log.Fatalf("invalid import path string: %v", err) // Shouldn't happen here since packages.Load succeeded.
|
||||
}
|
||||
if path == dst {
|
||||
continue
|
||||
}
|
||||
if newPath, ok := importMap[path]; ok {
|
||||
path = newPath
|
||||
}
|
||||
|
||||
var name string
|
||||
if imp.Name != nil {
|
||||
name = imp.Name.Name
|
||||
}
|
||||
spec := fmt.Sprintf("%s %q", name, path)
|
||||
if isStandardImportPath(path) {
|
||||
pkgStd[spec] = true
|
||||
} else {
|
||||
pkgExt[spec] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print a single declaration that imports all necessary packages.
|
||||
fmt.Fprintln(&out, "import (")
|
||||
for p := range pkgStd {
|
||||
fmt.Fprintf(&out, "\t%s\n", p)
|
||||
}
|
||||
if len(pkgExt) > 0 {
|
||||
fmt.Fprintln(&out)
|
||||
}
|
||||
for p := range pkgExt {
|
||||
fmt.Fprintf(&out, "\t%s\n", p)
|
||||
}
|
||||
fmt.Fprint(&out, ")\n\n")
|
||||
|
||||
// Modify and print each file.
|
||||
for _, f := range pkg.Syntax {
|
||||
// Update renamed identifiers.
|
||||
for id, obj := range pkg.TypesInfo.Defs {
|
||||
if objsToUpdate[obj] {
|
||||
id.Name = prefix + obj.Name()
|
||||
}
|
||||
}
|
||||
for id, obj := range pkg.TypesInfo.Uses {
|
||||
if objsToUpdate[obj] {
|
||||
id.Name = prefix + obj.Name()
|
||||
}
|
||||
}
|
||||
|
||||
// For each qualified identifier that refers to the
|
||||
// destination package, remove the qualifier.
|
||||
// The "@@@." strings are removed in postprocessing.
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
if sel, ok := n.(*ast.SelectorExpr); ok {
|
||||
if id, ok := sel.X.(*ast.Ident); ok {
|
||||
if obj, ok := pkg.TypesInfo.Uses[id].(*types.PkgName); ok {
|
||||
if obj.Imported().Path() == dst {
|
||||
id.Name = "@@@"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
last := f.Package
|
||||
if len(f.Imports) > 0 {
|
||||
imp := f.Imports[len(f.Imports)-1]
|
||||
last = imp.End()
|
||||
if imp.Comment != nil {
|
||||
if e := imp.Comment.End(); e > last {
|
||||
last = e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pretty-print package-level declarations.
|
||||
// but no package or import declarations.
|
||||
var buf bytes.Buffer
|
||||
for _, decl := range f.Decls {
|
||||
if decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT {
|
||||
continue
|
||||
}
|
||||
|
||||
beg, end := sourceRange(decl)
|
||||
|
||||
printComments(&out, f.Comments, last, beg)
|
||||
|
||||
buf.Reset()
|
||||
format.Node(&buf, pkg.Fset, &printer.CommentedNode{Node: decl, Comments: f.Comments})
|
||||
// Remove each "@@@." in the output.
|
||||
// TODO(adonovan): not hygienic.
|
||||
out.Write(bytes.Replace(buf.Bytes(), []byte("@@@."), nil, -1))
|
||||
|
||||
last = printSameLineComment(&out, f.Comments, pkg.Fset, end)
|
||||
|
||||
out.WriteString("\n\n")
|
||||
}
|
||||
|
||||
printLastComments(&out, f.Comments, last)
|
||||
}
|
||||
|
||||
// Now format the entire thing.
|
||||
result, err := format.Source(out.Bytes())
|
||||
if err != nil {
|
||||
log.Fatalf("formatting failed: %v", err)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// sourceRange returns the [beg, end) interval of source code
|
||||
// belonging to decl (incl. associated comments).
|
||||
func sourceRange(decl ast.Decl) (beg, end token.Pos) {
|
||||
beg = decl.Pos()
|
||||
end = decl.End()
|
||||
|
||||
var doc, com *ast.CommentGroup
|
||||
|
||||
switch d := decl.(type) {
|
||||
case *ast.GenDecl:
|
||||
doc = d.Doc
|
||||
if len(d.Specs) > 0 {
|
||||
switch spec := d.Specs[len(d.Specs)-1].(type) {
|
||||
case *ast.ValueSpec:
|
||||
com = spec.Comment
|
||||
case *ast.TypeSpec:
|
||||
com = spec.Comment
|
||||
}
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
doc = d.Doc
|
||||
}
|
||||
|
||||
if doc != nil {
|
||||
beg = doc.Pos()
|
||||
}
|
||||
if com != nil && com.End() > end {
|
||||
end = com.End()
|
||||
}
|
||||
|
||||
return beg, end
|
||||
}
|
||||
|
||||
func printComments(out *bytes.Buffer, comments []*ast.CommentGroup, pos, end token.Pos) {
|
||||
for _, cg := range comments {
|
||||
if pos <= cg.Pos() && cg.Pos() < end {
|
||||
for _, c := range cg.List {
|
||||
fmt.Fprintln(out, c.Text)
|
||||
}
|
||||
fmt.Fprintln(out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const infinity = 1 << 30
|
||||
|
||||
func printLastComments(out *bytes.Buffer, comments []*ast.CommentGroup, pos token.Pos) {
|
||||
printComments(out, comments, pos, infinity)
|
||||
}
|
||||
|
||||
func printSameLineComment(out *bytes.Buffer, comments []*ast.CommentGroup, fset *token.FileSet, pos token.Pos) token.Pos {
|
||||
tf := fset.File(pos)
|
||||
for _, cg := range comments {
|
||||
if pos <= cg.Pos() && tf.Line(cg.Pos()) == tf.Line(pos) {
|
||||
for _, c := range cg.List {
|
||||
fmt.Fprintln(out, c.Text)
|
||||
}
|
||||
return cg.End()
|
||||
}
|
||||
}
|
||||
return pos
|
||||
}
|
||||
|
||||
func quoteArgs(ss []string) []string {
|
||||
// From go help generate:
|
||||
//
|
||||
// > The arguments to the directive are space-separated tokens or
|
||||
// > double-quoted strings passed to the generator as individual
|
||||
// > arguments when it is run.
|
||||
//
|
||||
// > Quoted strings use Go syntax and are evaluated before execution; a
|
||||
// > quoted string appears as a single argument to the generator.
|
||||
//
|
||||
var qs []string
|
||||
for _, s := range ss {
|
||||
if s == "" || containsSpace(s) {
|
||||
s = strconv.Quote(s)
|
||||
}
|
||||
qs = append(qs, s)
|
||||
}
|
||||
return qs
|
||||
}
|
||||
|
||||
func containsSpace(s string) bool {
|
||||
for _, r := range s {
|
||||
if unicode.IsSpace(r) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type flagFunc func(string)
|
||||
|
||||
func (f flagFunc) Set(s string) error {
|
||||
f(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f flagFunc) String() string { return "" }
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/packages/packagestest"
|
||||
)
|
||||
|
||||
func TestBundle(t *testing.T) { packagestest.TestAll(t, testBundle) }
|
||||
func testBundle(t *testing.T, x packagestest.Exporter) {
|
||||
load := func(name string) string {
|
||||
data, err := os.ReadFile(name)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
e := packagestest.Export(t, x, []packagestest.Module{
|
||||
{
|
||||
Name: "initial",
|
||||
Files: map[string]interface{}{
|
||||
"a.go": load("testdata/src/initial/a.go"),
|
||||
"b.go": load("testdata/src/initial/b.go"),
|
||||
"c.go": load("testdata/src/initial/c.go"),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "domain.name/importdecl",
|
||||
Files: map[string]interface{}{
|
||||
"p.go": load("testdata/src/domain.name/importdecl/p.go"),
|
||||
},
|
||||
},
|
||||
})
|
||||
defer e.Cleanup()
|
||||
testingOnlyPackagesConfig = e.Config
|
||||
|
||||
os.Args = os.Args[:1] // avoid e.g. -test=short in the output
|
||||
out, err := bundle("initial", "github.com/dest", "dest", "prefix", "tag")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if got, want := string(out), load("testdata/out.golden"); got != want {
|
||||
t.Errorf("-- got --\n%s\n-- want --\n%s\n-- diff --", got, want)
|
||||
|
||||
if err := os.WriteFile("testdata/out.got", out, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Log(diff("testdata/out.golden", "testdata/out.got"))
|
||||
}
|
||||
}
|
||||
|
||||
func diff(a, b string) string {
|
||||
var cmd *exec.Cmd
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
cmd = exec.Command("/bin/diff", "-c", a, b)
|
||||
default:
|
||||
cmd = exec.Command("/usr/bin/diff", "-u", a, b)
|
||||
}
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
cmd.Stderr = &out
|
||||
cmd.Run() // nonzero exit is expected
|
||||
if out.Len() == 0 {
|
||||
return "(failed to compute diff)"
|
||||
}
|
||||
return out.String()
|
||||
}
|
||||
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
//go:build tag
|
||||
|
||||
// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
|
||||
// $ bundle
|
||||
|
||||
// The package doc comment
|
||||
//
|
||||
|
||||
package dest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
. "fmt"
|
||||
_ "fmt"
|
||||
renamedfmt "fmt"
|
||||
renamedfmt2 "fmt"
|
||||
|
||||
"domain.name/importdecl"
|
||||
)
|
||||
|
||||
// init functions are not renamed
|
||||
func init() { prefixfoo() }
|
||||
|
||||
// Type S.
|
||||
type prefixS struct {
|
||||
prefixt
|
||||
u int
|
||||
} /* multi-line
|
||||
comment
|
||||
*/
|
||||
|
||||
// non-associated comment
|
||||
|
||||
/*
|
||||
non-associated comment2
|
||||
*/
|
||||
|
||||
// Function bar.
|
||||
func prefixbar(s *prefixS) {
|
||||
fmt.Println(s.prefixt, s.u) // comment inside function
|
||||
}
|
||||
|
||||
// file-end comment
|
||||
|
||||
type prefixt int // type1
|
||||
|
||||
// const1
|
||||
const prefixc = 1 // const2
|
||||
|
||||
func prefixfoo() {
|
||||
fmt.Println(importdecl.F())
|
||||
}
|
||||
|
||||
// zinit
|
||||
const (
|
||||
prefixz1 = iota // z1
|
||||
prefixz2 // z2
|
||||
) // zend
|
||||
|
||||
func prefixbaz() {
|
||||
renamedfmt.Println()
|
||||
renamedfmt2.Println()
|
||||
Println()
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package importdecl
|
||||
|
||||
func F() int { return 1 }
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package initial
|
||||
|
||||
import "fmt" // this comment should not be visible
|
||||
|
||||
// init functions are not renamed
|
||||
func init() { foo() }
|
||||
|
||||
// Type S.
|
||||
type S struct {
|
||||
t
|
||||
u int
|
||||
} /* multi-line
|
||||
comment
|
||||
*/
|
||||
|
||||
// non-associated comment
|
||||
|
||||
/*
|
||||
non-associated comment2
|
||||
*/
|
||||
|
||||
// Function bar.
|
||||
func bar(s *S) {
|
||||
fmt.Println(s.t, s.u) // comment inside function
|
||||
}
|
||||
|
||||
// file-end comment
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// The package doc comment
|
||||
package initial
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"domain.name/importdecl"
|
||||
)
|
||||
|
||||
type t int // type1
|
||||
|
||||
// const1
|
||||
const c = 1 // const2
|
||||
|
||||
func foo() {
|
||||
fmt.Println(importdecl.F())
|
||||
}
|
||||
|
||||
// zinit
|
||||
const (
|
||||
z1 = iota // z1
|
||||
z2 // z2
|
||||
) // zend
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package initial
|
||||
|
||||
import _ "fmt"
|
||||
import renamedfmt "fmt"
|
||||
import renamedfmt2 "fmt"
|
||||
import . "fmt"
|
||||
|
||||
func baz() {
|
||||
renamedfmt.Println()
|
||||
renamedfmt2.Println()
|
||||
Println()
|
||||
}
|
||||
Reference in New Issue
Block a user