Releases: gostaticanalysis/skeleton
Releases · gostaticanalysis/skeleton
v2.3.0
v2.2.3
What's Changed
- fix -checker option description in README_ja.md by @ikura-hamu in #68
- Fix test and vet workflow by @tenntenn in #69
- Add tagpr by @tenntenn in #74
- Move .tagpr by @tenntenn in #76
- Fix go version logic by @tenntenn in #77
New Contributors
- @ikura-hamu made their first contribution in #68
Full Changelog: v2.2.2...v2.2.3
v2.2.2: Fix -gomod flag bug
- Fix
-gomod
flag bug (#64)
v2.2.1: Fix -gomod flag bug and improvement README
- Improvement README
- Go1.18 support
- Fix a bug of
-gomod
flag
v2.2.0: Add gomod flag
- Add
gomod
flag
v2.1.2: Fix main.go of packages kind tempalte
- Fix main.go of packages kind tempalte
v2.1.1: Fix template for packages kind
- Fix template for
packages
kind - Add tests which execute
go test
in generated directories
v2.1.0: Add kind packages
Add packages
kind
If you give packages
to kind option, skeleton generates golang.org/x/tools/go/packages package based source codes.
$ skeleton -kind packages example
$ tree example
example
├── cmd
│ └── example
│ └── main.go
├── example.go
├── example_test.go
├── go.mod
└── testdata
├── a-stderr.golden
├── a-stdout.golden
└── src
└── a
├── a.go
└── go.mod
The generated codes consist of main.go, analyzer-like analyzing code and a test code which check by golden file testing.
example/example.go
package example
import (
"flag"
"fmt"
"go/ast"
"io"
"path/filepath"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/go/packages"
)
type Pass struct {
Pkg *packages.Package
Stdin io.Reader
Stdout io.Writer
Stderr io.Writer
}
var Analyzer = struct {
Name string
Doc string
Flags *flag.FlagSet
Config *packages.Config
Run func(pass *Pass) error
}{
Name: "example",
Doc: "example is ...",
Config: &packages.Config{
Mode: packages.NeedName | packages.NeedTypes |
packages.NeedSyntax | packages.NeedTypesInfo |
packages.NeedModule,
},
Run: run,
}
func run(pass *Pass) error {
inspect := inspector.New(pass.Pkg.Syntax)
nodeFilter := []ast.Node{
(*ast.Ident)(nil),
}
inspect.Preorder(nodeFilter, func(n ast.Node) {
switch n := n.(type) {
case *ast.Ident:
if n.Name == "gopher" {
pos := pass.Pkg.Fset.Position(n.Pos())
fname, err := filepath.Rel(pass.Pkg.Module.Dir, pos.Filename)
if err != nil {
return
}
fmt.Fprintf(pass.Stdout, "%s:%d:%d identifier is gopher\n", fname, pos.Line, pos.Column)
}
}
})
return nil
}
example/example_test.go
package example_test
import (
"bytes"
"flag"
"path/filepath"
"strings"
"testing"
"example"
"github.com/tenntenn/golden"
"golang.org/x/tools/go/packages"
)
var (
flagUpdate bool
)
func init() {
flag.BoolVar(&flagUpdate, "update", false, "update golden files")
}
func Test(t *testing.T) {
pkgs := load(t, testdata(t), "a")
for _, pkg := range pkgs {
run(t, pkg)
}
}
func load(t *testing.T, testdata string, pkgname string) []*packages.Package {
t.Helper()
example.Analyzer.Config.Dir = filepath.Join(testdata, "src", pkgname)
pkgs, err := packages.Load(example.Analyzer.Config, pkgname)
if err != nil {
t.Fatal("unexpected error:", err)
}
return pkgs
}
func testdata(t *testing.T) string {
t.Helper()
dir, err := filepath.Abs("testdata")
if err != nil {
t.Fatal("unexpected error:", err)
}
return dir
}
func run(t *testing.T, pkg *packages.Package) {
var stdin, stdout, stderr bytes.Buffer
pass := &example.Pass{
Stdin: &stdin,
Stdout: &stdout,
Stderr: &stderr,
Pkg: pkg,
}
if err := example.Analyzer.Run(pass); err != nil {
t.Error("unexpected error:", err)
}
pkgname := pkgname(pkg)
if flagUpdate {
golden.Update(t, testdata(t), pkgname+"-stdout", &stdout)
golden.Update(t, testdata(t), pkgname+"-stderr", &stderr)
return
}
if diff := golden.Diff(t, testdata(t), pkgname+"-stdout", &stdout); diff != "" {
t.Errorf("stdout of analyzing %s:\n%s", pkgname, diff)
}
if diff := golden.Diff(t, testdata(t), pkgname+"-stderr", &stderr); diff != "" {
t.Errorf("stderr of analyzing %s:\n%s", pkgname, diff)
}
}
func pkgname(pkg *packages.Package) string {
switch {
case pkg.PkgPath != "":
return strings.ReplaceAll(pkg.PkgPath, "/", "-")
case pkg.Name != "":
return pkg.Name
default:
return pkg.ID
}
}
v2.0.5: Refactoring
- Use gostaticanalysis/skeletonkit and tenntenn/golden internally
- Add usage of
SKELETON_PREFIX
environment variable
v2.0.4: Trim spaces from version
- Trim spaces from version