From 63953431a670c60af69f53af207498283bc892ac Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Sat, 6 Jan 2024 17:28:57 -0500 Subject: [PATCH] Include subscripts and attributes in static key rule (#9416) --- .../resources/test/fixtures/ruff/RUF011.py | 5 ++ .../rules/static_key_dict_comprehension.rs | 4 + ..._rules__ruff__tests__RUF011_RUF011.py.snap | 84 ++++++++++++------- 3 files changed, 61 insertions(+), 32 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py b/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py index 37387b7fb2cf3..dec601bd685aa 100644 --- a/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py +++ b/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py @@ -7,6 +7,9 @@ {v: v * v for v in range(10)} {(0, "a", v): v * v for v in range(10)} # Tuple with variable {constant: value.upper() for value in data for constant in data} +{value.attribute: value.upper() for value in data for constant in data} +{constant[value]: value.upper() for value in data for constant in data} +{value[constant]: value.upper() for value in data for constant in data} # Errors {"key": value.upper() for value in data} @@ -15,3 +18,5 @@ {(1, "a"): value.upper() for value in data} # Constant tuple {constant: value.upper() for value in data} {constant + constant: value.upper() for value in data} +{constant.attribute: value.upper() for value in data} +{constant[0]: value.upper() for value in data} diff --git a/crates/ruff_linter/src/rules/ruff/rules/static_key_dict_comprehension.rs b/crates/ruff_linter/src/rules/ruff/rules/static_key_dict_comprehension.rs index 9f37acc09782d..cdcc672105428 100644 --- a/crates/ruff_linter/src/rules/ruff/rules/static_key_dict_comprehension.rs +++ b/crates/ruff_linter/src/rules/ruff/rules/static_key_dict_comprehension.rs @@ -74,6 +74,10 @@ fn is_constant(key: &Expr, names: &FxHashMap<&str, &ast::ExprName>) -> bool { match key { Expr::Tuple(ast::ExprTuple { elts, .. }) => elts.iter().all(|elt| is_constant(elt, names)), Expr::Name(ast::ExprName { id, .. }) => !names.contains_key(id.as_str()), + Expr::Attribute(ast::ExprAttribute { value, .. }) => is_constant(value, names), + Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { + is_constant(value, names) && is_constant(slice, names) + } Expr::BinOp(ast::ExprBinOp { left, right, .. }) => { is_constant(left, names) && is_constant(right, names) } diff --git a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF011_RUF011.py.snap b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF011_RUF011.py.snap index 34e5111b469be..f7a7667d1e131 100644 --- a/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF011_RUF011.py.snap +++ b/crates/ruff_linter/src/rules/ruff/snapshots/ruff_linter__rules__ruff__tests__RUF011_RUF011.py.snap @@ -1,60 +1,80 @@ --- source: crates/ruff_linter/src/rules/ruff/mod.rs --- -RUF011.py:12:2: RUF011 Dictionary comprehension uses static key: `"key"` +RUF011.py:15:2: RUF011 Dictionary comprehension uses static key: `"key"` | -11 | # Errors -12 | {"key": value.upper() for value in data} +14 | # Errors +15 | {"key": value.upper() for value in data} | ^^^^^ RUF011 -13 | {True: value.upper() for value in data} -14 | {0: value.upper() for value in data} +16 | {True: value.upper() for value in data} +17 | {0: value.upper() for value in data} | -RUF011.py:13:2: RUF011 Dictionary comprehension uses static key: `True` +RUF011.py:16:2: RUF011 Dictionary comprehension uses static key: `True` | -11 | # Errors -12 | {"key": value.upper() for value in data} -13 | {True: value.upper() for value in data} +14 | # Errors +15 | {"key": value.upper() for value in data} +16 | {True: value.upper() for value in data} | ^^^^ RUF011 -14 | {0: value.upper() for value in data} -15 | {(1, "a"): value.upper() for value in data} # Constant tuple +17 | {0: value.upper() for value in data} +18 | {(1, "a"): value.upper() for value in data} # Constant tuple | -RUF011.py:14:2: RUF011 Dictionary comprehension uses static key: `0` +RUF011.py:17:2: RUF011 Dictionary comprehension uses static key: `0` | -12 | {"key": value.upper() for value in data} -13 | {True: value.upper() for value in data} -14 | {0: value.upper() for value in data} +15 | {"key": value.upper() for value in data} +16 | {True: value.upper() for value in data} +17 | {0: value.upper() for value in data} | ^ RUF011 -15 | {(1, "a"): value.upper() for value in data} # Constant tuple -16 | {constant: value.upper() for value in data} +18 | {(1, "a"): value.upper() for value in data} # Constant tuple +19 | {constant: value.upper() for value in data} | -RUF011.py:15:2: RUF011 Dictionary comprehension uses static key: `(1, "a")` +RUF011.py:18:2: RUF011 Dictionary comprehension uses static key: `(1, "a")` | -13 | {True: value.upper() for value in data} -14 | {0: value.upper() for value in data} -15 | {(1, "a"): value.upper() for value in data} # Constant tuple +16 | {True: value.upper() for value in data} +17 | {0: value.upper() for value in data} +18 | {(1, "a"): value.upper() for value in data} # Constant tuple | ^^^^^^^^ RUF011 -16 | {constant: value.upper() for value in data} -17 | {constant + constant: value.upper() for value in data} +19 | {constant: value.upper() for value in data} +20 | {constant + constant: value.upper() for value in data} | -RUF011.py:16:2: RUF011 Dictionary comprehension uses static key: `constant` +RUF011.py:19:2: RUF011 Dictionary comprehension uses static key: `constant` | -14 | {0: value.upper() for value in data} -15 | {(1, "a"): value.upper() for value in data} # Constant tuple -16 | {constant: value.upper() for value in data} +17 | {0: value.upper() for value in data} +18 | {(1, "a"): value.upper() for value in data} # Constant tuple +19 | {constant: value.upper() for value in data} | ^^^^^^^^ RUF011 -17 | {constant + constant: value.upper() for value in data} +20 | {constant + constant: value.upper() for value in data} +21 | {constant.attribute: value.upper() for value in data} | -RUF011.py:17:2: RUF011 Dictionary comprehension uses static key: `constant + constant` +RUF011.py:20:2: RUF011 Dictionary comprehension uses static key: `constant + constant` | -15 | {(1, "a"): value.upper() for value in data} # Constant tuple -16 | {constant: value.upper() for value in data} -17 | {constant + constant: value.upper() for value in data} +18 | {(1, "a"): value.upper() for value in data} # Constant tuple +19 | {constant: value.upper() for value in data} +20 | {constant + constant: value.upper() for value in data} | ^^^^^^^^^^^^^^^^^^^ RUF011 +21 | {constant.attribute: value.upper() for value in data} +22 | {constant[0]: value.upper() for value in data} + | + +RUF011.py:21:2: RUF011 Dictionary comprehension uses static key: `constant.attribute` + | +19 | {constant: value.upper() for value in data} +20 | {constant + constant: value.upper() for value in data} +21 | {constant.attribute: value.upper() for value in data} + | ^^^^^^^^^^^^^^^^^^ RUF011 +22 | {constant[0]: value.upper() for value in data} + | + +RUF011.py:22:2: RUF011 Dictionary comprehension uses static key: `constant[0]` + | +20 | {constant + constant: value.upper() for value in data} +21 | {constant.attribute: value.upper() for value in data} +22 | {constant[0]: value.upper() for value in data} + | ^^^^^^^^^^^ RUF011 |