1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
from dataclasses import dataclass
from mypy.nodes import (
Block,
CallExpr,
ExpressionStmt,
MemberExpr,
MypyFile,
NameExpr,
Statement,
Var,
)
from refurb.checks.common import check_block_like
from refurb.error import Error
@dataclass
class ErrorInfo(Error):
"""
When appending multiple values to a list, you can use the `.extend()`
method to add an iterable to the end of an existing list. This way, you
don't have to call `.append()` on every element:
Bad:
```
nums = [1, 2, 3]
nums.append(4)
nums.append(5)
nums.append(6)
```
Good:
```
nums = [1, 2, 3]
nums.extend((4, 5, 6))
```
"""
name = "use-list-extend"
code = 113
msg: str = "Use `x.extend(...)` instead of repeatedly calling `x.append()`"
categories = ("list",)
@dataclass
class Last:
name: str = ""
line: int = 0
column: int = 0
did_error: bool = False
def check(node: Block | MypyFile, errors: list[Error]) -> None:
check_block_like(check_stmts, node, errors)
def check_stmts(stmts: list[Statement], errors: list[Error]) -> None:
last = Last()
for stmt in stmts:
match stmt:
case ExpressionStmt(
expr=CallExpr(
callee=MemberExpr(
expr=NameExpr(name=name, node=Var(type=ty)),
name="append",
),
)
) if str(ty).startswith("builtins.list["):
if not last.did_error and name == last.name:
errors.append(ErrorInfo(last.line, last.column))
last.did_error = True
last.name = name
last.line = stmt.line
last.column = stmt.column
case _:
last = Last()
|