Bind a foreach key variable.
(
key_expr: &'b Expression<'b>,
iter_type: &Option<PhpType>,
scope: &mut ScopeState,
ctx: &ForwardWalkCtx<'_>,
)
| 6866 | |
| 6867 | /// Bind a foreach key variable. |
| 6868 | fn bind_foreach_key<'b>( |
| 6869 | key_expr: &'b Expression<'b>, |
| 6870 | iter_type: &Option<PhpType>, |
| 6871 | scope: &mut ScopeState, |
| 6872 | ctx: &ForwardWalkCtx<'_>, |
| 6873 | ) { |
| 6874 | if let Expression::Variable(Variable::Direct(dv)) = key_expr { |
| 6875 | let var_name = dv.name.to_string(); |
| 6876 | if let Some(it) = iter_type { |
| 6877 | let key_php_type = it.extract_key_type(false); |
| 6878 | if let Some(kt) = key_php_type { |
| 6879 | let resolved = crate::completion::type_resolution::type_hint_to_classes_typed( |
| 6880 | kt, |
| 6881 | &ctx.current_class.name, |
| 6882 | ctx.all_classes, |
| 6883 | ctx.class_loader, |
| 6884 | ); |
| 6885 | if !resolved.is_empty() { |
| 6886 | scope.set( |
| 6887 | &var_name, |
| 6888 | ResolvedType::from_classes_with_hint(resolved, kt.clone()), |
| 6889 | ); |
| 6890 | } else { |
| 6891 | scope.set(&var_name, vec![ResolvedType::from_type_string(kt.clone())]); |
| 6892 | } |
| 6893 | return; |
| 6894 | } |
| 6895 | } |
| 6896 | // Default: key is int|string. |
| 6897 | scope.set( |
| 6898 | &var_name, |
| 6899 | vec![ResolvedType::from_type_string(PhpType::Union(vec![ |
| 6900 | PhpType::int(), |
| 6901 | PhpType::string(), |
| 6902 | ]))], |
| 6903 | ); |
| 6904 | } |
| 6905 | } |
| 6906 | |
| 6907 | /// Process a `while` loop. |
| 6908 | /// |
no test coverage detected