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
**/*.test
**/*.sublime-workspace
deadcode

View file

@ -13,7 +13,10 @@ checkgopath:
getdeps: checkdeps checkgopath
@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"
@godep go generate ./...
@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
}
if resources.Maxkeys == 0 {
resources.Maxkeys = maxObjectList
}
acceptsContentType := getContentType(req)
objects, resources, err := server.storage.ListObjects(bucket, resources)
switch err := err.(type) {

View file

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

View file

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

View file

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

View file

@ -29,7 +29,7 @@ var _ = Suite(&MySuite{})
func Test(t *testing.T) { TestingT(t) }
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.")

View file

@ -32,7 +32,7 @@
// ParseEncoderParams(k, m, technique int) (EncoderParams, error)
// k - Number of rows 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)
//
// Choosing right parity and matrix technique is left for application to decide.
@ -53,14 +53,14 @@
//
// Creating and using an encoder
// var bytes []byte
// params := erasure.ParseEncoderParams(10, 5, erasure.CAUCHY)
// params := erasure.ParseEncoderParams(10, 5, erasure.Cauchy)
// encoder := erasure.NewEncoder(params)
// encodedData, length := encoder.Encode(bytes)
//
// Creating and using a decoder
// var encodedData [][]byte
// var length int
// params := erasure.ParseEncoderParams(10, 5, erasure.CAUCHY)
// params := erasure.ParseEncoderParams(10, 5, erasure.Cauchy)
// encoder := erasure.NewEncoder(params)
// originalData, err := encoder.Decode(encodedData, length)
//

View file

@ -29,8 +29,8 @@ import (
type Technique int
const (
VANDERMONDE Technique = iota
CAUCHY
Vandermonde Technique = iota
Cauchy
)
const (
@ -59,7 +59,7 @@ type Encoder struct {
// ParseEncoderParams creates an EncoderParams object.
//
// 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) {
if k < 1 {
@ -75,9 +75,9 @@ func ParseEncoderParams(k, m uint8, technique Technique) (*EncoderParams, error)
}
switch technique {
case VANDERMONDE:
case Vandermonde:
break
case CAUCHY:
case Cauchy:
break
default:
return nil, errors.New("Technique can be either vandermonde or cauchy")

View file

@ -26,16 +26,6 @@ import "unsafe"
var (
// 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())
// SizeInt8 is the byte size of a int8.
sizeInt8 = int(unsafe.Sizeof(int8(0)))

View file

@ -22,7 +22,7 @@ import (
)
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.")