Skip to content

Commit

Permalink
Add deadcode code which recursivley goes into all directories and ver…
Browse files Browse the repository at this point in the history
…ifies dangling variables.
  • Loading branch information
Harshavardhana committed Mar 3, 2015
1 parent 022b89d commit c3ad090
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 25 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ cover.out
minio
**/*.test
**/*.sublime-workspace
deadcode
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 ./...
Expand Down
205 changes: 205 additions & 0 deletions buildscripts/deadcode.go
Original file line number Diff line number Diff line change
@@ -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
}
4 changes: 4 additions & 0 deletions pkg/api/minioapi/bucket_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/minioapi/definitions.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (

// Limit number of objects in a given response
const (
MAX_OBJECT_LIST = 1000
maxObjectList = 1000
)

// Object list response format
Expand Down
4 changes: 2 additions & 2 deletions pkg/storage/donut/data/data_v1/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ type DataHeader struct {
type EncoderTechnique int

const (
VANDERMONDE EncoderTechnique = iota
CAUCHY
Vandermonde EncoderTechnique = iota
Cauchy
)

type EncoderParams struct {
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/donut/data/data_v1/data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/erasure/cauchy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.")

Expand Down
6 changes: 3 additions & 3 deletions pkg/storage/erasure/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
//
Expand Down
10 changes: 5 additions & 5 deletions pkg/storage/erasure/erasure_encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ import (
type Technique int

const (
VANDERMONDE Technique = iota
CAUCHY
Vandermonde Technique = iota
Cauchy
)

const (
Expand Down Expand Up @@ -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 {
Expand All @@ -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")
Expand Down
10 changes: 0 additions & 10 deletions pkg/storage/erasure/stdint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)))
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/erasure/vandermonde_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.")

Expand Down

0 comments on commit c3ad090

Please sign in to comment.