mirror of https://github.com/minio/minio.git
Add deadcode code which recursivley goes into all directories and verifies dangling variables.
This commit is contained in:
parent
022b89dd9b
commit
c3ad0906e0
|
@ -5,3 +5,4 @@ cover.out
|
|||
minio
|
||||
**/*.test
|
||||
**/*.sublime-workspace
|
||||
deadcode
|
5
Makefile
5
Makefile
|
@ -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 ./...
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
// Limit number of objects in a given response
|
||||
const (
|
||||
MAX_OBJECT_LIST = 1000
|
||||
maxObjectList = 1000
|
||||
)
|
||||
|
||||
// Object list response format
|
||||
|
|
|
@ -36,8 +36,8 @@ type DataHeader struct {
|
|||
type EncoderTechnique int
|
||||
|
||||
const (
|
||||
VANDERMONDE EncoderTechnique = iota
|
||||
CAUCHY
|
||||
Vandermonde EncoderTechnique = iota
|
||||
Cauchy
|
||||
)
|
||||
|
||||
type EncoderParams struct {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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.")
|
||||
|
||||
|
|
|
@ -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)
|
||||
//
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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.")
|
||||
|
||||
|
|
Loading…
Reference in New Issue