mirror of
https://github.com/status-im/status-go.git
synced 2025-02-14 15:56:47 +00:00
wip
This commit is contained in:
parent
6ee62061bc
commit
b0d3f87844
89
cmd/earlyreturn/analyzer/analyzer.go
Normal file
89
cmd/earlyreturn/analyzer/analyzer.go
Normal file
@ -0,0 +1,89 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
"go/ast"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func New() *analysis.Analyzer {
|
||||
return &analysis.Analyzer{
|
||||
Name: "earlyreturn",
|
||||
Doc: "reports places for early return pattern usage",
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||
Run: run,
|
||||
}
|
||||
}
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
inspected, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
if !ok {
|
||||
return nil, errors.New("analyzer is not type *inspector.Inspector")
|
||||
}
|
||||
|
||||
// Create a nodes filter for `if` statements
|
||||
nodeFilter := []ast.Node{
|
||||
(*ast.IfStmt)(nil),
|
||||
}
|
||||
|
||||
// Inspect go statements
|
||||
inspected.Preorder(nodeFilter, func(n ast.Node) {
|
||||
processNode(pass, n)
|
||||
})
|
||||
|
||||
inspected.WithStack(nodeFilter, func(n ast.Node, push bool, stack []ast.Node) bool {
|
||||
return processNodeWithStack(pass, n, push, stack)
|
||||
})
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func processNodeWithStack(pass *analysis.Pass, n ast.Node, push bool, stack []ast.Node) bool {
|
||||
ifStmt, ok := n.(*ast.IfStmt)
|
||||
if !ok {
|
||||
panic("unexpected node type")
|
||||
}
|
||||
|
||||
// Find the parent node of the `if` statement
|
||||
if len(stack) < 2 {
|
||||
return false
|
||||
}
|
||||
parent := stack[len(stack)-2] // Last node in stack is `n`. Second to last is the parent node.
|
||||
|
||||
// Check if the `if` statement has an `else` block
|
||||
if ifStmt.Else != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the `if` statement has a `return` statement
|
||||
for _, stmt := range ifStmt.Body.List {
|
||||
retStmt, ok := stmt.(*ast.ReturnStmt)
|
||||
if ok {
|
||||
pass.Reportf(retStmt.Pos(), "early return pattern detected")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func processNode(pass *analysis.Pass, n ast.Node) {
|
||||
ifStmt, ok := n.(*ast.IfStmt)
|
||||
if !ok {
|
||||
panic("unexpected node type")
|
||||
}
|
||||
|
||||
// Check if the `if` statement has an `else` block
|
||||
if ifStmt.Else != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the `if` statement has a `return` statement
|
||||
for _, stmt := range ifStmt.Body.List {
|
||||
retStmt, ok := stmt.(*ast.ReturnStmt)
|
||||
if ok {
|
||||
pass.Reportf(retStmt.Pos(), "early return pattern detected")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
12
cmd/earlyreturn/analyzer/analyzer_test.go
Normal file
12
cmd/earlyreturn/analyzer/analyzer_test.go
Normal file
@ -0,0 +1,12 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
)
|
||||
|
||||
func TestConditions(t *testing.T) {
|
||||
t.Parallel()
|
||||
a := New()
|
||||
analysistest.Run(t, analysistest.TestData(), a, "functions")
|
||||
}
|
61
cmd/earlyreturn/analyzer/testdata/src/functions/functions.go
vendored
Normal file
61
cmd/earlyreturn/analyzer/testdata/src/functions/functions.go
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
package testdata
|
||||
|
||||
func test2(a bool, input string) string {
|
||||
if a { // want "condition body is longer than the code after it"
|
||||
input += "a"
|
||||
input += "b"
|
||||
input += "c"
|
||||
return input
|
||||
}
|
||||
return "test"
|
||||
}
|
||||
|
||||
func test1(a bool, input string) string {
|
||||
out := input
|
||||
if a {
|
||||
// nothing to improve, `else` branch is same size as `if` branch
|
||||
out += "a"
|
||||
} else {
|
||||
out += "b"
|
||||
}
|
||||
out += "c" // can't early return because: 1. has `else` branch AND 2. there's code after the `if` statement
|
||||
return "test"
|
||||
}
|
||||
|
||||
func test3(a bool, b bool, input string) string {
|
||||
out := ""
|
||||
if a {
|
||||
out = "1"
|
||||
} else {
|
||||
if b {
|
||||
out = "2"
|
||||
} else {
|
||||
out = "3"
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func test4(a bool, b bool) string {
|
||||
out := ""
|
||||
if a {
|
||||
if b { // want "condition body is longer that `else` body"
|
||||
out = "2"
|
||||
} else {
|
||||
out = "3"
|
||||
}
|
||||
} else {
|
||||
out = "1"
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func test5(a bool, b bool, items []string) {
|
||||
for range items {
|
||||
if a { // want "condition body is longer than the code after it"
|
||||
a := "1"
|
||||
a += "2"
|
||||
a += "3"
|
||||
}
|
||||
}
|
||||
}
|
1
cmd/earlyreturn/main.go
Normal file
1
cmd/earlyreturn/main.go
Normal file
@ -0,0 +1 @@
|
||||
package earlyreturn
|
Loading…
x
Reference in New Issue
Block a user