-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: remove examples/foo.go and add fixer.go for enhanced functionality
- **Why remove examples/foo.go?** The functions within were likely deemed unnecessary or have been refactored into a more comprehensive solution. - **Why add fixer.go?** Introduces a utility for modifying Go source files, possibly to automate code refactoring or corrections, enhancing the development workflow. refactor(main.go): streamline flag parsing and function removal logic feat(main.go): add JSON schema support for dead code analysis feat(schema.go): introduce JSON schema for deadcode output analysis feat(testdata): add test files and examples for dead code analysis feat(testdata/stringer.go): add new myString struct implementing fmt.Stringer This commit introduces a new file `stringer.go` within the `testdata` directory, which defines a `myString` struct. This struct implements the `fmt.Stringer` interface, ensuring that instances of `myString` can be easily converted to a string using the `String()` method. This addition aims to enhance the codebase by providing a clear and idiomatic way to convert `myString` instances to strings, following Go's convention of using the `Stringer` interface for string representations of types.
- Loading branch information
1 parent
d484a9b
commit 9ea8391
Showing
8 changed files
with
198 additions
and
64 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"fmt" | ||
"go/ast" | ||
"go/format" | ||
"go/parser" | ||
"go/token" | ||
"os" | ||
) | ||
|
||
func fix(filename, functionName string) error { | ||
start, end, err := lookup(filename, functionName) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := rewrite(filename, start, end); err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func lookup(filename, functionName string) (int, int, error) { | ||
fset := token.NewFileSet() | ||
node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) | ||
if err != nil { | ||
return 0, 0, err | ||
} | ||
|
||
var start, end int | ||
ast.Inspect(node, func(n ast.Node) bool { | ||
funcDecl, ok := n.(*ast.FuncDecl) | ||
if ok && funcDecl.Name.Name == functionName { | ||
start = fset.Position(funcDecl.Pos()).Line | ||
end = fset.Position(funcDecl.End()).Line | ||
return false | ||
} | ||
return true | ||
}) | ||
if start == 0 || end == 0 { | ||
return 0, 0, fmt.Errorf("func %s not found in %s", functionName, filename) | ||
} | ||
return start, end, nil | ||
} | ||
|
||
func rewrite(filename string, start, end int) error { | ||
file, err := os.Open(filename) | ||
if err != nil { | ||
return err | ||
} | ||
defer file.Close() | ||
|
||
buf := new(bytes.Buffer) | ||
scanner := bufio.NewScanner(file) | ||
for l := 1; scanner.Scan(); { | ||
if l < start || l > end { | ||
if _, err := buf.Write(append(scanner.Bytes(), '\n')); err != nil { | ||
return err | ||
} | ||
} | ||
l++ | ||
} | ||
if err := scanner.Err(); err != nil { | ||
return err | ||
} | ||
|
||
// run gofmt | ||
b, err := format.Source(buf.Bytes()) | ||
if err != nil { | ||
return err | ||
} | ||
// write to file | ||
info, err := file.Stat() | ||
if err != nil { | ||
return err | ||
} | ||
if err := os.WriteFile(filename, b, info.Mode()); err != nil { | ||
return err | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,59 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"encoding/json" | ||
"flag" | ||
"go/ast" | ||
"go/format" | ||
"go/parser" | ||
"go/token" | ||
"io" | ||
"log" | ||
"os" | ||
) | ||
|
||
// flags | ||
var ( | ||
fileName, functionName string | ||
jsonFlag = flag.String("json", "", "JSON file generated by deadcode") | ||
fileFlag = flag.String("file", "", "File to remove function from") | ||
functionFlag = flag.String("function", "", "Function to remove") | ||
) | ||
|
||
func main() { | ||
flag.StringVar(&fileName, "f", "", "File to remove function from (shorthand)") | ||
flag.StringVar(&fileName, "file", "", "File to remove function from") | ||
flag.StringVar(&functionName, "fn", "", "File to remove function from (shorthand)") | ||
flag.StringVar(&functionName, "function", "", "Function to remove") | ||
flag.Parse() | ||
|
||
if fileName == "" || functionName == "" { | ||
flag.Usage() | ||
os.Exit(1) | ||
} | ||
|
||
fset := token.NewFileSet() | ||
node, err := parser.ParseFile(fset, fileName, nil, parser.ParseComments) | ||
if err != nil { | ||
log.Fatalf("Failed to parse file: %v", err) | ||
} | ||
|
||
var start, end int | ||
ast.Inspect(node, func(n ast.Node) bool { | ||
fn, ok := n.(*ast.FuncDecl) | ||
if ok && fn.Name.Name == functionName { | ||
start = fset.Position(fn.Pos()).Line | ||
end = fset.Position(fn.End()).Line | ||
return false | ||
// run specific fixer | ||
if f, fn := *fileFlag, *functionFlag; f != "" && fn != "" { | ||
if err := fix(f, fn); err != nil { | ||
log.Fatal(err) | ||
} | ||
return true | ||
}) | ||
|
||
file, err := os.Open(fileName) | ||
if err != nil { | ||
log.Fatalf("Failed to open file: %v", err) | ||
} | ||
defer file.Close() | ||
|
||
buf := new(bytes.Buffer) | ||
scanner := bufio.NewScanner(file) | ||
for l := 1; scanner.Scan(); { | ||
if l < start || l > end { | ||
if _, err := buf.Write(append(scanner.Bytes(), '\n')); err != nil { | ||
log.Fatalf("Failed to write to buffer: %v", err) | ||
} | ||
return | ||
} | ||
// run fixer by reading JSON | ||
var r io.Reader | ||
switch v := *jsonFlag; v { | ||
case "", "-": | ||
r = os.Stdin | ||
default: | ||
f, err := os.Open(v) | ||
if err != nil { | ||
log.Fatalf("failed to open file %s: %v", v, err) | ||
} | ||
l++ | ||
defer f.Close() | ||
r = f | ||
} | ||
if err := scanner.Err(); err != nil { | ||
log.Fatalf("Failed to read file: %v", err) | ||
if err := run(r); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
// run gofmt | ||
b, err := format.Source(buf.Bytes()) | ||
if err != nil { | ||
log.Fatalf("Failed to format source: %v", err) | ||
func run(r io.Reader) error { | ||
packages := []Package{} | ||
if err := json.NewDecoder(r).Decode(&packages); err != nil { | ||
return err | ||
} | ||
// write to file | ||
info, err := file.Stat() | ||
if err != nil { | ||
log.Fatalf("Failed to get file info: %v", err) | ||
} | ||
if err := os.WriteFile(fileName, b, info.Mode()); err != nil { | ||
log.Fatalf("Failed to write to file: %v", err) | ||
for _, p := range packages { | ||
for _, f := range p.Funcs { | ||
if err := fix(f.Position.File, f.Name); err != nil { | ||
return err | ||
} | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package main | ||
|
||
// This file contains the JSON schema for the deadcode output. | ||
// https://pkg.go.dev/golang.org/x/tools@v0.20.0/cmd/deadcode#hdr-JSON_schema | ||
|
||
type Package struct { | ||
Name string // declared name | ||
Path string // full import path | ||
Funcs []Function // list of dead functions within it | ||
} | ||
|
||
type Function struct { | ||
Name string // name (sans package qualifier) | ||
Position Position // file/line/column of function declaration | ||
Generated bool // function is declared in a generated .go file | ||
} | ||
|
||
type Edge struct { | ||
Initial string // initial entrypoint (main or init); first edge only | ||
Kind string // = static | dynamic | ||
Position Position // file/line/column of call site | ||
Callee string // target of the call | ||
} | ||
|
||
type Position struct { | ||
File string // name of file | ||
Line, Col int // line and byte index, both 1-based | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package main | ||
|
||
func main() { | ||
Reachable() | ||
} | ||
|
||
func init() { | ||
s := myString{Value: "hello"} | ||
s.Reachable() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package main | ||
|
||
import "testing" | ||
|
||
func TestReachableByTest(t *testing.T) { | ||
ReachableByTest() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package main | ||
|
||
import "fmt" | ||
|
||
func Reachable() { | ||
fmt.Println("reachable") | ||
} | ||
|
||
func Unreachable() { | ||
fmt.Println("unreachable") | ||
} | ||
|
||
func ReachableByTest() { | ||
fmt.Println("reachableByTest") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package main | ||
|
||
import "fmt" | ||
|
||
var _ fmt.Stringer = myString{} | ||
|
||
type myString struct { | ||
Value string | ||
} | ||
|
||
func (s myString) String() string { | ||
return s.Value | ||
} | ||
|
||
func (s myString) Reachable() { | ||
return | ||
} |