38
38
from ..utils .ast import (
39
39
Token ,
40
40
is_non_variable_token ,
41
+ range_from_node ,
41
42
range_from_token_or_node ,
42
43
tokenize_variables ,
43
44
)
@@ -219,12 +220,20 @@ async def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
219
220
220
221
221
222
class 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 ]:
224
224
self .source = source
225
+ self .position = position
226
+
227
+ self ._results : List [VariableDefinition ] = []
228
+
225
229
await self .visit (model )
230
+
226
231
return self ._results
227
232
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
+
228
237
async def visit_KeywordName (self , node : ast .AST ) -> None : # noqa: N802
229
238
from robot .parsing .lexer .tokens import Token as RobotToken
230
239
from robot .parsing .model .statements import KeywordName
@@ -343,6 +352,39 @@ async def visit_KeywordCall(self, node: ast.AST) -> None: # noqa: N802
343
352
except VariableError :
344
353
pass
345
354
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
+
346
388
347
389
class ImportVisitor (AsyncVisitor ):
348
390
async def get (self , source : str , model : ast .AST ) -> List [Import ]:
@@ -953,7 +995,9 @@ def get_builtin_variables(cls) -> List[BuiltInVariableDefinition]:
953
995
954
996
return cls ._builtin_variables
955
997
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 ]:
957
1001
from robot .parsing .model .blocks import Keyword , TestCase
958
1002
959
1003
await self .ensure_initialized ()
@@ -962,7 +1006,7 @@ async def get_variables(self, nodes: Optional[List[ast.AST]] = None) -> Dict[Var
962
1006
963
1007
async for var in async_chain (
964
1008
* [
965
- await BlockVariableVisitor ().get (self .source , n )
1009
+ await BlockVariableVisitor ().get (self .source , n , position )
966
1010
for n in nodes or []
967
1011
if isinstance (n , (Keyword , TestCase ))
968
1012
],
@@ -975,8 +1019,10 @@ async def get_variables(self, nodes: Optional[List[ast.AST]] = None) -> Dict[Var
975
1019
976
1020
return result
977
1021
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 )
980
1026
981
1027
async def _import_imports (self , imports : Iterable [Import ], base_dir : str , * , top_level : bool = False ) -> None :
982
1028
async def _import (value : Import ) -> Optional [LibraryEntry ]:
0 commit comments