1
0
mirror of https://github.com/mgechev/revive.git synced 2025-10-30 23:37:49 +02:00

draft version

This commit is contained in:
chavacava
2025-08-30 08:04:31 +02:00
parent ec8439e646
commit 22844d49af
4 changed files with 186 additions and 0 deletions

View File

@@ -115,6 +115,7 @@ var allRules = append([]lint.Rule{
&rule.UnsecureURLSchemeRule{},
&rule.InefficientMapLookupRule{},
&rule.ForbiddenCallInWgGoRule{},
&rule.UnnecessaryConditionalRule{},
}, defaultRules...)
// allFormatters is a list of all available formatters to output the linting results.

View File

@@ -0,0 +1,156 @@
package rule
import (
"fmt"
"go/ast"
"github.com/mgechev/revive/internal/astutils"
"github.com/mgechev/revive/lint"
)
// UnnecessaryConditionalRule warns on if...else statements with both branches being the same.
type UnnecessaryConditionalRule struct{}
// Apply applies the rule to given file.
func (*UnnecessaryConditionalRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
var failures []lint.Failure
onFailure := func(failure lint.Failure) {
failures = append(failures, failure)
}
w := &lintUnnecessaryConditional{onFailure: onFailure}
for _, decl := range file.AST.Decls {
fn, ok := decl.(*ast.FuncDecl)
if !ok || fn.Body == nil {
continue
}
ast.Walk(w, fn.Body)
}
return failures
}
// Name returns the rule name.
func (*UnnecessaryConditionalRule) Name() string {
return "unnecessary-conditional"
}
type lintUnnecessaryConditional struct {
onFailure func(lint.Failure)
}
func (w *lintUnnecessaryConditional) Visit(node ast.Node) ast.Visitor {
ifStmt, ok := node.(*ast.IfStmt)
if !ok {
return w
}
if ifStmt.Else == nil {
return w // if without else
}
elseBranch, ok := ifStmt.Else.(*ast.BlockStmt)
if !ok { // if-else-if construction, the rule only copes with single if...else statements
return w
}
thenStmts := ifStmt.Body.List
elseStmts := elseBranch.List
if len(thenStmts) != 1 || len(elseStmts) != 1 {
return w
}
replacement := ""
switch thenStmt := thenStmts[0].(type) {
case *ast.ReturnStmt:
thenBool, ok := w.resultValueIsBooleanLiteral(thenStmt.Results)
if !ok {
return w
}
elseStmt, ok := elseStmts[0].(*ast.ReturnStmt)
if !ok {
return w
}
_, ok = w.resultValueIsBooleanLiteral(elseStmt.Results)
if !ok {
return w
}
cond := astutils.GoFmt(ifStmt.Cond)
if thenBool != "true" {
cond = "!(" + cond + ")"
}
replacement = "return " + cond
case *ast.AssignStmt:
thenBool, ok := w.isBooleanLiteral(thenStmt.Rhs)
if !ok {
return w
}
thenLhs := astutils.GoFmt(thenStmt.Lhs[0])
elseStmt, ok := elseStmts[0].(*ast.AssignStmt)
if !ok {
return w
}
elseLhs := astutils.GoFmt(elseStmt.Lhs[0])
if thenLhs != elseLhs {
return w
}
_, ok = w.isBooleanLiteral(elseStmt.Rhs)
if !ok {
return w
}
cond := astutils.GoFmt(ifStmt.Cond)
if thenBool != "true" {
cond = "!(" + cond + ")"
}
replacement = fmt.Sprintf("%s %s %s", thenLhs, thenStmt.Tok.String(), cond)
default:
return w
}
w.onFailure(lint.Failure{
Confidence: 1.0,
Node: ifStmt,
Category: lint.FailureCategoryLogic,
Failure: "replace this conditional by: " + replacement,
})
return nil
}
func (w *lintUnnecessaryConditional) resultValueIsBooleanLiteral(results []ast.Expr) (string, bool) {
if len(results) != 1 {
return "", false
}
ident, ok := results[0].(*ast.Ident)
if !ok {
return "", false
}
return ident.Name, (ident.Name == "true" || ident.Name == "false")
}
func (*lintUnnecessaryConditional) isBooleanLiteral(exprs []ast.Expr) (string, bool) {
if len(exprs) != 1 {
return "", false
}
ident, ok := exprs[0].(*ast.Ident)
if !ok {
return "", false
}
return ident.Name, (ident.Name == "true" || ident.Name == "false")
}

View File

@@ -0,0 +1,12 @@
package test
import (
"testing"
"github.com/mgechev/revive/lint"
"github.com/mgechev/revive/rule"
)
func TestUnnecessaryConditional(t *testing.T) {
testRule(t, "unnecessary_conditional", &rule.UnnecessaryConditionalRule{}, &lint.RuleConfig{})
}

17
testdata/unnecessary_conditional.go vendored Normal file
View File

@@ -0,0 +1,17 @@
package fixtures
func unnecessaryConditional() bool {
if cond {
return true
} else {
return false
}
if cond {
id = true
} else {
id = false
}
return false
}