cmd/stringer: revert back to source importer
Roll back my two recent changes. Stringer is now very slow again, but works in most use cases. My git foo is insufficient to do this as a revert, but it is a by-hand reversion of CLs https://go-review.googlesource.com/121884 https://go-review.googlesource.com/121995 See the issue for a long conversation about the general problem. Update golang/go#10249 Update golang/go#25650 Change-Id: I7b6ce352a4c7ebf0977883509e9d7189aaac1251 Reviewed-on: https://go-review.googlesource.com/122535 Run-TryBot: Rob Pike <r@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
435878328f
commit
827133af57
|
@ -9,7 +9,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
|
@ -27,8 +26,17 @@ import (
|
|||
// binary panics if the String method for X is not correct, including for error cases.
|
||||
|
||||
func TestEndToEnd(t *testing.T) {
|
||||
dir, stringer := buildStringer(t)
|
||||
dir, err := ioutil.TempDir("", "stringer")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
// Create stringer in temporary directory.
|
||||
stringer := filepath.Join(dir, "stringer.exe")
|
||||
err = run("go", "build", "-o", stringer)
|
||||
if err != nil {
|
||||
t.Fatalf("building stringer: %s", err)
|
||||
}
|
||||
// Read the testdata directory.
|
||||
fd, err := os.Open("testdata")
|
||||
if err != nil {
|
||||
|
@ -45,10 +53,6 @@ func TestEndToEnd(t *testing.T) {
|
|||
t.Errorf("%s is not a Go file", name)
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(name, "tag_") {
|
||||
// This file is used for tag processing in TestTags, below.
|
||||
continue
|
||||
}
|
||||
if name == "cgo.go" && !build.Default.CgoEnabled {
|
||||
t.Logf("cgo is not enabled for %s", name)
|
||||
continue
|
||||
|
@ -59,69 +63,9 @@ func TestEndToEnd(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestTags verifies that the -tags flag works as advertised.
|
||||
func TestTags(t *testing.T) {
|
||||
dir, stringer := buildStringer(t)
|
||||
defer os.RemoveAll(dir)
|
||||
var (
|
||||
protectedConst = []byte("TagProtected")
|
||||
output = filepath.Join(dir, "const_string.go")
|
||||
)
|
||||
for _, file := range []string{"tag_main.go", "tag_tag.go"} {
|
||||
|
||||
err := copy(filepath.Join(dir, file), filepath.Join("testdata", file))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
err := run(stringer, "-type", "Const", dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err := ioutil.ReadFile(output)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if bytes.Contains(result, protectedConst) {
|
||||
t.Fatal("tagged variable appears in untagged run")
|
||||
}
|
||||
err = os.Remove(output)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = run(stringer, "-type", "Const", "-tags", "tag", dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result, err = ioutil.ReadFile(output)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Contains(result, protectedConst) {
|
||||
t.Fatal("tagged variable does not appear in tagged run")
|
||||
}
|
||||
}
|
||||
|
||||
// buildStringer creates a temporary directory and installs stringer there.
|
||||
func buildStringer(t *testing.T) (dir string, stringer string) {
|
||||
t.Helper()
|
||||
dir, err := ioutil.TempDir("", "stringer")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
stringer = filepath.Join(dir, "stringer.exe")
|
||||
err = run("go", "build", "-o", stringer, "stringer.go")
|
||||
if err != nil {
|
||||
t.Fatalf("building stringer: %s", err)
|
||||
}
|
||||
return dir, stringer
|
||||
}
|
||||
|
||||
// stringerCompileAndRun runs stringer for the named file and compiles and
|
||||
// runs the target binary in directory dir. That binary will panic if the String method is incorrect.
|
||||
func stringerCompileAndRun(t *testing.T, dir, stringer, typeName, fileName string) {
|
||||
t.Helper()
|
||||
t.Logf("run: %s %s\n", fileName, typeName)
|
||||
source := filepath.Join(dir, fileName)
|
||||
err := copy(source, filepath.Join("testdata", fileName))
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
// +build !go1.9
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/importer"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func defaultImporter() types.Importer {
|
||||
return importer.Default()
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
// +build go1.9
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/importer"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func defaultImporter() types.Importer {
|
||||
return importer.For("source", nil)
|
||||
}
|
|
@ -66,7 +66,6 @@ import (
|
|||
"go/build"
|
||||
exact "go/constant"
|
||||
"go/format"
|
||||
"go/importer"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
|
@ -83,7 +82,6 @@ var (
|
|||
output = flag.String("output", "", "output file name; default srcdir/<type>_string.go")
|
||||
trimprefix = flag.String("trimprefix", "", "trim the `prefix` from the generated constant names")
|
||||
linecomment = flag.Bool("linecomment", false, "use line comment text as printed text when present")
|
||||
buildTags = flag.String("tags", "", "comma-separated list of build tags to apply")
|
||||
)
|
||||
|
||||
// Usage is a replacement usage function for the flags package.
|
||||
|
@ -107,10 +105,6 @@ func main() {
|
|||
os.Exit(2)
|
||||
}
|
||||
types := strings.Split(*typeNames, ",")
|
||||
var tags []string
|
||||
if len(*buildTags) > 0 {
|
||||
tags = strings.Split(*buildTags, ",")
|
||||
}
|
||||
|
||||
// We accept either one directory or a list of files. Which do we have?
|
||||
args := flag.Args()
|
||||
|
@ -127,11 +121,8 @@ func main() {
|
|||
}
|
||||
if len(args) == 1 && isDirectory(args[0]) {
|
||||
dir = args[0]
|
||||
g.parsePackageDir(args[0], tags)
|
||||
g.parsePackageDir(args[0])
|
||||
} else {
|
||||
if len(tags) != 0 {
|
||||
log.Fatal("-tags option applies only to directories, not when files are specified")
|
||||
}
|
||||
dir = filepath.Dir(args[0])
|
||||
g.parsePackageFiles(args)
|
||||
}
|
||||
|
@ -206,15 +197,9 @@ type Package struct {
|
|||
typesPkg *types.Package
|
||||
}
|
||||
|
||||
func buildContext(tags []string) *build.Context {
|
||||
ctx := build.Default
|
||||
ctx.BuildTags = tags
|
||||
return &ctx
|
||||
}
|
||||
|
||||
// parsePackageDir parses the package residing in the directory.
|
||||
func (g *Generator) parsePackageDir(directory string, tags []string) {
|
||||
pkg, err := buildContext(tags).ImportDir(directory, 0)
|
||||
func (g *Generator) parsePackageDir(directory string) {
|
||||
pkg, err := build.Default.ImportDir(directory, 0)
|
||||
if err != nil {
|
||||
log.Fatalf("cannot process directory %s: %s", directory, err)
|
||||
}
|
||||
|
@ -276,17 +261,14 @@ func (g *Generator) parsePackage(directory string, names []string, text interfac
|
|||
g.pkg.name = astFiles[0].Name.Name
|
||||
g.pkg.files = files
|
||||
g.pkg.dir = directory
|
||||
g.pkg.typeCheck(fs, astFiles)
|
||||
// Type check the package.
|
||||
g.pkg.check(fs, astFiles)
|
||||
}
|
||||
|
||||
// check type-checks the package so we can evaluate contants whose values we are printing.
|
||||
func (pkg *Package) typeCheck(fs *token.FileSet, astFiles []*ast.File) {
|
||||
// check type-checks the package. The package must be OK to proceed.
|
||||
func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) {
|
||||
pkg.defs = make(map[*ast.Ident]types.Object)
|
||||
config := types.Config{
|
||||
IgnoreFuncBodies: true, // We only need to evaluate constants.
|
||||
Importer: importer.Default(),
|
||||
FakeImportC: true,
|
||||
}
|
||||
config := types.Config{Importer: defaultImporter(), FakeImportC: true}
|
||||
info := &types.Info{
|
||||
Defs: pkg.defs,
|
||||
}
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
// No build tag in this file.
|
||||
|
||||
package main
|
||||
|
||||
type Const int
|
||||
|
||||
const (
|
||||
A Const = iota
|
||||
B
|
||||
C
|
||||
)
|
|
@ -1,7 +0,0 @@
|
|||
// This file has a build tag "tag"
|
||||
|
||||
// +build tag
|
||||
|
||||
package main
|
||||
|
||||
const TagProtected Const = C + 1
|
Loading…
Reference in New Issue