@@ -79,19 +79,40 @@ def _find_identifier(self,
7979 or None if not found
8080 """
8181 query_info_key = marker .type
82+ identifier_name = marker .value
8283 match marker .type :
8384 case 'method' :
8485 query_info_key = 'function'
8586 try :
86- candidates = (
87- self .language .query (self .query_info [query_info_key ].format (name = marker .value ))
87+ all_restrictions : list [ParentRestriction ] = [parent_restriction ]
88+ # Extract parent name if using dot notation
89+ if '.' in identifier_name :
90+ * parent_parts , identifier_name = identifier_name .split ('.' )
91+ all_restrictions .append ("." + '.' .join (reversed (parent_parts )))
92+
93+ # Get all node candidates first
94+ candidate_nodes = (
95+ self .language .query (self .query_info [query_info_key ].format (name = identifier_name ))
8896 .captures (self .tree .root_node )
8997 )
90- # TODO discard candidates that aren't of type 'marker.type'
91- candidates : list [IdentifierBoundaries ] = [ib for ib in capture2identifier_boundaries (
92- candidates ,
93- self .lines
94- ) if ib .match_parent (parent_restriction )]
98+ if not candidate_nodes :
99+ return None
100+
101+ # Convert captures to boundaries and filter by parent
102+ candidates : list [IdentifierBoundaries ] = []
103+ for ib in capture2identifier_boundaries (candidate_nodes , self .lines ):
104+ # For methods, verify the immediate parent is a class
105+ if marker .type == 'method' :
106+ if not ib .parents or not ib .parents [0 ].parent_type .startswith ('class' ):
107+ continue
108+ # Check parent restriction (e.g., specific class name)
109+ candidate_matched_all_restrictions = True
110+ for pr in all_restrictions :
111+ if not ib .match_parent (pr ):
112+ candidate_matched_all_restrictions = False
113+ break
114+ if candidate_matched_all_restrictions :
115+ candidates .append (ib )
95116 except Exception as e :
96117 raise ValueError (f"Unable to capture nodes for { marker } : { e } " ) from e
97118
@@ -100,13 +121,13 @@ def _find_identifier(self,
100121 return None
101122 if candidate_count > 1 and marker .offset is None :
102123 raise ValueError (
103- f"The { marker .type } identifier named `{ marker . value } ` is ambiguous (found { candidate_count } matches). "
124+ f"The { marker .type } identifier named `{ identifier_name } ` is ambiguous (found { candidate_count } matches). "
104125 f"Choose an `OFFSET` between 0 and { candidate_count - 1 } to determine how many to skip. "
105- f"Example to reference the *last* `{ marker . value } `: `OFFSET { candidate_count - 1 } `"
126+ f"Example to reference the *last* `{ identifier_name } `: `OFFSET { candidate_count - 1 } `"
106127 )
107128 if marker .offset and marker .offset >= candidate_count :
108129 raise ValueError (
109- f"There are only { candidate_count } { marker .type } identifiers named `{ marker . value } `, "
130+ f"There are only { candidate_count } { marker .type } identifiers named `{ identifier_name } `, "
110131 f"but 'OFFSET' was set to { marker .offset } (you can skip at most { candidate_count - 1 } of those)"
111132 )
112133 candidates .sort (key = lambda x : x .whole .start )
0 commit comments