Skip to content

Commit

Permalink
Add use-list-literal and use-dict-literal
Browse files Browse the repository at this point in the history
This adds two checks for when empty lists and dicts are created
using a function call instead of their literals.
This closes pylint-dev#4365
  • Loading branch information
DanielNoord committed Jul 29, 2021
1 parent c00b07b commit 62d5a81
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 1 deletion.
7 changes: 7 additions & 0 deletions ChangeLog
Expand Up @@ -37,6 +37,13 @@ Release date: TBA

Closes #3878

* Added ``use-list-literal``: Emitted when ``list()`` is called with no arguments instead of using ``[]``

Closes #4365

* Added ``use-dict-literal``: Emitted when ``dict()`` is called with no arguments instead of using ``{}``

Closes #4365


What's New in Pylint 2.9.6?
Expand Down
8 changes: 8 additions & 0 deletions doc/whatsnew/2.10.rst
Expand Up @@ -16,6 +16,14 @@ New checkers

Closes #3826

* Added ``use-list-literal``: Emitted when ``list()`` is called with no arguments instead of using ``[]``

Closes #4365

* Added ``use-dict-literal``: Emitted when ``dict()`` is called with no arguments instead of using ``{}``

Closes #4365


Other Changes
=============
Expand Down
31 changes: 30 additions & 1 deletion pylint/checkers/refactoring/refactoring_checker.py
Expand Up @@ -413,6 +413,18 @@ class RefactoringChecker(checkers.BaseTokenChecker):
"value by index lookup. "
"The value can be accessed directly instead.",
),
"R1734": (
"Consider using [] instead of list()",
"use-list-literal",
"Emitted when using list() to create an empty list instead of the literal []. "
"The literal is faster as it avoids an additional function call.",
),
"R1735": (
"Consider using {} instead of dict()",
"use-dict-literal",
"Emitted when using dict() to create an empty dictionary instead of the literal {}. "
"The literal is faster as it avoids an additional function call.",
),
}
options = (
(
Expand Down Expand Up @@ -964,6 +976,8 @@ def _check_consider_using_generator(self, node):
"super-with-arguments",
"consider-using-generator",
"consider-using-with",
"use-list-literal",
"use-dict-literal",
)
def visit_call(self, node):
self._check_raising_stopiteration_in_generator_next_call(node)
Expand All @@ -972,6 +986,7 @@ def visit_call(self, node):
self._check_super_with_arguments(node)
self._check_consider_using_generator(node)
self._check_consider_using_with(node)
self._check_use_list_or_dict_literal(node)

@staticmethod
def _has_exit_in_scope(scope):
Expand Down Expand Up @@ -1454,6 +1469,20 @@ def _check_consider_using_with(self, node: astroid.Call):
if could_be_used_in_with and not _will_be_released_automatically(node):
self.add_message("consider-using-with", node=node)

def _check_use_list_or_dict_literal(self, node: astroid.Call) -> None:
"""Check if empty list or dict is created by using the literal [] or {}"""
try:
for inferred in node.func.infer():
if inferred is astroid.Uninferable:
continue
if isinstance(inferred, astroid.ClassDef) and node.args == []:
if inferred.name == "list":
self.add_message("use-list-literal", node=node)
if inferred.name == "dict" and node.keywords == []:
self.add_message("use-dict-literal", node=node)
except astroid.InferenceError:
pass

def _check_consider_using_join(self, aug_assign):
"""
We start with the augmented assignment and work our way upwards.
Expand Down Expand Up @@ -1660,7 +1689,7 @@ def _is_if_node_return_ended(self, node: astroid.If) -> bool:
def _is_raise_node_return_ended(self, node: astroid.Raise) -> bool:
"""Check if the Raise node ends with an explicit return statement.
Args:
Args:x
node (astroid.Raise): Raise node to be checked.
Returns:
Expand Down
7 changes: 7 additions & 0 deletions tests/functional/u/use/use_dict_literal.py
@@ -0,0 +1,7 @@
# pylint: disable=missing-docstring, invalid-name

x = dict() # [use-dict-literal]
x = dict(a="1", b=None, c=3)
x = dict(zip(["a", "b", "c"], [1, 2, 3]))
x = {}
x = {"a": 1, "b": 2, "c": 3}
1 change: 1 addition & 0 deletions tests/functional/u/use/use_dict_literal.txt
@@ -0,0 +1 @@
use-dict-literal:3:4::"Consider using {} instead of dict()"
9 changes: 9 additions & 0 deletions tests/functional/u/use/use_list_literal.py
@@ -0,0 +1,9 @@
# pylint: disable=missing-docstring, invalid-name

x = list() # [use-list-literal]
x = list("string")
x = list(range(3))
x = []
x = ["string"]
x = [1, 2, 3]
x = [range(3)]
1 change: 1 addition & 0 deletions tests/functional/u/use/use_list_literal.txt
@@ -0,0 +1 @@
use-list-literal:3:4::"Consider using [] instead of list()"

0 comments on commit 62d5a81

Please sign in to comment.