Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions warn/warn_control_flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,15 @@ func noEffectWarning(f *build.File) []*LinterFinding {
return findings
}

var mutatingMethodsReturningNone = map[string]bool{
"append": true,
"clear": true,
"extend": true,
"insert": true,
"remove": true,
"update": true,
}
Comment thread
keith marked this conversation as resolved.

// extractIdentsFromStmt returns all idents from an AST node representing a
// single statement that are either defined outside the node and used inside,
// or defined inside the node and can be used outside.
Expand Down Expand Up @@ -305,6 +314,13 @@ func extractIdentsFromStmt(stmt build.Expr) (assigned, used map[*build.Ident]boo
(!allLValuesUnderscored && strings.HasPrefix(lValue.Name, "_"))
}

case *build.CallExpr:
if dot, ok := expr.X.(*build.DotExpr); ok && mutatingMethodsReturningNone[dot.Name] {
if _, ok := dot.X.(*build.Ident); ok {
blockedNodes[dot.X] = true
}
}

case *build.ForStmt:
// Like AssignExpr, ForStmt too has an analogue of LHS and RHS.
// Unlike AssignExpr, in this function they may appear only in the root of
Expand Down
24 changes: 24 additions & 0 deletions warn/warn_control_flow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,30 @@ sample_macro_with_used_foo()
`,
[]string{},
scopeEverywhere)

checkFindings(t, "unused-variable", `
def framework_import_impl():
used_list = []
unused_list = []
unused_dictionary = {}

used_list.extend([1])
unused_dictionary.update(_ensure_swiftmodule_is_embedded(swiftmodule))
unused_list.extend([
x
for x in used_list
if x > 5
])

return used_list

framework_import_impl()
`,
[]string{
":3: Variable \"unused_list\" is unused.",
":4: Variable \"unused_dictionary\" is unused.",
},
scopeEverywhere)
}

func TestRedefinedVariable(t *testing.T) {
Expand Down