3838from ..utils .ast import (
3939 Token ,
4040 is_non_variable_token ,
41+ range_from_node ,
4142 range_from_token_or_node ,
4243 tokenize_variables ,
4344)
@@ -219,12 +220,20 @@ async def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
219220
220221
221222class BlockVariableVisitor (AsyncVisitor ):
222- async def get (self , source : str , model : ast .AST ) -> List [VariableDefinition ]:
223- self ._results : List [VariableDefinition ] = []
223+ async def get (self , source : str , model : ast .AST , position : Optional [Position ] = None ) -> List [VariableDefinition ]:
224224 self .source = source
225+ self .position = position
226+
227+ self ._results : List [VariableDefinition ] = []
228+
225229 await self .visit (model )
230+
226231 return self ._results
227232
233+ async def visit (self , node : ast .AST ) -> None :
234+ if self .position is None or self .position >= range_from_node (node ).start :
235+ return await super ().visit (node )
236+
228237 async def visit_KeywordName (self , node : ast .AST ) -> None : # noqa: N802
229238 from robot .parsing .lexer .tokens import Token as RobotToken
230239 from robot .parsing .model .statements import KeywordName
@@ -343,6 +352,39 @@ async def visit_KeywordCall(self, node: ast.AST) -> None: # noqa: N802
343352 except VariableError :
344353 pass
345354
355+ async def visit_ForHeader (self , node : ast .AST ) -> None : # noqa: N802
356+ from robot .errors import VariableError
357+ from robot .parsing .lexer .tokens import Token as RobotToken
358+ from robot .parsing .model .statements import ForHeader
359+ from robot .variables .search import contains_variable
360+
361+ try :
362+ n = cast (ForHeader , node )
363+ variables = n .get_tokens (RobotToken .VARIABLE )
364+ for variable in variables :
365+ if variable is not None and variable .value and contains_variable (variable .value ):
366+ self ._results .append (
367+ VariableDefinition (
368+ name = variable .value ,
369+ name_token = variable ,
370+ line_no = node .lineno ,
371+ col_offset = node .col_offset ,
372+ end_line_no = node .end_lineno
373+ if node .end_lineno is not None
374+ else variable .lineno
375+ if variable .lineno is not None
376+ else - 1 ,
377+ end_col_offset = node .end_col_offset
378+ if node .end_col_offset is not None
379+ else variable .end_col_offset
380+ if variable .end_col_offset is not None
381+ else - 1 ,
382+ source = self .source ,
383+ )
384+ )
385+ except VariableError :
386+ pass
387+
346388
347389class ImportVisitor (AsyncVisitor ):
348390 async def get (self , source : str , model : ast .AST ) -> List [Import ]:
@@ -953,7 +995,9 @@ def get_builtin_variables(cls) -> List[BuiltInVariableDefinition]:
953995
954996 return cls ._builtin_variables
955997
956- async def get_variables (self , nodes : Optional [List [ast .AST ]] = None ) -> Dict [VariableMatcher , VariableDefinition ]:
998+ async def get_variables (
999+ self , nodes : Optional [List [ast .AST ]] = None , position : Optional [Position ] = None
1000+ ) -> Dict [VariableMatcher , VariableDefinition ]:
9571001 from robot .parsing .model .blocks import Keyword , TestCase
9581002
9591003 await self .ensure_initialized ()
@@ -962,7 +1006,7 @@ async def get_variables(self, nodes: Optional[List[ast.AST]] = None) -> Dict[Var
9621006
9631007 async for var in async_chain (
9641008 * [
965- await BlockVariableVisitor ().get (self .source , n )
1009+ await BlockVariableVisitor ().get (self .source , n , position )
9661010 for n in nodes or []
9671011 if isinstance (n , (Keyword , TestCase ))
9681012 ],
@@ -975,8 +1019,10 @@ async def get_variables(self, nodes: Optional[List[ast.AST]] = None) -> Dict[Var
9751019
9761020 return result
9771021
978- async def find_variable (self , name : str , nodes : Optional [List [ast .AST ]]) -> Optional [VariableDefinition ]:
979- return (await self .get_variables (nodes )).get (VariableMatcher (name ), None )
1022+ async def find_variable (
1023+ self , name : str , nodes : Optional [List [ast .AST ]], position : Optional [Position ] = None
1024+ ) -> Optional [VariableDefinition ]:
1025+ return (await self .get_variables (nodes , position )).get (VariableMatcher (name ), None )
9801026
9811027 async def _import_imports (self , imports : Iterable [Import ], base_dir : str , * , top_level : bool = False ) -> None :
9821028 async def _import (value : Import ) -> Optional [LibraryEntry ]:
0 commit comments