@@ -334,6 +334,8 @@ impl AnalyzerService {
334334
335335 let signature = Self :: extract_signature ( def_node, source) ;
336336
337+ let parent_scope = Self :: extract_parent_scope ( def_node, source) ;
338+
337339 if let Some ( kind) = kind {
338340 symbols. push ( CodeSymbol {
339341 kind,
@@ -345,6 +347,7 @@ impl AnalyzerService {
345347 is_added,
346348 is_whitespace_only : None ,
347349 signature,
350+ parent_scope,
348351 } ) ;
349352 }
350353 }
@@ -498,6 +501,40 @@ impl AnalyzerService {
498501 }
499502 }
500503
504+ /// Walk up the AST to find the enclosing scope (impl, class, trait).
505+ /// Skips intermediate wrapper nodes like `declaration_list`, `class_body`, etc.
506+ fn extract_parent_scope ( node : tree_sitter:: Node , source : & str ) -> Option < String > {
507+ let mut current = node. parent ( ) ;
508+ while let Some ( parent) = current {
509+ match parent. kind ( ) {
510+ "impl_item" | "impl_block" => {
511+ // Rust: impl Type { fn method() }
512+ return parent
513+ . child_by_field_name ( "type" )
514+ . and_then ( |t| t. utf8_text ( source. as_bytes ( ) ) . ok ( ) )
515+ . map ( |s| s. to_string ( ) ) ;
516+ }
517+ "class_declaration" | "class_definition" | "class" | "class_specifier" => {
518+ // Most languages: class Foo { method() }
519+ return parent
520+ . child_by_field_name ( "name" )
521+ . and_then ( |n| n. utf8_text ( source. as_bytes ( ) ) . ok ( ) )
522+ . map ( |s| s. to_string ( ) ) ;
523+ }
524+ "trait_item" => {
525+ return parent
526+ . child_by_field_name ( "name" )
527+ . and_then ( |n| n. utf8_text ( source. as_bytes ( ) ) . ok ( ) )
528+ . map ( |s| s. to_string ( ) ) ;
529+ }
530+ _ => {
531+ current = parent. parent ( ) ;
532+ }
533+ }
534+ }
535+ None
536+ }
537+
501538 /// Check if a C# node has a `modifier` child with text "public"
502539 fn has_csharp_public_modifier ( node : tree_sitter:: Node ) -> bool {
503540 let child_count = node. child_count ( ) ;
0 commit comments