Add deadcode code which recursivley goes into all directories and verifies dangling variables.

This commit is contained in:
Harshavardhana 2015-03-02 18:03:01 -08:00
parent 022b89dd9b
commit c3ad0906e0
12 changed files with 228 additions and 25 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@ cover.out
minio minio
**/*.test **/*.test
**/*.sublime-workspace **/*.sublime-workspace
deadcode

View file

@ -13,7 +13,10 @@ checkgopath:
getdeps: checkdeps checkgopath getdeps: checkdeps checkgopath
@go get github.com/tools/godep && echo "Installed godep" @go get github.com/tools/godep && echo "Installed godep"
build-all: getdeps deadcode: getdeps
@go run buildscripts/deadcode.go .
build-all: getdeps deadcode
@echo "Building Libraries" @echo "Building Libraries"
@godep go generate ./... @godep go generate ./...
@godep go build ./... @godep go build ./...

205
buildscripts/deadcode.go Normal file
View file

@ -0,0 +1,205 @@
package main
import (
"flag"
"fmt"
"go/ast"
"go/parser"
"go/token"
"os"
"path/filepath"
"sort"
"strings"
)
var exitCode int
var dirs []string
func appendUniq(slice []string, i string) []string {
for _, ele := range slice {
if ele == i {
return slice
}
}
return append(slice, i)
}
func getAllFiles(path string, fl os.FileInfo, err error) error {
if err != nil {
return err
}
if fl.IsDir() {
dirs = appendUniq(dirs, path)
}
return nil
}
func main() {
flag.Parse()
if flag.NArg() == 0 {
doDir(".")
} else {
for _, name := range flag.Args() {
// Is it a directory?
if fi, err := os.Stat(name); err == nil && fi.IsDir() {
err := filepath.Walk(name, getAllFiles)
if err != nil {
errorf(err.Error())
}
for _, dir := range dirs {
doDir(dir)
}
} else {
errorf("not a directory: %s", name)
}
}
}
os.Exit(exitCode)
}
// error formats the error to standard error, adding program
// identification and a newline
func errorf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, "deadcode: "+format+"\n", args...)
exitCode = 2
}
func doDir(name string) {
notests := func(info os.FileInfo) bool {
if !info.IsDir() && strings.HasSuffix(info.Name(), ".go") &&
!strings.HasSuffix(info.Name(), "_test.go") {
return true
}
return false
}
fs := token.NewFileSet()
pkgs, err := parser.ParseDir(fs, name, notests, parser.Mode(0))
if err != nil {
errorf("%s", err)
return
}
for _, pkg := range pkgs {
doPackage(fs, pkg)
}
}
type Package struct {
p *ast.Package
fs *token.FileSet
decl map[string]ast.Node
used map[string]bool
}
func doPackage(fs *token.FileSet, pkg *ast.Package) {
p := &Package{
p: pkg,
fs: fs,
decl: make(map[string]ast.Node),
used: make(map[string]bool),
}
for _, file := range pkg.Files {
for _, decl := range file.Decls {
switch n := decl.(type) {
case *ast.GenDecl:
// var, const, types
for _, spec := range n.Specs {
switch s := spec.(type) {
case *ast.ValueSpec:
// constants and variables.
for _, name := range s.Names {
p.decl[name.Name] = n
}
case *ast.TypeSpec:
// type definitions.
p.decl[s.Name.Name] = n
}
}
case *ast.FuncDecl:
// function declarations
// TODO(remy): do methods
if n.Recv == nil {
p.decl[n.Name.Name] = n
}
}
}
}
// init() is always used
p.used["init"] = true
if pkg.Name != "main" {
// exported names are marked used for non-main packages.
for name := range p.decl {
if ast.IsExported(name) {
p.used[name] = true
}
}
} else {
// in main programs, main() is called.
p.used["main"] = true
}
for _, file := range pkg.Files {
// walk file looking for used nodes.
ast.Walk(p, file)
}
// reports.
reports := Reports(nil)
for name, node := range p.decl {
if !p.used[name] {
reports = append(reports, Report{node.Pos(), name})
}
}
sort.Sort(reports)
for _, report := range reports {
errorf("%s: %s is unused", fs.Position(report.pos), report.name)
}
}
type Report struct {
pos token.Pos
name string
}
type Reports []Report
func (l Reports) Len() int { return len(l) }
func (l Reports) Less(i, j int) bool { return l[i].pos < l[j].pos }
func (l Reports) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
// Visits files for used nodes.
func (p *Package) Visit(node ast.Node) ast.Visitor {
u := usedWalker(*p) // hopefully p fields are references.
switch n := node.(type) {
// don't walk whole file, but only:
case *ast.ValueSpec:
// - variable initializers
for _, value := range n.Values {
ast.Walk(&u, value)
}
// variable types.
if n.Type != nil {
ast.Walk(&u, n.Type)
}
case *ast.BlockStmt:
// - function bodies
for _, stmt := range n.List {
ast.Walk(&u, stmt)
}
case *ast.FuncDecl:
// - function signatures
ast.Walk(&u, n.Type)
case *ast.TypeSpec:
// - type declarations
ast.Walk(&u, n.Type)
}
return p
}
type usedWalker Package
// Walks through the AST marking used identifiers.
func (p *usedWalker) Visit(node ast.Node) ast.Visitor {
// just be stupid and mark all *ast.Ident
switch n := node.(type) {
case *ast.Ident:
p.used[n.Name] = true
}
return p
}

View file

@ -40,6 +40,10 @@ func (server *minioApi) listObjectsHandler(w http.ResponseWriter, req *http.Requ
return return
} }
if resources.Maxkeys == 0 {
resources.Maxkeys = maxObjectList
}
acceptsContentType := getContentType(req) acceptsContentType := getContentType(req)
objects, resources, err := server.storage.ListObjects(bucket, resources) objects, resources, err := server.storage.ListObjects(bucket, resources)
switch err := err.(type) { switch err := err.(type) {

View file

@ -22,7 +22,7 @@ import (
// Limit number of objects in a given response // Limit number of objects in a given response
const ( const (
MAX_OBJECT_LIST = 1000 maxObjectList = 1000
) )
// Object list response format // Object list response format

View file

@ -36,8 +36,8 @@ type DataHeader struct {
type EncoderTechnique int type EncoderTechnique int
const ( const (
VANDERMONDE EncoderTechnique = iota Vandermonde EncoderTechnique = iota
CAUCHY Cauchy
) )
type EncoderParams struct { type EncoderParams struct {

View file

@ -39,7 +39,7 @@ func (s *MySuite) TestSingleWrite(c *C) {
Length: uint32(len(testData)), Length: uint32(len(testData)),
K: 8, K: 8,
M: 8, M: 8,
Technique: CAUCHY, Technique: Cauchy,
} }
metadata := make(Metadata) metadata := make(Metadata)
metadata["Content-Type"] = "application/octet-stream" metadata["Content-Type"] = "application/octet-stream"

View file

@ -29,7 +29,7 @@ var _ = Suite(&MySuite{})
func Test(t *testing.T) { TestingT(t) } func Test(t *testing.T) { TestingT(t) }
func (s *MySuite) TestCauchyDecode(c *C) { func (s *MySuite) TestCauchyDecode(c *C) {
ep, _ := ParseEncoderParams(10, 5, CAUCHY) ep, _ := ParseEncoderParams(10, 5, Cauchy)
data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.") data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")

View file

@ -32,7 +32,7 @@
// ParseEncoderParams(k, m, technique int) (EncoderParams, error) // ParseEncoderParams(k, m, technique int) (EncoderParams, error)
// k - Number of rows in matrix // k - Number of rows in matrix
// m - Number of colums in matrix // m - Number of colums in matrix
// technique - Matrix type, can be either CAUCHY (recommended) or VANDERMONDE // technique - Matrix type, can be either Cauchy (recommended) or Vandermonde
// constraints: k + m < Galois Field (2^8) // constraints: k + m < Galois Field (2^8)
// //
// Choosing right parity and matrix technique is left for application to decide. // Choosing right parity and matrix technique is left for application to decide.
@ -53,14 +53,14 @@
// //
// Creating and using an encoder // Creating and using an encoder
// var bytes []byte // var bytes []byte
// params := erasure.ParseEncoderParams(10, 5, erasure.CAUCHY) // params := erasure.ParseEncoderParams(10, 5, erasure.Cauchy)
// encoder := erasure.NewEncoder(params) // encoder := erasure.NewEncoder(params)
// encodedData, length := encoder.Encode(bytes) // encodedData, length := encoder.Encode(bytes)
// //
// Creating and using a decoder // Creating and using a decoder
// var encodedData [][]byte // var encodedData [][]byte
// var length int // var length int
// params := erasure.ParseEncoderParams(10, 5, erasure.CAUCHY) // params := erasure.ParseEncoderParams(10, 5, erasure.Cauchy)
// encoder := erasure.NewEncoder(params) // encoder := erasure.NewEncoder(params)
// originalData, err := encoder.Decode(encodedData, length) // originalData, err := encoder.Decode(encodedData, length)
// //

View file

@ -29,8 +29,8 @@ import (
type Technique int type Technique int
const ( const (
VANDERMONDE Technique = iota Vandermonde Technique = iota
CAUCHY Cauchy
) )
const ( const (
@ -59,7 +59,7 @@ type Encoder struct {
// ParseEncoderParams creates an EncoderParams object. // ParseEncoderParams creates an EncoderParams object.
// //
// k and m represent the matrix size, which corresponds to the protection level // k and m represent the matrix size, which corresponds to the protection level
// technique is the matrix type. Valid inputs are CAUCHY (recommended) or VANDERMONDE. // technique is the matrix type. Valid inputs are Cauchy (recommended) or Vandermonde.
// //
func ParseEncoderParams(k, m uint8, technique Technique) (*EncoderParams, error) { func ParseEncoderParams(k, m uint8, technique Technique) (*EncoderParams, error) {
if k < 1 { if k < 1 {
@ -75,9 +75,9 @@ func ParseEncoderParams(k, m uint8, technique Technique) (*EncoderParams, error)
} }
switch technique { switch technique {
case VANDERMONDE: case Vandermonde:
break break
case CAUCHY: case Cauchy:
break break
default: default:
return nil, errors.New("Technique can be either vandermonde or cauchy") return nil, errors.New("Technique can be either vandermonde or cauchy")

View file

@ -26,16 +26,6 @@ import "unsafe"
var ( var (
// See http://golang.org/ref/spec#Numeric_types // See http://golang.org/ref/spec#Numeric_types
// SizeUint8 is the byte size of a uint8.
sizeUint8 = int(unsafe.Sizeof(uint8(0)))
// SizeUint16 is the byte size of a uint16.
sizeUint16 = int(unsafe.Sizeof(uint16(0)))
// SizeUint32 is the byte size of a uint32.
sizeUint32 = int(unsafe.Sizeof(uint32(0)))
// SizeUint64 is the byte size of a uint64.
sizeUint64 = int(unsafe.Sizeof(uint64(0)))
sizeInt = int(C.sizeInt()) sizeInt = int(C.sizeInt())
// SizeInt8 is the byte size of a int8. // SizeInt8 is the byte size of a int8.
sizeInt8 = int(unsafe.Sizeof(int8(0))) sizeInt8 = int(unsafe.Sizeof(int8(0)))

View file

@ -22,7 +22,7 @@ import (
) )
func (s *MySuite) TestVanderMondeDecode(c *C) { func (s *MySuite) TestVanderMondeDecode(c *C) {
ep, _ := ParseEncoderParams(10, 5, VANDERMONDE) ep, _ := ParseEncoderParams(10, 5, Vandermonde)
data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.") data := []byte("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.")