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

Code before:
                {
                    class_def
                        .body
                        .iter()
                        .filter_map(|stmt| {
                            stmt.as_ann_assign_stmt()
                                .and_then(|ann_assign| ann_assign.target.as_name_expr())
                                .map(|name| name.id.as_str())
                        })
                        .collect()
                } else if let Some(method_def) = class_def
                    .body
                    .iter()
                    .filter_map(|stmt| stmt.as_function_def_stmt())
                    .find(|func_def| {
                        func_def.name.as_str() == "__init__"
                            || func_def.name.as_str() == "__call__"
                    })
                {
                    // Skip `self` parameter.
                    //
                    // For classes used as FastAPI dependencies, the parameters
                    // can come from either `__init__` (when the class itself is
                    // passed to `Depends`) or `__call__` (when an instance of
                    // the class is passed to `Depends`). We check `__init__`
                    // first, falling back to `__call__`.
                    non_posonly_non_variadic_parameters(method_def)
                        .skip(1)
                        .map(|param| param.name().as_str())
                        .collect()
                } else {
                    return Some(Self::Unknown);
                };

                Some(Self::Class(parameter_names))
            }
            _ => Some(Self::Unknown),
        }
    }
}

fn depends_arguments<'a>(expr: &'a Expr, semantic: &SemanticModel) -> Option<&'a Arguments> {
    let Expr::Call(ExprCall {
        func, arguments, ..
    }) = expr
    else {
        return None;
    };

    if !is_fastapi_depends(func.as_ref(), semantic) {
        return None;

Review comment (suggestion):
```suggestion
                    // Skip `self` parameter
```

Let's just put back the old comment. I don't think this is fully accurate, specifically the precedence comment about checking `__init__` first.

Code after:

                Some(Self::Function(parameter_names))
            }
            BindingKind::ClassDefinition(scope_id) => {
                Self::class_params_from_method(semantic, scope_id, "__init__")
            }
            _ => Some(Self::Unknown),
        }
    }

    /// Resolve a dependency that is a class instance (e.g. `Depends(Query())`).
    ///
    /// FastAPI calls the instance, so the parameters come from `__call__`.
    fn from_dependency_instance(
        name: &'a ast::ExprName,
        semantic: &SemanticModel<'a>,
    ) -> Option<Self> {
        let Some(binding) = semantic.only_binding(name).map(|id| semantic.binding(id)) else {
            return Some(Self::Unknown);
        };

        match binding.kind {
            BindingKind::ClassDefinition(scope_id) => {
                Self::class_params_from_method(semantic, scope_id, "__call__")
            }
            _ => Some(Self::Unknown),
        }
    }

    /// Extract parameters from a specific method (`__init__` or `__call__`) of a class.
    fn class_params_from_method(
        semantic: &SemanticModel<'a>,
        scope_id: ruff_python_semantic::ScopeId,
        method_name: &str,
    ) -> Option<Self> {
        let scope = &semantic.scopes[scope_id];

        let ScopeKind::Class(class_def) = scope.kind else {
            return Some(Self::Unknown);
        };

        let parameter_names = if class_def
            .bases()
            .iter()
            .any(|expr| is_pydantic_base_model(expr, semantic))
        {
            class_def
                .body
                .iter()
                .filter_map(|stmt| {
                    stmt.as_ann_assign_stmt()