@@ -207,15 +207,15 @@ async def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
207
207
208
208
n = cast (Variable , node )
209
209
name = n .get_token (Token .VARIABLE )
210
- if n . name :
210
+ if name is not None :
211
211
self ._results .append (
212
212
VariableDefinition (
213
213
name = n .name ,
214
- name_token = name if name is not None else None ,
215
- line_no = node .lineno ,
216
- col_offset = node .col_offset ,
217
- end_line_no = node . end_lineno if node . end_lineno is not None else - 1 ,
218
- end_col_offset = node .end_col_offset if node . end_col_offset is not None else - 1 ,
214
+ name_token = name ,
215
+ line_no = name .lineno ,
216
+ col_offset = name .col_offset ,
217
+ end_line_no = name . lineno ,
218
+ end_col_offset = name .end_col_offset ,
219
219
source = self .source ,
220
220
)
221
221
)
@@ -226,11 +226,11 @@ async def get(self, source: str, model: ast.AST, position: Optional[Position] =
226
226
self .source = source
227
227
self .position = position
228
228
229
- self ._results : List [ VariableDefinition ] = []
229
+ self ._results : Dict [ str , VariableDefinition ] = {}
230
230
231
231
await self .visit (model )
232
232
233
- return self ._results
233
+ return list ( self ._results . values ())
234
234
235
235
async def visit (self , node : ast .AST ) -> None :
236
236
if self .position is None or self .position >= range_from_node (node ).start :
@@ -245,149 +245,110 @@ async def visit_KeywordName(self, node: ast.AST) -> None: # noqa: N802
245
245
name_token = cast (Token , n .get_token (RobotToken .KEYWORD_NAME ))
246
246
247
247
if name_token is not None and name_token .value :
248
- for a in filter (
248
+ for variable_token in filter (
249
249
lambda e : e .type == RobotToken .VARIABLE ,
250
250
tokenize_variables (name_token , identifiers = "$" , ignore_errors = True ),
251
251
):
252
- if a .value :
252
+ if variable_token .value :
253
253
searcher = VariableSearcher ("$" , ignore_errors = True )
254
- match = searcher .search (a .value )
254
+ match = searcher .search (variable_token .value )
255
255
if match .base is None :
256
256
continue
257
257
name = f"{ match .identifier } {{{ match .base .split (':' , 1 )[0 ]} }}"
258
258
259
- self ._results .append (
260
- ArgumentDefinition (
261
- name = name ,
262
- name_token = a ,
263
- line_no = a .lineno ,
264
- col_offset = node .col_offset ,
265
- end_line_no = node .end_lineno
266
- if node .end_lineno is not None
267
- else a .lineno
268
- if a .lineno is not None
269
- else - 1 ,
270
- end_col_offset = node .end_col_offset
271
- if node .end_col_offset is not None
272
- else a .end_col_offset
273
- if name_token .end_col_offset is not None
274
- else - 1 ,
275
- source = self .source ,
276
- )
259
+ self ._results [name ] = ArgumentDefinition (
260
+ name = name ,
261
+ name_token = variable_token ,
262
+ line_no = variable_token .lineno ,
263
+ col_offset = variable_token .col_offset ,
264
+ end_line_no = variable_token .lineno ,
265
+ end_col_offset = variable_token .end_col_offset ,
266
+ source = self .source ,
277
267
)
278
268
269
+ def get_variable_token (self , token : Token ) -> Optional [Token ]:
270
+ from robot .parsing .lexer .tokens import Token as RobotToken
271
+
272
+ return next (
273
+ (
274
+ v
275
+ for v in itertools .dropwhile (
276
+ lambda t : t .type in RobotToken .NON_DATA_TOKENS ,
277
+ tokenize_variables (token , ignore_errors = True ),
278
+ )
279
+ if v .type == RobotToken .VARIABLE
280
+ ),
281
+ None ,
282
+ )
283
+
279
284
async def visit_Arguments (self , node : ast .AST ) -> None : # noqa: N802
280
285
from robot .errors import VariableError
281
286
from robot .parsing .lexer .tokens import Token as RobotToken
282
287
from robot .parsing .model .statements import Arguments
283
288
284
289
n = cast (Arguments , node )
285
290
arguments = n .get_tokens (RobotToken .ARGUMENT )
286
- for argument1 in (cast (RobotToken , e ) for e in arguments ):
291
+ for argument_token in (cast (RobotToken , e ) for e in arguments ):
287
292
try :
288
- argument = None
289
- try :
290
- argument = next (
291
- (
292
- v
293
- for v in itertools .dropwhile (
294
- lambda t : t .type in RobotToken .NON_DATA_TOKENS , argument1 .tokenize_variables ()
295
- )
296
- if v .type == RobotToken .VARIABLE
297
- ),
298
- None ,
299
- )
300
- except VariableError :
301
- pass
293
+ argument = self .get_variable_token (argument_token )
294
+
302
295
if argument is not None :
303
- self ._results .append (
304
- ArgumentDefinition (
305
- name = argument .value ,
306
- name_token = argument ,
307
- line_no = node .lineno ,
308
- col_offset = node .col_offset ,
309
- end_line_no = node .end_lineno
310
- if node .end_lineno is not None
311
- else argument .lineno
312
- if argument .lineno is not None
313
- else - 1 ,
314
- end_col_offset = node .end_col_offset
315
- if node .end_col_offset is not None
316
- else argument .end_col_offset
317
- if argument .end_col_offset is not None
318
- else - 1 ,
319
- source = self .source ,
320
- )
296
+ self ._results [argument .value ] = ArgumentDefinition (
297
+ name = argument .value ,
298
+ name_token = argument ,
299
+ line_no = argument .lineno ,
300
+ col_offset = argument .col_offset ,
301
+ end_line_no = argument .lineno ,
302
+ end_col_offset = argument .end_col_offset ,
303
+ source = self .source ,
321
304
)
305
+
322
306
except VariableError :
323
307
pass
324
308
325
309
async def visit_KeywordCall (self , node : ast .AST ) -> None : # noqa: N802
326
310
from robot .errors import VariableError
327
311
from robot .parsing .lexer .tokens import Token as RobotToken
328
312
from robot .parsing .model .statements import KeywordCall
329
- from robot .variables .search import contains_variable
330
313
331
314
# TODO analyse "Set Local/Global/Suite Variable"
332
315
333
- try :
334
- n = cast (KeywordCall , node )
335
- assign_token = n .get_token (RobotToken .ASSIGN )
336
- if assign_token is not None and assign_token .value and contains_variable (assign_token .value ):
337
- self ._results .append (
338
- VariableDefinition (
339
- name = assign_token .value ,
340
- name_token = assign_token ,
341
- line_no = node .lineno ,
342
- col_offset = node .col_offset ,
343
- end_line_no = node .end_lineno
344
- if node .end_lineno is not None
345
- else assign_token .lineno
346
- if assign_token .lineno is not None
347
- else - 1 ,
348
- end_col_offset = node .end_col_offset
349
- if node .end_col_offset is not None
350
- else assign_token .end_col_offset
351
- if assign_token .end_col_offset is not None
352
- else - 1 ,
316
+ n = cast (KeywordCall , node )
317
+ for assign_token in n .get_tokens (RobotToken .ASSIGN ):
318
+ variable_token = self .get_variable_token (assign_token )
319
+ try :
320
+ if variable_token is not None and variable_token .value not in self ._results :
321
+ self ._results [variable_token .value ] = VariableDefinition (
322
+ name = variable_token .value ,
323
+ name_token = variable_token ,
324
+ line_no = variable_token .lineno ,
325
+ col_offset = variable_token .col_offset ,
326
+ end_line_no = variable_token .lineno ,
327
+ end_col_offset = variable_token .end_col_offset ,
353
328
source = self .source ,
354
329
)
355
- )
356
- except VariableError :
357
- pass
330
+
331
+ except VariableError :
332
+ pass
358
333
359
334
async def visit_ForHeader (self , node : ast .AST ) -> None : # noqa: N802
360
- from robot .errors import VariableError
361
335
from robot .parsing .lexer .tokens import Token as RobotToken
362
336
from robot .parsing .model .statements import ForHeader
363
- from robot .variables .search import contains_variable
364
337
365
- try :
366
- n = cast (ForHeader , node )
367
- variables = n .get_tokens (RobotToken .VARIABLE )
368
- for variable in variables :
369
- if variable is not None and variable .value and contains_variable (variable .value ):
370
- self ._results .append (
371
- VariableDefinition (
372
- name = variable .value ,
373
- name_token = variable ,
374
- line_no = node .lineno ,
375
- col_offset = node .col_offset ,
376
- end_line_no = node .end_lineno
377
- if node .end_lineno is not None
378
- else variable .lineno
379
- if variable .lineno is not None
380
- else - 1 ,
381
- end_col_offset = node .end_col_offset
382
- if node .end_col_offset is not None
383
- else variable .end_col_offset
384
- if variable .end_col_offset is not None
385
- else - 1 ,
386
- source = self .source ,
387
- )
388
- )
389
- except VariableError :
390
- pass
338
+ n = cast (ForHeader , node )
339
+ variables = n .get_tokens (RobotToken .VARIABLE )
340
+ for variable in variables :
341
+ variable_token = self .get_variable_token (variable )
342
+ if variable_token is not None and variable_token .value and variable_token .value not in self ._results :
343
+ self ._results [variable_token .value ] = VariableDefinition (
344
+ name = variable_token .value ,
345
+ name_token = variable_token ,
346
+ line_no = node .lineno ,
347
+ col_offset = node .col_offset ,
348
+ end_line_no = variable_token .lineno ,
349
+ end_col_offset = variable_token .end_col_offset ,
350
+ source = self .source ,
351
+ )
391
352
392
353
393
354
class ImportVisitor (AsyncVisitor ):
0 commit comments