From 47f775425aa55706512a0500ef50c2008455ea4c Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Fri, 12 Jan 2024 13:20:11 -0500 Subject: [PATCH] Avoid treating named expressions as static keys --- .../resources/test/fixtures/ruff/RUF011.py | 2 + .../rules/static_key_dict_comprehension.rs | 6 +- ..._rules__ruff__tests__RUF011_RUF011.py.snap | 98 ++++++++++--------- 3 files changed, 60 insertions(+), 46 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py b/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py index dec601bd685aaf..dbc18ab1b11e0f 100644 --- a/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py +++ b/crates/ruff_linter/resources/test/fixtures/ruff/RUF011.py @@ -10,6 +10,7 @@ {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} +{local_id: token for token in tokens if (local_id := _extract_local_id(token)) is not None} # Errors {"key": value.upper() for value in data} @@ -20,3 +21,4 @@ {constant + constant: value.upper() for value in data} {constant.attribute: value.upper() for value in data} {constant[0]: value.upper() for value in data} +{tokens: token for token in tokens} 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 cdcc672105428a..301b82e9d74134 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 @@ -53,7 +53,7 @@ pub(crate) fn static_key_dict_comprehension(checker: &mut Checker, dict_comp: &a let names = { let mut visitor = NameFinder::default(); for generator in &dict_comp.generators { - visitor.visit_expr(&generator.target); + visitor.visit_comprehension(&generator); } visitor.names }; @@ -73,7 +73,9 @@ pub(crate) fn static_key_dict_comprehension(checker: &mut Checker, dict_comp: &a 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::Name(ast::ExprName { id, .. }) => !names + .get(id.as_str()) + .is_some_and(|name| name.ctx.is_store()), Expr::Attribute(ast::ExprAttribute { value, .. }) => is_constant(value, names), Expr::Subscript(ast::ExprSubscript { value, slice, .. }) => { is_constant(value, names) && is_constant(slice, 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 f7a7667d1e1310..10f044793e7547 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,80 +1,90 @@ --- source: crates/ruff_linter/src/rules/ruff/mod.rs --- -RUF011.py:15:2: RUF011 Dictionary comprehension uses static key: `"key"` +RUF011.py:16:2: RUF011 Dictionary comprehension uses static key: `"key"` | -14 | # Errors -15 | {"key": value.upper() for value in data} +15 | # Errors +16 | {"key": value.upper() for value in data} | ^^^^^ RUF011 -16 | {True: value.upper() for value in data} -17 | {0: value.upper() for value in data} +17 | {True: value.upper() for value in data} +18 | {0: value.upper() for value in data} | -RUF011.py:16:2: RUF011 Dictionary comprehension uses static key: `True` +RUF011.py:17:2: RUF011 Dictionary comprehension uses static key: `True` | -14 | # Errors -15 | {"key": value.upper() for value in data} -16 | {True: value.upper() for value in data} +15 | # Errors +16 | {"key": value.upper() for value in data} +17 | {True: value.upper() for value in data} | ^^^^ RUF011 -17 | {0: value.upper() for value in data} -18 | {(1, "a"): value.upper() for value in data} # Constant tuple +18 | {0: value.upper() for value in data} +19 | {(1, "a"): value.upper() for value in data} # Constant tuple | -RUF011.py:17:2: RUF011 Dictionary comprehension uses static key: `0` +RUF011.py:18:2: RUF011 Dictionary comprehension uses static key: `0` | -15 | {"key": value.upper() for value in data} -16 | {True: value.upper() for value in data} -17 | {0: value.upper() for value in data} +16 | {"key": value.upper() for value in data} +17 | {True: value.upper() for value in data} +18 | {0: value.upper() for value in data} | ^ RUF011 -18 | {(1, "a"): value.upper() for value in data} # Constant tuple -19 | {constant: value.upper() for value in data} +19 | {(1, "a"): value.upper() for value in data} # Constant tuple +20 | {constant: value.upper() for value in data} | -RUF011.py:18:2: RUF011 Dictionary comprehension uses static key: `(1, "a")` +RUF011.py:19:2: RUF011 Dictionary comprehension uses static key: `(1, "a")` | -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 +17 | {True: value.upper() for value in data} +18 | {0: value.upper() for value in data} +19 | {(1, "a"): value.upper() for value in data} # Constant tuple | ^^^^^^^^ RUF011 -19 | {constant: value.upper() for value in data} -20 | {constant + constant: value.upper() for value in data} +20 | {constant: value.upper() for value in data} +21 | {constant + constant: value.upper() for value in data} | -RUF011.py:19:2: RUF011 Dictionary comprehension uses static key: `constant` +RUF011.py:20:2: RUF011 Dictionary comprehension uses static key: `constant` | -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} +18 | {0: value.upper() for value in data} +19 | {(1, "a"): value.upper() for value in data} # Constant tuple +20 | {constant: value.upper() for value in data} | ^^^^^^^^ RUF011 -20 | {constant + constant: value.upper() for value in data} -21 | {constant.attribute: value.upper() for value in data} +21 | {constant + constant: value.upper() for value in data} +22 | {constant.attribute: value.upper() for value in data} | -RUF011.py:20:2: RUF011 Dictionary comprehension uses static key: `constant + constant` +RUF011.py:21:2: RUF011 Dictionary comprehension uses static key: `constant + constant` | -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} +19 | {(1, "a"): value.upper() for value in data} # Constant tuple +20 | {constant: value.upper() for value in data} +21 | {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} +22 | {constant.attribute: value.upper() for value in data} +23 | {constant[0]: value.upper() for value in data} | -RUF011.py:21:2: RUF011 Dictionary comprehension uses static key: `constant.attribute` +RUF011.py:22: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} +20 | {constant: value.upper() for value in data} +21 | {constant + constant: value.upper() for value in data} +22 | {constant.attribute: value.upper() for value in data} | ^^^^^^^^^^^^^^^^^^ RUF011 -22 | {constant[0]: value.upper() for value in data} +23 | {constant[0]: value.upper() for value in data} +24 | {tokens: token for token in tokens} | -RUF011.py:22:2: RUF011 Dictionary comprehension uses static key: `constant[0]` +RUF011.py:23: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} +21 | {constant + constant: value.upper() for value in data} +22 | {constant.attribute: value.upper() for value in data} +23 | {constant[0]: value.upper() for value in data} | ^^^^^^^^^^^ RUF011 +24 | {tokens: token for token in tokens} + | + +RUF011.py:24:2: RUF011 Dictionary comprehension uses static key: `tokens` + | +22 | {constant.attribute: value.upper() for value in data} +23 | {constant[0]: value.upper() for value in data} +24 | {tokens: token for token in tokens} + | ^^^^^^ RUF011 |