MCPcopy Create free account
hub / github.com/PHPantom-dev/phpantom_lsp / resolve_in_method_body

Function resolve_in_method_body

src/completion/variable/forward_walk.rs:2279–2410  ·  view source on GitHub ↗

Resolve the target variable from a method body using the forward walker. This is the main entry point called from `resolve_variable_in_members`. It seeds the scope with parameter types and walks the method body forward to the cursor.

(
    var_name: &str,
    parameters: impl Iterator<Item = &'b FunctionLikeParameter<'b>>,
    body_statements: impl Iterator<Item = &'b Statement<'b>>,
    method_span_start: u32,
    method_ctx: Opt

Source from the content-addressed store, hash-verified

2277/// It seeds the scope with parameter types and walks the method body
2278/// forward to the cursor.
2279pub(crate) fn resolve_in_method_body<'b>(
2280 var_name: &str,
2281 parameters: impl Iterator<Item = &'b FunctionLikeParameter<'b>>,
2282 body_statements: impl Iterator<Item = &'b Statement<'b>>,
2283 method_span_start: u32,
2284 method_ctx: Option<(&str, bool)>,
2285 is_static: bool,
2286 ctx: &ForwardWalkCtx<'_>,
2287) -> Option<Vec<ResolvedType>> {
2288 // Collect iterators up front so they can be reused across the cache
2289 // populate path and the standard walk path without ownership issues.
2290 let params_vec: Vec<&'b FunctionLikeParameter<'b>> = parameters.collect();
2291 let stmts_vec: Vec<&'b Statement<'b>> = body_statements.collect();
2292
2293 // ── Hover scope cache ────────────────────────────────────────────────
2294 // The hover scope cache records snapshots at each statement's START
2295 // offset (before the statement is processed). This works well for
2296 // member-access resolution within a statement (which needs the scope
2297 // from before the statement), but returns the wrong type for variable
2298 // hover on the LHS of an assignment: hovering `$x` in `$x = new Foo()`
2299 // should show the post-assignment type (`Foo`), not the pre-assignment
2300 // type. Detecting all edge cases (nudged offsets, nested blocks,
2301 // closures) is fragile, so variable resolution always uses the
2302 // standard walk which processes statements up to the cursor and
2303 // returns the correct post-assignment scope.
2304 //
2305 // The cache IS still populated here (if not yet present) so that
2306 // other consumers (diagnostics member-access lookups via
2307 // `lookup_diagnostic_scope`) benefit from it.
2308 if !is_diagnostic_scope_active()
2309 && is_hover_scope_cache_active()
2310 && !hover_scope_has_method(method_span_start)
2311 {
2312 // Activate a temporary diagnostic scope so that walk_body_forward
2313 // records snapshots at every statement boundary.
2314 let _diag_guard = with_diagnostic_scope_cache();
2315
2316 // Build a full-walk context (cursor at u32::MAX = walk entire body).
2317 let full_ctx = ForwardWalkCtx {
2318 cursor_offset: u32::MAX,
2319 current_class: ctx.current_class,
2320 all_classes: ctx.all_classes,
2321 content: ctx.content,
2322 class_loader: ctx.class_loader,
2323 loaders: ctx.loaders,
2324 resolved_class_cache: ctx.resolved_class_cache,
2325 enclosing_return_type: ctx.enclosing_return_type.clone(),
2326 top_level_scope: ctx.top_level_scope.clone(),
2327 };
2328
2329 let mut scope = ScopeState::new();
2330 if !is_static {
2331 seed_this(&mut scope, ctx.current_class);
2332 }
2333 let method_name = method_ctx.map(|(n, _)| n);
2334 let has_scope_attr = method_ctx.is_some_and(|(_, s)| s);
2335
2336 seed_params(

Callers 1

Calls 15

hover_scope_has_methodFunction · 0.85
seed_thisFunction · 0.85
seed_paramsFunction · 0.85
record_scope_snapshotFunction · 0.85
walk_body_forwardFunction · 0.85

Tested by

no test coverage detected