From b2c7223a9fecbe64624814fc09a63269a6832e71 Mon Sep 17 00:00:00 2001 From: Eric Zimanyi Date: Wed, 22 Dec 2021 15:27:30 -0500 Subject: [PATCH] Fix a few edge cases due to missing ast node types * Traverse Unary expressions in if statements * Traverse else blocks This fixes both false positives and negatives resulting from previously ignoring uses of variables in the above node types. --- pkg/analyzer/analyzer.go | 7 +++++++ pkg/analyzer/occurrences.go | 7 +++++++ testdata/testdata.go | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/pkg/analyzer/analyzer.go b/pkg/analyzer/analyzer.go index 05c3b17..b2d0688 100644 --- a/pkg/analyzer/analyzer.go +++ b/pkg/analyzer/analyzer.go @@ -108,8 +108,15 @@ func (nom namedOccurrenceMap) checkStatement(stmt ast.Stmt, ifPos token.Pos) { for _, el := range v.Body.List { nom.checkStatement(el, v.If) } + if elseBlock, ok := v.Else.(*ast.BlockStmt); ok { + for _, el := range elseBlock.List { + nom.checkStatement(el, v.If) + } + } switch cond := v.Cond.(type) { + case *ast.UnaryExpr: + nom.checkExpression(cond.X, v.If) case *ast.BinaryExpr: nom.checkExpression(cond.X, v.If) nom.checkExpression(cond.Y, v.If) diff --git a/pkg/analyzer/occurrences.go b/pkg/analyzer/occurrences.go index 34224c9..117559a 100644 --- a/pkg/analyzer/occurrences.go +++ b/pkg/analyzer/occurrences.go @@ -193,6 +193,13 @@ func (nom namedOccurrenceMap) addFromCondition(stmt *ast.IfStmt) { nom.addFromIdent(stmt.If, e.X) } } + case *ast.UnaryExpr: + switch e := v.X.(type) { + case *ast.Ident: + nom.addFromIdent(stmt.If, e) + case *ast.SelectorExpr: + nom.addFromIdent(stmt.If, e.X) + } case *ast.Ident: nom.addFromIdent(stmt.If, v) case *ast.CallExpr: diff --git a/testdata/testdata.go b/testdata/testdata.go index d0d019c..b97a3aa 100644 --- a/testdata/testdata.go +++ b/testdata/testdata.go @@ -77,6 +77,14 @@ func notUsed_DifferentVarsWithSameName_NotOK() { noOp2(b) } +func notUsed_UnaryOpIfStatement_NotOK() { + shouldRun := false // want "variable '.+' is only used in the if-statement" + if !shouldRun { + return + } + noOp1(0) +} + // Cases where short syntax SHOULD NOT be used AND IS NOT used. func notUsed_DeferStmt_OK() { @@ -574,4 +582,28 @@ func notUsed_ReturnInSlice_Selector_OK(d dummyType) ([]interface{}, interface{}) return nil, v.interf } return []interface{}{v.interf}, nil -} \ No newline at end of file +} + +func notUsed_Multiple_If_Statements_OK() { + shouldRun := false + if shouldRun { + noOp1(0) + } + if !shouldRun { + return + } + noOp2(0) +} + +func notUsed_Also_Used_In_Else_Body_OK() { + x := 0 + if x > 0 { + noOp1(0) + } + + if y := getInt(0); y > 0 { + noOp1(y) + } else { + noOp1(x) + } +}