Walk a top-level statement, recursing into namespace blocks, class declarations, and function bodies.
(
stmt: &Statement<'_>,
ctx: &mut DiagnosticCtx<'_>,
resolver: Option<ByRefResolver<'_>>,
)
| 225 | /// Walk a top-level statement, recursing into namespace blocks, |
| 226 | /// class declarations, and function bodies. |
| 227 | fn collect_from_statement( |
| 228 | stmt: &Statement<'_>, |
| 229 | ctx: &mut DiagnosticCtx<'_>, |
| 230 | resolver: Option<ByRefResolver<'_>>, |
| 231 | ) { |
| 232 | match stmt { |
| 233 | Statement::Function(func) => { |
| 234 | let body_start = func.body.left_brace.start.offset; |
| 235 | let body_end = func.body.right_brace.end.offset; |
| 236 | let scope = collect_function_scope_with_resolver( |
| 237 | &func.parameter_list, |
| 238 | func.body.statements.as_slice(), |
| 239 | body_start, |
| 240 | body_end, |
| 241 | resolver, |
| 242 | ); |
| 243 | check_scope( |
| 244 | &scope, |
| 245 | func.body.statements.as_slice(), |
| 246 | ctx, |
| 247 | false, // not a method |
| 248 | ); |
| 249 | } |
| 250 | Statement::Class(class) => { |
| 251 | let class_name = class.name.value.to_string(); |
| 252 | collect_from_class_members(class.members.as_slice(), ctx, resolver, Some(&class_name)); |
| 253 | } |
| 254 | Statement::Trait(tr) => { |
| 255 | let trait_name = tr.name.value.to_string(); |
| 256 | collect_from_class_members(tr.members.as_slice(), ctx, resolver, Some(&trait_name)); |
| 257 | } |
| 258 | Statement::Enum(en) => { |
| 259 | let enum_name = en.name.value.to_string(); |
| 260 | collect_from_class_members(en.members.as_slice(), ctx, resolver, Some(&enum_name)); |
| 261 | } |
| 262 | Statement::Interface(_) => { |
| 263 | // Interfaces don't have method bodies. |
| 264 | } |
| 265 | Statement::Namespace(ns) => { |
| 266 | for inner in ns.statements().iter() { |
| 267 | collect_from_statement(inner, ctx, resolver); |
| 268 | } |
| 269 | } |
| 270 | // Top-level code (outside any function/class). |
| 271 | _ => { |
| 272 | // We don't diagnose top-level code because PHP's global |
| 273 | // scope has too many implicit variable definitions |
| 274 | // (include/require, extract in bootstrap files, etc.). |
| 275 | } |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | /// Walk class-like members to find method bodies. |
| 280 | fn collect_from_class_members( |
no test coverage detected