Repository: astral-sh/ruff
File: crates/ruff_linter/src/rules/pylint/rules/dict_index_missing_items.rs (Rust)

Code before:

/// PLC0206
pub(crate) fn dict_index_missing_items(checker: &Checker, stmt_for: &ast::StmtFor) {
    let ast::StmtFor {
        target, iter, body, ..
    } = stmt_for;

    // Extract the name of the iteration object (e.g., `obj` in `for key in obj:`).
    let Some(dict_name) = extract_dict_name(iter) else {
        return;
    };

    // Determine if the right-hand side is a dictionary literal (i.e. `for key in (dict := {"a": 1}):`).
    let is_dict_literal = matches!(
        ResolvedPythonType::from(&**iter),
        ResolvedPythonType::Atom(PythonType::Dict),
    );

    if !is_dict_literal && !is_inferred_dict(dict_name, checker.semantic()) {
        return;
    }

    let range = if is_plc0206_narrower_range_enabled(checker.settings()) {
        TextRange::new(target.start(), iter.end())
    } else {
        stmt_for.range()
    };

    SubscriptVisitor::new(target, dict_name, checker, range).visit_body(body);
}

/// A visitor to detect subscript operations on a target dictionary.
struct SubscriptVisitor<'a, 'b> {
    /// The target of the for loop (e.g., `key` in `for key in obj:`).
    target: &'a Expr,
    /// The name of the iterated object (e.g., `obj` in `for key in obj:`).
    dict_name: &'a ast::ExprName,
    /// The range to use for the primary diagnostic.
    range: TextRange,
    /// The [`Checker`] used to emit diagnostics.
    checker: &'a Checker<'b>,
    /// The [`DiagnosticGuard`] used for attaching additional annotations for each subscript use in
    /// preview.
    ///
    /// The guard is initially `None` and then set to `Some` when the first subscript operation is
    /// found.
    guard: Option<DiagnosticGuard<'a, 'b>>,
}

impl<'a, 'b> SubscriptVisitor<'a, 'b> {
    fn new(

Review comment (suggestion):
I suggest moving this into `SubscriptVisitor::new`, as it seems the better place once we remove the preview gating.

Code after:
        "Extracting value from dictionary without calling `.items()`".to_string()
    }

    fn fix_title(&self) -> Option<String> {
        let Self { key, dict } = self;
        Some(format!("Use `for {key}, value in {dict}.items()` instead"))
    }
}

/// PLC0206
pub(crate) fn dict_index_missing_items(checker: &Checker, stmt_for: &StmtFor) {
    let StmtFor { iter, body, .. } = stmt_for;

    // Extract the name of the iteration object (e.g., `obj` in `for key in obj:`).
    let Some(dict_name) = extract_dict_name(iter) else {
        return;
    };

    // Determine if the right-hand side is a dictionary literal (i.e. `for key in (dict := {"a": 1}):`).
    let is_dict_literal = matches!(
        ResolvedPythonType::from(&**iter),
        ResolvedPythonType::Atom(PythonType::Dict),
    );

    if !is_dict_literal && !is_inferred_dict(dict_name, checker.semantic()) {
        return;
    }

    SubscriptVisitor::new(stmt_for, dict_name, checker).visit_body(body);
}

/// A visitor to detect subscript operations on a target dictionary.
struct SubscriptVisitor<'a, 'b> {
    /// The target of the for loop (e.g., `key` in `for key in obj:`).
    target: &'a Expr,
    /// The name of the iterated object (e.g., `obj` in `for key in obj:`).
    dict_name: &'a ast::ExprName,
    /// The range to use for the primary diagnostic.
    range: TextRange,
    /// The [`Checker`] used to emit diagnostics.
    checker: &'a Checker<'b>,
    /// The [`DiagnosticGuard`] used to attach additional annotations for each subscript.
    ///
    /// The guard is initially `None` and then set to `Some` when the first subscript is found.
    guard: Option<DiagnosticGuard<'a, 'b>>,
}

impl<'a, 'b> SubscriptVisitor<'a, 'b> {
    fn new(stmt_for: &'a StmtFor, dict_name: &'a ast::ExprName, checker: &'a Checker<'b>) -> Self {
        let StmtFor { target, iter, .. } = stmt_for;
        let range = {