Skip to content

Commit

Permalink
Added a new check, redeclared-assigned-name
Browse files Browse the repository at this point in the history
This check is emitted when ``pylint`` detects that a name
was assigned one or multiple times in the same assignment,
which indicate a potential bug.
Close #2898
  • Loading branch information
PCManticore committed Jul 17, 2019
1 parent 4f943ed commit f38bd0d
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 1 deletion.
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ What's New in Pylint 2.4.0?

Release date: TBA

* Added a new check, ``redeclared-assigned-name``

This check is emitted when ``pylint`` detects that a name
was assigned one or multiple times in the same assignment,
which indicate a potential bug.
Close #2898

* Ignore lambda calls with variadic arguments without a context.

Inferring variadic positional arguments and keyword arguments
Expand Down
7 changes: 7 additions & 0 deletions doc/whatsnew/2.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ New checkers

Close #2905

* Added a new check, ``redeclared-assigned-name``

This check is emitted when ``pylint`` detects that a name was assigned one or multiple times in the same assignment,
which indicate a potential bug.

Close #2898

* Added a new check, ``self-assigning-variable``

This check is emitted when we detect that a variable is assigned
Expand Down
31 changes: 30 additions & 1 deletion pylint/checkers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,11 @@ class BasicChecker(_BasicChecker):
"self-assigning-variable",
"Emitted when we detect that a variable is assigned to itself",
),
"W0128": (
"Redeclared variable %r in assignment",
"redeclared-assigned-name",
"Emitted when we detect that a variable was redeclared in the same assignment.",
),
"E0111": (
"The first reversed() argument is not a sequence",
"bad-reversed-sequence",
Expand Down Expand Up @@ -1532,9 +1537,33 @@ def _check_self_assigning_variable(self, node):
"self-assigning-variable", args=(target.name,), node=target
)

@utils.check_messages("self-assigning-variable")
def _check_redeclared_assign_name(self, targets):
for target in targets:
if not isinstance(target, astroid.Tuple):
continue

found_names = []
for element in target.elts:
if isinstance(element, astroid.Tuple):
self._check_redeclared_assign_name([element])
elif isinstance(element, astroid.AssignName) and element.name != "_":
found_names.append(element.name)

names = collections.Counter(found_names)
for name, count in names.most_common():
if count > 1:
self.add_message(
"redeclared-assigned-name", args=(name,), node=target
)

@utils.check_messages("self-assigning-variable", "redeclared-assigned-name")
def visit_assign(self, node):
self._check_self_assigning_variable(node)
self._check_redeclared_assign_name(node.targets)

@utils.check_messages("redeclared-assigned-name")
def visit_for(self, node):
self._check_redeclared_assign_name([node.target])


KNOWN_NAME_TYPES = {
Expand Down
9 changes: 9 additions & 0 deletions tests/functional/redeclared_assigned_name.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# pylint: disable=missing-docstring

FIRST, FIRST = (1, 2) # [redeclared-assigned-name]

for SECOND, SECOND in enumerate(range(5, 10)): # [redeclared-assigned-name]
print(SECOND)

for FIRST, (SECOND, FIRST, SECOND) in enumerate(range(5, 10)): # [redeclared-assigned-name]
print(SECOND)
3 changes: 3 additions & 0 deletions tests/functional/redeclared_assigned_name.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
redeclared-assigned-name:3::Redeclared variable 'FIRST' in assignment
redeclared-assigned-name:5::Redeclared variable 'SECOND' in assignment
redeclared-assigned-name:8::Redeclared variable 'SECOND' in assignment

0 comments on commit f38bd0d

Please sign in to comment.