go.tools/cmd/vet: update to new go/types package

Now that it's in the same repository as the go/types package we can delete
the mechanism to build it without type checking.

Add a make rule to install it where the go tool can find it.
Why doesn't "go install" take a -o flag?

R=gri
CC=gobot, golang-dev
https://golang.org/cl/9526043
This commit is contained in:
Rob Pike 2013-05-20 12:20:05 -07:00
parent 113d6d30b1
commit 08cc526448
4 changed files with 32 additions and 91 deletions

View File

@ -4,11 +4,11 @@
# Assumes go/types is installed
test testshort:
go build -tags 'vet_test gotypes'
go build
$(GOROOT)/test/errchk ./vet -printfuncs='Warn:1,Warnf:1' test_*.go test_*.s
test_notypes:
go build -tags 'vet_test'
# Only those tests that do not depend on types.
# Excluded: test_print.go
$(GOROOT)/test/errchk ./vet -printfuncs='Warn:1,Warnf:1' test_asm.go test_assign.go test_atomic.go test_buildtag.go test_buildtag_bad.go test_deadcode.go test_method.go test_rangeloop.go test_structtag.go test_taglit.go test_*.s
# Install command where the go tool can find it.
install:
go build -o _vet
cp _vet $(GOROOT)/pkg/tool/$(GOOS)_$(GOARCH)/vet
rm -f _vet

View File

@ -20,6 +20,9 @@ import (
"path/filepath"
"strconv"
"strings"
"code.google.com/p/go.tools/go/exact"
"code.google.com/p/go.tools/go/types"
)
var verbose = flag.Bool("v", false, "verbose")
@ -41,6 +44,8 @@ var report = map[string]*bool{
"unreachable": flag.Bool("unreachable", false, "check for unreachable code"),
}
// TODO: Need a flag to set build tags when parsing the package.
// vet tells whether to report errors for the named check, a flag name.
func vet(name string) bool {
return *report["all"] || *report[name]
@ -136,7 +141,7 @@ func main() {
}
return
}
doPackage(flag.Args())
doPackage(".", flag.Args())
os.Exit(exitCode)
}
@ -168,23 +173,24 @@ func doPackageDir(directory string) {
names = append(names, pkg.TestGoFiles...) // These are also in the "foo" package.
names = append(names, pkg.SFiles...)
prefixDirectory(directory, names)
doPackage(names)
doPackage(directory, names)
// Is there also a "foo_test" package? If so, do that one as well.
if len(pkg.XTestGoFiles) > 0 {
names = pkg.XTestGoFiles
prefixDirectory(directory, names)
doPackage(names)
doPackage(directory, names)
}
}
type Package struct {
types map[ast.Expr]Type
values map[ast.Expr]ExactValue
path string
types map[ast.Expr]types.Type
values map[ast.Expr]exact.Value
files []*File
}
// doPackage analyzes the single package constructed from the named files.
func doPackage(names []string) {
func doPackage(directory string, names []string) {
var files []*File
var astFiles []*ast.File
fs := token.NewFileSet()
@ -214,6 +220,7 @@ func doPackage(names []string) {
files = append(files, &File{fset: fs, content: data, name: name, file: parsedFile})
}
pkg := new(Package)
pkg.path = directory
pkg.files = files
// Type check the package.
err := pkg.check(fs, astFiles)

View File

@ -2,11 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build gotypes
// This file contains the pieces of the tool that require the go/types package.
// To compile this file, you must first run
// $ go get code.google.com/p/go.tools/go/types
// This file contains the pieces of the tool that use typechecking from the go/types package.
package main
@ -18,22 +14,9 @@ import (
"code.google.com/p/go.tools/go/types"
)
// Type is equivalent to types.Type. Repeating it here allows us to avoid
// having main depend on the go/types package.
type Type interface {
String() string
}
// ExactValue is equivalent to exact.Value. Repeating it here allows us to
// avoid having main depend on the go/exact package.
type ExactValue interface {
Kind() exact.Kind
String() string
}
func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
pkg.types = make(map[ast.Expr]Type)
pkg.values = make(map[ast.Expr]ExactValue)
pkg.types = make(map[ast.Expr]types.Type)
pkg.values = make(map[ast.Expr]exact.Value)
exprFn := func(x ast.Expr, typ types.Type, val exact.Value) {
pkg.types[x] = typ
if val != nil {
@ -46,7 +29,7 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
Expr: exprFn,
Error: func(error) {},
}
_, err := context.Check(fs, astFiles)
_, err := context.Check(pkg.path, fs, astFiles...)
return err
}
@ -55,10 +38,11 @@ func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
// Check that the CompositeLit's type is a slice or array (which needs no tag), if possible.
typ := pkg.types[c]
// If it's a named type, pull out the underlying type.
// If it's a named type, pull out the underlying type. If it's not, the Underlying
// method returns the type itself.
actual := typ
if namedType, ok := typ.(*types.NamedType); ok {
actual = namedType.Underlying
if actual != nil {
actual = actual.Underlying()
}
if actual == nil {
// No type information available. Assume true, so we do the check.
@ -82,7 +66,7 @@ func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
if !ok {
return true
}
switch basic.Kind {
switch basic.Kind() {
case types.Bool:
return t&argBool != 0
case types.Int, types.Int8, types.Int16, types.Int32, types.Int64:
@ -136,7 +120,7 @@ func (f *File) numArgsInSignature(call *ast.CallExpr) int {
if !ok {
return 0
}
return len(sig.Params)
return sig.Params().Len()
}
// isErrorMethodCall reports whether the call is of a method with signature
@ -168,16 +152,16 @@ func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
return false
}
// There must be no arguments. Already verified by type checking, but be thorough.
if len(sig.Params) > 0 {
if sig.Params().Len() > 0 {
return false
}
// Finally the real questions.
// There must be one result.
if len(sig.Results) != 1 {
if sig.Results().Len() != 1 {
return false
}
// It must have return type "string" from the universe.
result := sig.Results[0].Type
result := sig.Results().At(0).Type()
if types.IsIdentical(result, types.Typ[types.String]) {
return true
}

View File

@ -1,50 +0,0 @@
// Copyright 2010 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 !gotypes
// This file contains stubs for the pieces of the tool that require the go/types package,
// to be used if go/types is not available.
package main
import (
"go/ast"
"go/token"
)
// Type is equivalent to go/types.Type. Repeating it here allows us to avoid
// having main depend on the go/types package.
type Type interface {
String() string
}
// ExactValue is a stub for exact.Value. Stubbing it here allows us to
// avoid having main depend on the go/exact package.
type ExactValue interface {
}
func (pkg *Package) check(fs *token.FileSet, astFiles []*ast.File) error {
return nil
}
func (pkg *Package) isStruct(c *ast.CompositeLit) (bool, string) {
return true, "" // Assume true, so we do the check.
}
func (f *File) matchArgType(t printfArgType, arg ast.Expr) bool {
return true // We can't tell without types.
}
func (f *File) numArgsInSignature(call *ast.CallExpr) int {
return 0 // We don't know.
}
func (f *File) isErrorMethodCall(call *ast.CallExpr) bool {
// Is it a selector expression? Otherwise it's a function call, not a method call.
if _, ok := call.Fun.(*ast.SelectorExpr); !ok {
return false
}
return true // Best guess we can make without types.
}