Seed the scope with types from function/method parameters. For each parameter, resolves its type from: 1. The native type hint 2. The `@param` docblock annotation (which may be more specific) 3. The merged class info (from parent/interface inheritance) 4. Eloquent scope Builder enrichment
(
scope: &mut ScopeState,
parameters: impl Iterator<Item = &'b FunctionLikeParameter<'b>>,
method_span_start: u32,
method_name: Option<&str>,
has_scope_attr: bool,
ctx: &Forwar
| 2619 | /// 3. The merged class info (from parent/interface inheritance) |
| 2620 | /// 4. Eloquent scope Builder enrichment |
| 2621 | fn seed_params<'b>( |
| 2622 | scope: &mut ScopeState, |
| 2623 | parameters: impl Iterator<Item = &'b FunctionLikeParameter<'b>>, |
| 2624 | method_span_start: u32, |
| 2625 | method_name: Option<&str>, |
| 2626 | has_scope_attr: bool, |
| 2627 | ctx: &ForwardWalkCtx<'_>, |
| 2628 | ) { |
| 2629 | for param in parameters { |
| 2630 | let pname = param.variable.name.to_string(); |
| 2631 | let is_variadic = param.ellipsis.is_some(); |
| 2632 | let native_type = param.hint.as_ref().map(|h| extract_hint_type(h)); |
| 2633 | |
| 2634 | // For promoted constructor properties, check for an inline |
| 2635 | // `/** @var Type */` docblock on the parameter itself. The |
| 2636 | // property parser already uses this for the property's type_hint, |
| 2637 | // but the forward walker resolves parameter variables via |
| 2638 | // `resolve_param_type` which only checks `@param` tags on the |
| 2639 | // method docblock. When an inline `@var` is present, resolve it |
| 2640 | // directly and seed the scope, bypassing `resolve_param_type` |
| 2641 | // (which would otherwise fall back to the merged class's native |
| 2642 | // parameter type, losing the docblock refinement). |
| 2643 | if param.is_promoted_property() { |
| 2644 | let param_offset = param.span().start.offset as usize; |
| 2645 | if let Some((var_type, _name)) = |
| 2646 | crate::docblock::find_inline_var_docblock(ctx.content, param_offset) |
| 2647 | { |
| 2648 | let var_type = crate::util::resolve_php_type_names(&var_type, ctx.class_loader); |
| 2649 | let effective = crate::docblock::resolve_effective_type_typed( |
| 2650 | native_type.as_ref(), |
| 2651 | Some(&var_type), |
| 2652 | ) |
| 2653 | .unwrap_or(var_type); |
| 2654 | |
| 2655 | let resolved = crate::completion::type_resolution::type_hint_to_classes_typed( |
| 2656 | &effective, |
| 2657 | &ctx.current_class.name, |
| 2658 | ctx.all_classes, |
| 2659 | ctx.class_loader, |
| 2660 | ); |
| 2661 | |
| 2662 | let results = if !resolved.is_empty() { |
| 2663 | ResolvedType::from_classes_with_hint(resolved, effective) |
| 2664 | } else { |
| 2665 | vec![ResolvedType::from_type_string(effective)] |
| 2666 | }; |
| 2667 | |
| 2668 | scope.seed(&pname, results); |
| 2669 | continue; |
| 2670 | } |
| 2671 | } |
| 2672 | |
| 2673 | let param_results = resolve_param_type( |
| 2674 | &pname, |
| 2675 | native_type.as_ref(), |
| 2676 | is_variadic, |
| 2677 | method_span_start, |
| 2678 | method_name, |
no test coverage detected