mirror of https://github.com/dmarkham/enumer.git
Add support for go modules
This commit is contained in:
parent
7820f3770a
commit
0f1dc27ec9
|
@ -111,7 +111,14 @@ func copy(to, from string) error {
|
||||||
// run runs a single command and returns an error if it does not succeed.
|
// run runs a single command and returns an error if it does not succeed.
|
||||||
// os/exec should have this function, to be honest.
|
// os/exec should have this function, to be honest.
|
||||||
func run(name string, arg ...string) error {
|
func run(name string, arg ...string) error {
|
||||||
|
return runInDir(".", name, arg...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// runInDir runs a single command in directory dir and returns an error if
|
||||||
|
// it does not succeed.
|
||||||
|
func runInDir(dir, name string, arg ...string) error {
|
||||||
cmd := exec.Command(name, arg...)
|
cmd := exec.Command(name, arg...)
|
||||||
|
cmd.Dir = dir
|
||||||
cmd.Stdout = os.Stdout
|
cmd.Stdout = os.Stdout
|
||||||
cmd.Stderr = os.Stderr
|
cmd.Stderr = os.Stderr
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
|
|
5
go.mod
5
go.mod
|
@ -2,4 +2,7 @@ module github.com/alvaroloes/enumer
|
||||||
|
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1
|
require (
|
||||||
|
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1
|
||||||
|
golang.org/x/tools v0.0.0-20190524210228-3d17549cdc6b
|
||||||
|
)
|
||||||
|
|
7
go.sum
7
go.sum
|
@ -1,2 +1,9 @@
|
||||||
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1 h1:/I3lTljEEDNYLho3/FUB7iD/oc2cEFgVmbHzV+O0PtU=
|
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1 h1:/I3lTljEEDNYLho3/FUB7iD/oc2cEFgVmbHzV+O0PtU=
|
||||||
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1/go.mod h1:eD5JxqMiuNYyFNmyY9rkJ/slN8y59oEu4Ei7F8OoKWQ=
|
github.com/pascaldekloe/name v0.0.0-20180628100202-0fd16699aae1/go.mod h1:eD5JxqMiuNYyFNmyY9rkJ/slN8y59oEu4Ei7F8OoKWQ=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190524210228-3d17549cdc6b h1:iEAPfYPbYbxG/2lNN4cMOHkmgKNsCuUwkxlDCK46UlU=
|
||||||
|
golang.org/x/tools v0.0.0-20190524210228-3d17549cdc6b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
|
|
|
@ -10,6 +10,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -1050,7 +1053,24 @@ func runGoldenTest(t *testing.T, test Golden, generateJSON, generateYAML, genera
|
||||||
var g Generator
|
var g Generator
|
||||||
input := "package test\n" + test.input
|
input := "package test\n" + test.input
|
||||||
file := test.name + ".go"
|
file := test.name + ".go"
|
||||||
g.parsePackage(".", []string{file}, input)
|
|
||||||
|
dir, err := ioutil.TempDir("", "stringer")
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
err = os.RemoveAll(dir)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
absFile := filepath.Join(dir, file)
|
||||||
|
err = ioutil.WriteFile(absFile, []byte(input), 0644)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
g.parsePackage([]string{absFile})
|
||||||
// Extract the name and type of the constant from the first line.
|
// Extract the name and type of the constant from the first line.
|
||||||
tokens := strings.SplitN(test.input, " ", 3)
|
tokens := strings.SplitN(test.input, " ", 3)
|
||||||
if len(tokens) != 3 {
|
if len(tokens) != 3 {
|
||||||
|
|
154
stringer.go
154
stringer.go
|
@ -15,13 +15,12 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/build"
|
|
||||||
exact "go/constant"
|
exact "go/constant"
|
||||||
"go/format"
|
"go/format"
|
||||||
"go/importer"
|
"go/importer"
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"golang.org/x/tools/go/packages"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
@ -97,12 +96,12 @@ func main() {
|
||||||
|
|
||||||
if len(args) == 1 && isDirectory(args[0]) {
|
if len(args) == 1 && isDirectory(args[0]) {
|
||||||
dir = args[0]
|
dir = args[0]
|
||||||
g.parsePackageDir(args[0])
|
|
||||||
} else {
|
} else {
|
||||||
dir = filepath.Dir(args[0])
|
dir = filepath.Dir(args[0])
|
||||||
g.parsePackageFiles(args)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g.parsePackage(args)
|
||||||
|
|
||||||
// Print the header and package clause.
|
// Print the header and package clause.
|
||||||
g.Printf("// Code generated by \"enumer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
|
g.Printf("// Code generated by \"enumer %s\"; DO NOT EDIT.\n", strings.Join(os.Args[1:], " "))
|
||||||
g.Printf("\n")
|
g.Printf("\n")
|
||||||
|
@ -194,70 +193,105 @@ type Package struct {
|
||||||
typesPkg *types.Package
|
typesPkg *types.Package
|
||||||
}
|
}
|
||||||
|
|
||||||
// parsePackageDir parses the package residing in the directory.
|
//// parsePackageDir parses the package residing in the directory.
|
||||||
func (g *Generator) parsePackageDir(directory string) {
|
//func (g *Generator) parsePackageDir(directory string) {
|
||||||
pkg, err := build.Default.ImportDir(directory, 0)
|
// pkg, err := build.Default.ImportDir(directory, 0)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
log.Fatalf("cannot process directory %s: %s", directory, err)
|
// log.Fatalf("cannot process directory %s: %s", directory, err)
|
||||||
}
|
// }
|
||||||
var names []string
|
// var names []string
|
||||||
names = append(names, pkg.GoFiles...)
|
// names = append(names, pkg.GoFiles...)
|
||||||
names = append(names, pkg.CgoFiles...)
|
// names = append(names, pkg.CgoFiles...)
|
||||||
|
// // TODO: Need to think about constants in test files. Maybe write type_string_test.go
|
||||||
|
// // in a separate pass? For later.
|
||||||
|
// // names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
|
||||||
|
// names = append(names, pkg.SFiles...)
|
||||||
|
// names = prefixDirectory(directory, names)
|
||||||
|
// g.parsePackage(directory, names, nil)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//// parsePackageFiles parses the package occupying the named files.
|
||||||
|
//func (g *Generator) parsePackageFiles(names []string) {
|
||||||
|
// g.parsePackage(".", names, nil)
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//// prefixDirectory places the directory name on the beginning of each name in the list.
|
||||||
|
//func prefixDirectory(directory string, names []string) []string {
|
||||||
|
// if directory == "." {
|
||||||
|
// return names
|
||||||
|
// }
|
||||||
|
// ret := make([]string, len(names))
|
||||||
|
// for i, name := range names {
|
||||||
|
// ret[i] = filepath.Join(directory, name)
|
||||||
|
// }
|
||||||
|
// return ret
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// parsePackage analyzes the single package constructed from the named files.
|
||||||
|
//// If text is non-nil, it is a string to be used instead of the content of the file,
|
||||||
|
//// to be used for testing. parsePackage exits if there is an error.
|
||||||
|
//func (g *Generator) parsePackage(directory string, names []string, text interface{}) {
|
||||||
|
// var files []*File
|
||||||
|
// var astFiles []*ast.File
|
||||||
|
// g.pkg = new(Package)
|
||||||
|
// fs := token.NewFileSet()
|
||||||
|
// for _, name := range names {
|
||||||
|
// if !strings.HasSuffix(name, ".go") {
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// parsedFile, err := parser.ParseFile(fs, name, text, 0)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Fatalf("parsing package: %s: %s", name, err)
|
||||||
|
// }
|
||||||
|
// astFiles = append(astFiles, parsedFile)
|
||||||
|
// files = append(files, &File{
|
||||||
|
// file: parsedFile,
|
||||||
|
// pkg: g.pkg,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// if len(astFiles) == 0 {
|
||||||
|
// log.Fatalf("%s: no buildable Go files", directory)
|
||||||
|
// }
|
||||||
|
// g.pkg.name = astFiles[0].Name.Name
|
||||||
|
// g.pkg.files = files
|
||||||
|
// g.pkg.dir = directory
|
||||||
|
// // Type check the package.
|
||||||
|
// g.pkg.check(fs, astFiles)
|
||||||
|
//}
|
||||||
|
|
||||||
|
// parsePackage analyzes the single package constructed from the patterns and tags.
|
||||||
|
// parsePackage exits if there is an error.
|
||||||
|
func (g *Generator) parsePackage(patterns []string) {
|
||||||
|
cfg := &packages.Config{
|
||||||
|
Mode: packages.LoadSyntax,
|
||||||
// TODO: Need to think about constants in test files. Maybe write type_string_test.go
|
// TODO: Need to think about constants in test files. Maybe write type_string_test.go
|
||||||
// in a separate pass? For later.
|
// in a separate pass? For later.
|
||||||
// names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
|
Tests: false,
|
||||||
names = append(names, pkg.SFiles...)
|
|
||||||
names = prefixDirectory(directory, names)
|
|
||||||
g.parsePackage(directory, names, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parsePackageFiles parses the package occupying the named files.
|
|
||||||
func (g *Generator) parsePackageFiles(names []string) {
|
|
||||||
g.parsePackage(".", names, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefixDirectory places the directory name on the beginning of each name in the list.
|
|
||||||
func prefixDirectory(directory string, names []string) []string {
|
|
||||||
if directory == "." {
|
|
||||||
return names
|
|
||||||
}
|
}
|
||||||
ret := make([]string, len(names))
|
pkgs, err := packages.Load(cfg, patterns...)
|
||||||
for i, name := range names {
|
|
||||||
ret[i] = filepath.Join(directory, name)
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// parsePackage analyzes the single package constructed from the named files.
|
|
||||||
// If text is non-nil, it is a string to be used instead of the content of the file,
|
|
||||||
// to be used for testing. parsePackage exits if there is an error.
|
|
||||||
func (g *Generator) parsePackage(directory string, names []string, text interface{}) {
|
|
||||||
var files []*File
|
|
||||||
var astFiles []*ast.File
|
|
||||||
g.pkg = new(Package)
|
|
||||||
fs := token.NewFileSet()
|
|
||||||
for _, name := range names {
|
|
||||||
if !strings.HasSuffix(name, ".go") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
parsedFile, err := parser.ParseFile(fs, name, text, 0)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("parsing package: %s: %s", name, err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
astFiles = append(astFiles, parsedFile)
|
if len(pkgs) != 1 {
|
||||||
files = append(files, &File{
|
log.Fatalf("error: %d packages found", len(pkgs))
|
||||||
file: parsedFile,
|
}
|
||||||
|
g.addPackage(pkgs[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// addPackage adds a type checked Package and its syntax files to the generator.
|
||||||
|
func (g *Generator) addPackage(pkg *packages.Package) {
|
||||||
|
g.pkg = &Package{
|
||||||
|
name: pkg.Name,
|
||||||
|
defs: pkg.TypesInfo.Defs,
|
||||||
|
files: make([]*File, len(pkg.Syntax)),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, file := range pkg.Syntax {
|
||||||
|
g.pkg.files[i] = &File{
|
||||||
|
file: file,
|
||||||
pkg: g.pkg,
|
pkg: g.pkg,
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if len(astFiles) == 0 {
|
|
||||||
log.Fatalf("%s: no buildable Go files", directory)
|
|
||||||
}
|
}
|
||||||
g.pkg.name = astFiles[0].Name.Name
|
|
||||||
g.pkg.files = files
|
|
||||||
g.pkg.dir = directory
|
|
||||||
// Type check the package.
|
|
||||||
g.pkg.check(fs, astFiles)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check type-checks the package. The package must be OK to proceed.
|
// check type-checks the package. The package must be OK to proceed.
|
||||||
|
|
Loading…
Reference in New Issue