robotcode-robot 0.82.0__py3-none-any.whl → 0.82.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- __version__ = "0.82.0"
1
+ __version__ = "0.82.2"
@@ -258,6 +258,7 @@ class ModelHelper:
258
258
  nodes: Optional[List[ast.AST]],
259
259
  position: Optional[Position] = None,
260
260
  skip_commandline_variables: bool = False,
261
+ skip_local_variables: bool = False,
261
262
  return_not_found: bool = False,
262
263
  ) -> Iterator[Tuple[Token, VariableDefinition]]:
263
264
  variable_started = False
@@ -270,6 +271,7 @@ class ModelHelper:
270
271
  nodes,
271
272
  position,
272
273
  skip_commandline_variables=skip_commandline_variables,
274
+ skip_local_variables=skip_local_variables,
273
275
  ignore_error=True,
274
276
  )
275
277
  sub_token = Token(
@@ -376,6 +378,7 @@ class ModelHelper:
376
378
  nodes: Optional[List[ast.AST]],
377
379
  position: Optional[Position] = None,
378
380
  skip_commandline_variables: bool = False,
381
+ skip_local_variables: bool = False,
379
382
  return_not_found: bool = False,
380
383
  ) -> Iterator[Tuple[Token, VariableDefinition]]:
381
384
  def is_number(name: str) -> bool:
@@ -405,6 +408,7 @@ class ModelHelper:
405
408
  nodes,
406
409
  position,
407
410
  skip_commandline_variables=skip_commandline_variables,
411
+ skip_local_variables=skip_local_variables,
408
412
  return_not_found=return_not_found,
409
413
  ):
410
414
  yield v
@@ -461,6 +465,7 @@ class ModelHelper:
461
465
  nodes,
462
466
  position,
463
467
  skip_commandline_variables=skip_commandline_variables,
468
+ skip_local_variables=skip_local_variables,
464
469
  ignore_error=True,
465
470
  )
466
471
  if var is not None:
@@ -485,6 +490,7 @@ class ModelHelper:
485
490
  nodes,
486
491
  position,
487
492
  skip_commandline_variables=skip_commandline_variables,
493
+ skip_local_variables=skip_local_variables,
488
494
  ignore_error=True,
489
495
  )
490
496
  sub_sub_token = Token(
@@ -26,13 +26,8 @@ from typing import (
26
26
  from robot.errors import VariableError
27
27
  from robot.libraries import STDLIBS
28
28
  from robot.parsing.lexer.tokens import Token
29
- from robot.parsing.model.blocks import (
30
- Keyword,
31
- SettingSection,
32
- TestCase,
33
- VariableSection,
34
- )
35
- from robot.parsing.model.statements import Arguments, Statement
29
+ from robot.parsing.model.blocks import Keyword, SettingSection, TestCase, VariableSection
30
+ from robot.parsing.model.statements import Arguments, Fixture, Statement, Timeout
36
31
  from robot.parsing.model.statements import LibraryImport as RobotLibraryImport
37
32
  from robot.parsing.model.statements import ResourceImport as RobotResourceImport
38
33
  from robot.parsing.model.statements import (
@@ -182,7 +177,7 @@ class VariablesVisitor(Visitor):
182
177
  )
183
178
 
184
179
 
185
- class BlockVariableVisitor(Visitor):
180
+ class VariableVisitorBase(Visitor):
186
181
  def __init__(
187
182
  self,
188
183
  namespace: "Namespace",
@@ -198,7 +193,79 @@ class BlockVariableVisitor(Visitor):
198
193
 
199
194
  self._results: Dict[str, VariableDefinition] = {}
200
195
  self.current_kw_doc: Optional[KeywordDoc] = None
196
+ self.current_kw: Optional[Keyword] = None
197
+
198
+ def get_variable_token(self, token: Token) -> Optional[Token]:
199
+ return next(
200
+ (
201
+ v
202
+ for v in itertools.dropwhile(
203
+ lambda t: t.type in Token.NON_DATA_TOKENS,
204
+ tokenize_variables(token, ignore_errors=True, extra_types={Token.VARIABLE}),
205
+ )
206
+ if v.type == Token.VARIABLE
207
+ ),
208
+ None,
209
+ )
210
+
211
+
212
+ class ArgumentVisitor(VariableVisitorBase):
213
+ def __init__(
214
+ self,
215
+ namespace: "Namespace",
216
+ nodes: Optional[List[ast.AST]],
217
+ position: Optional[Position],
218
+ in_args: bool,
219
+ current_kw_doc: Optional[KeywordDoc],
220
+ ) -> None:
221
+ super().__init__(namespace, nodes, position, in_args)
222
+
223
+ self.current_kw_doc: Optional[KeywordDoc] = current_kw_doc
224
+
225
+ def get(self, model: ast.AST) -> Dict[str, VariableDefinition]:
226
+ self._results = {}
227
+
228
+ self.visit(model)
229
+
230
+ return self._results
231
+
232
+ def visit_Arguments(self, node: Statement) -> None: # noqa: N802
233
+ args: List[str] = []
234
+
235
+ arguments = node.get_tokens(Token.ARGUMENT)
236
+
237
+ for argument_token in arguments:
238
+ try:
239
+ argument = self.get_variable_token(argument_token)
240
+
241
+ if argument is not None and argument.value != "@{}":
242
+ if (
243
+ self.in_args
244
+ and self.position is not None
245
+ and self.position in range_from_token(argument_token)
246
+ and self.position > range_from_token(argument).end
247
+ ):
248
+ break
249
+
250
+ if argument.value not in args:
251
+ args.append(argument.value)
252
+ arg_def = ArgumentDefinition(
253
+ name=argument.value,
254
+ name_token=strip_variable_token(argument),
255
+ line_no=argument.lineno,
256
+ col_offset=argument.col_offset,
257
+ end_line_no=argument.lineno,
258
+ end_col_offset=argument.end_col_offset,
259
+ source=self.namespace.source,
260
+ keyword_doc=self.current_kw_doc,
261
+ )
262
+ self._results[argument.value] = arg_def
263
+
264
+ except VariableError:
265
+ pass
201
266
 
267
+
268
+ class OnlyArgumentsVisitor(VariableVisitorBase):
202
269
  def get(self, model: ast.AST) -> List[VariableDefinition]:
203
270
  self._results = {}
204
271
 
@@ -211,9 +278,11 @@ class BlockVariableVisitor(Visitor):
211
278
  super().visit(node)
212
279
 
213
280
  def visit_Keyword(self, node: ast.AST) -> None: # noqa: N802
281
+ self.current_kw = cast(Keyword, node)
214
282
  try:
215
283
  self.generic_visit(node)
216
284
  finally:
285
+ self.current_kw = None
217
286
  self.current_kw_doc = None
218
287
 
219
288
  def visit_KeywordName(self, node: Statement) -> None: # noqa: N802
@@ -248,53 +317,15 @@ class BlockVariableVisitor(Visitor):
248
317
  keyword_doc=self.current_kw_doc,
249
318
  )
250
319
 
251
- def get_variable_token(self, token: Token) -> Optional[Token]:
252
- return next(
253
- (
254
- v
255
- for v in itertools.dropwhile(
256
- lambda t: t.type in Token.NON_DATA_TOKENS,
257
- tokenize_variables(token, ignore_errors=True, extra_types={Token.VARIABLE}),
258
- )
259
- if v.type == Token.VARIABLE
260
- ),
261
- None,
262
- )
263
-
264
- def visit_Arguments(self, node: Statement) -> None: # noqa: N802
265
- args: List[str] = []
320
+ if self.current_kw is not None:
321
+ args = ArgumentVisitor(
322
+ self.namespace, self.nodes, self.position, self.in_args, self.current_kw_doc
323
+ ).get(self.current_kw)
324
+ if args:
325
+ self._results.update(args)
266
326
 
267
- arguments = node.get_tokens(Token.ARGUMENT)
268
327
 
269
- for argument_token in arguments:
270
- try:
271
- argument = self.get_variable_token(argument_token)
272
-
273
- if argument is not None and argument.value != "@{}":
274
- if (
275
- self.in_args
276
- and self.position is not None
277
- and self.position in range_from_token(argument_token)
278
- and self.position > range_from_token(argument).end
279
- ):
280
- break
281
-
282
- if argument.value not in args:
283
- args.append(argument.value)
284
- arg_def = ArgumentDefinition(
285
- name=argument.value,
286
- name_token=strip_variable_token(argument),
287
- line_no=argument.lineno,
288
- col_offset=argument.col_offset,
289
- end_line_no=argument.lineno,
290
- end_col_offset=argument.end_col_offset,
291
- source=self.namespace.source,
292
- keyword_doc=self.current_kw_doc,
293
- )
294
- self._results[argument.value] = arg_def
295
-
296
- except VariableError:
297
- pass
328
+ class BlockVariableVisitor(OnlyArgumentsVisitor):
298
329
 
299
330
  def visit_ExceptHeader(self, node: Statement) -> None: # noqa: N802
300
331
  variables = node.get_tokens(Token.VARIABLE)[:1]
@@ -990,10 +1021,12 @@ class Namespace:
990
1021
  nodes: Optional[List[ast.AST]] = None,
991
1022
  position: Optional[Position] = None,
992
1023
  skip_commandline_variables: bool = False,
1024
+ skip_local_variables: bool = False,
993
1025
  ) -> Iterator[Tuple[VariableMatcher, VariableDefinition]]:
994
1026
  yielded: Dict[VariableMatcher, VariableDefinition] = {}
995
1027
 
996
1028
  test_or_keyword = None
1029
+ test_or_keyword_nodes = None
997
1030
 
998
1031
  if nodes:
999
1032
  test_or_keyword_nodes = list(
@@ -1004,18 +1037,23 @@ class Namespace:
1004
1037
  )
1005
1038
  test_or_keyword = test_or_keyword_nodes[0] if test_or_keyword_nodes else None
1006
1039
 
1040
+ in_args = isinstance(test_or_keyword_nodes[-1], Arguments) if test_or_keyword_nodes else False
1041
+ only_args = (
1042
+ isinstance(test_or_keyword_nodes[-1], (Arguments, Fixture, Timeout)) if test_or_keyword_nodes else False
1043
+ )
1044
+
1007
1045
  for var in chain(
1008
1046
  *[
1009
1047
  (
1010
1048
  (
1011
- BlockVariableVisitor(
1049
+ (OnlyArgumentsVisitor if only_args else BlockVariableVisitor)(
1012
1050
  self,
1013
1051
  nodes,
1014
1052
  position,
1015
- isinstance(test_or_keyword_nodes[-1], Arguments) if nodes else False,
1053
+ in_args,
1016
1054
  ).get(test_or_keyword)
1017
1055
  )
1018
- if test_or_keyword is not None
1056
+ if test_or_keyword is not None and not skip_local_variables
1019
1057
  else []
1020
1058
  )
1021
1059
  ],
@@ -1081,6 +1119,7 @@ class Namespace:
1081
1119
  nodes: Optional[List[ast.AST]] = None,
1082
1120
  position: Optional[Position] = None,
1083
1121
  skip_commandline_variables: bool = False,
1122
+ skip_local_variables: bool = False,
1084
1123
  ignore_error: bool = False,
1085
1124
  ) -> Optional[VariableDefinition]:
1086
1125
  self.ensure_initialized()
@@ -1105,6 +1144,7 @@ class Namespace:
1105
1144
  nodes,
1106
1145
  position,
1107
1146
  skip_commandline_variables=skip_commandline_variables,
1147
+ skip_local_variables=skip_local_variables,
1108
1148
  ):
1109
1149
  if matcher == m:
1110
1150
  return v
@@ -12,12 +12,14 @@ from robot.parsing.lexer.tokens import Token
12
12
  from robot.parsing.model.blocks import Keyword, TestCase
13
13
  from robot.parsing.model.statements import (
14
14
  Arguments,
15
+ DefaultTags,
15
16
  DocumentationOrMetadata,
16
17
  Fixture,
17
18
  KeywordCall,
18
19
  LibraryImport,
19
20
  ResourceImport,
20
21
  Statement,
22
+ Tags,
21
23
  Template,
22
24
  TemplateArguments,
23
25
  TestCaseName,
@@ -70,9 +72,35 @@ from .namespace import KeywordFinder, Namespace
70
72
 
71
73
  if get_robot_version() < (7, 0):
72
74
  from robot.variables.search import VariableIterator
75
+
76
+ VARIABLE_NOT_FOUND_HINT_TYPES: Tuple[Any, ...] = (
77
+ DocumentationOrMetadata,
78
+ TestCaseName,
79
+ Tags,
80
+ robot.parsing.model.statements.ForceTags,
81
+ DefaultTags,
82
+ )
83
+
84
+ IN_SETTING_TYPES: Tuple[Any, ...] = (
85
+ DocumentationOrMetadata,
86
+ Tags,
87
+ robot.parsing.model.statements.ForceTags,
88
+ DefaultTags,
89
+ Template,
90
+ )
73
91
  else:
74
92
  from robot.variables.search import VariableMatches
75
93
 
94
+ VARIABLE_NOT_FOUND_HINT_TYPES = (
95
+ DocumentationOrMetadata,
96
+ TestCaseName,
97
+ Tags,
98
+ robot.parsing.model.statements.TestTags,
99
+ DefaultTags,
100
+ )
101
+
102
+ IN_SETTING_TYPES = (DocumentationOrMetadata, Tags, robot.parsing.model.statements.TestTags, DefaultTags, Template)
103
+
76
104
 
77
105
  @dataclass
78
106
  class AnalyzerResult:
@@ -266,10 +294,10 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
266
294
 
267
295
  self.node_stack.append(node)
268
296
  try:
297
+ in_setting = isinstance(node, IN_SETTING_TYPES)
298
+
269
299
  severity = (
270
- DiagnosticSeverity.HINT
271
- if isinstance(node, (DocumentationOrMetadata, TestCaseName))
272
- else DiagnosticSeverity.ERROR
300
+ DiagnosticSeverity.HINT if isinstance(node, VARIABLE_NOT_FOUND_HINT_TYPES) else DiagnosticSeverity.ERROR
273
301
  )
274
302
 
275
303
  if isinstance(node, KeywordCall) and node.keyword:
@@ -295,6 +323,7 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
295
323
  self.node_stack,
296
324
  range_from_token(token).start,
297
325
  skip_commandline_variables=False,
326
+ skip_local_variables=in_setting,
298
327
  return_not_found=True,
299
328
  ):
300
329
  if isinstance(var, VariableNotFoundDefinition):
@@ -380,6 +409,7 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
380
409
  self.node_stack,
381
410
  range_from_token(token).start,
382
411
  skip_commandline_variables=False,
412
+ skip_local_variables=in_setting,
383
413
  return_not_found=True,
384
414
  ):
385
415
  if isinstance(var, VariableNotFoundDefinition):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: robotcode-robot
3
- Version: 0.82.0
3
+ Version: 0.82.2
4
4
  Summary: Support classes for RobotCode for handling Robot Framework projects.
5
5
  Project-URL: Homepage, https://robotcode.io
6
6
  Project-URL: Donate, https://opencollective.com/robotcode
@@ -26,7 +26,7 @@ Classifier: Topic :: Utilities
26
26
  Classifier: Typing :: Typed
27
27
  Requires-Python: >=3.8
28
28
  Requires-Dist: platformdirs<4.2.0,>=3.2.0
29
- Requires-Dist: robotcode-core==0.82.0
29
+ Requires-Dist: robotcode-core==0.82.2
30
30
  Requires-Dist: robotframework>=4.1.0
31
31
  Requires-Dist: tomli>=1.1.0; python_version < '3.11'
32
32
  Description-Content-Type: text/markdown
@@ -1,5 +1,5 @@
1
1
  robotcode/robot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- robotcode/robot/__version__.py,sha256=3E7u1ATSjtoHo9Pq3zuZICzm_iPH64qoru2bGBZuNbw,23
2
+ robotcode/robot/__version__.py,sha256=RTYfZgQQ2I7IHQ7CnMLKfzWJLJYwV_HoEeJ8bvw2WlY,23
3
3
  robotcode/robot/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
4
4
  robotcode/robot/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  robotcode/robot/config/loader.py,sha256=LpGqJAdysvVSZpccW-Il52xn9RMBBb9X94emlBY7zCc,6077
@@ -11,9 +11,9 @@ robotcode/robot/diagnostics/entities.py,sha256=CrjhLHHwKCCE3YI_dcjoZADJz1urm0VGb
11
11
  robotcode/robot/diagnostics/errors.py,sha256=VavgWYuHoW5sTT16j2rl9hxMhWxBKNSFsNmHWPzARQQ,1413
12
12
  robotcode/robot/diagnostics/imports_manager.py,sha256=qE__lm0Hsj3R0gUauXRmbWJPYihNjk3O-c5hcICGQjc,56251
13
13
  robotcode/robot/diagnostics/library_doc.py,sha256=sLENYhMoq5IvYgd0jUhVpRkRTvY9IfTotlthLUUO0vY,97124
14
- robotcode/robot/diagnostics/model_helper.py,sha256=3-6lZluPQaT9KstHLfV0jsRUAjTfrkUOomSXiMPKoQg,29868
15
- robotcode/robot/diagnostics/namespace.py,sha256=yerha8VmX_01h8Ga7MaH4wRVk1waVQ4pJfPu55ohcYU,89792
16
- robotcode/robot/diagnostics/namespace_analyzer.py,sha256=tElI2NzcCRnsvPqv7wYaV2p5E22VyqEwQQ90FOOjadI,50086
14
+ robotcode/robot/diagnostics/model_helper.py,sha256=_5ixKKMrb-nY-uvV8_WjJ1rlNlz7gT7kHM5NYi_hjVg,30232
15
+ robotcode/robot/diagnostics/namespace.py,sha256=OlhhK1RH4ZFGXZEerFQIzye0ddAq8V-W0cCsxYg6tdc,91315
16
+ robotcode/robot/diagnostics/namespace_analyzer.py,sha256=PWZjpLdn-9GCpp4L4dKxVF2B1hxzSEdDzBNUw2Lp51A,50937
17
17
  robotcode/robot/diagnostics/workspace_config.py,sha256=lWNq1KmGGJ9cHFNHn0QTCBHHzgz4AewTw0l-W4TKrj0,1803
18
18
  robotcode/robot/utils/__init__.py,sha256=OjNPMn_XSnfaMCyKd8Kmq6vlRt6mIGlzW4qiiD3ykUg,447
19
19
  robotcode/robot/utils/ast.py,sha256=N7PobxXjpPWwv6UBa-GBn5wn6RAsiRm8unP6UZt0P6M,10193
@@ -23,7 +23,7 @@ robotcode/robot/utils/robot_path.py,sha256=qKBh1cEnReBBLKkWu4gB9EzM-scAwE4xJc1m6
23
23
  robotcode/robot/utils/stubs.py,sha256=6-DMI_CQVJHDgG13t-zINKGCRb_Q7MQPm0_AkfhAEvE,748
24
24
  robotcode/robot/utils/variables.py,sha256=fEl8S37lb_mD4hn2MZRAlkiuLGBjAOeZVK0r2o2CfPw,742
25
25
  robotcode/robot/utils/visitor.py,sha256=uYLqEhGPmzWKWI3SSrmCaYMwtKvNShvbiPZ4b3FavX8,3241
26
- robotcode_robot-0.82.0.dist-info/METADATA,sha256=tolbKF_209BXd1oEnPJYGb3EXqx4n9bvKBp-lWuu-gI,2240
27
- robotcode_robot-0.82.0.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
28
- robotcode_robot-0.82.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
29
- robotcode_robot-0.82.0.dist-info/RECORD,,
26
+ robotcode_robot-0.82.2.dist-info/METADATA,sha256=pRwfD5QyBb_O5ISAAeBTS_ERjDt3ksXL7ac5FqxT2cg,2240
27
+ robotcode_robot-0.82.2.dist-info/WHEEL,sha256=zEMcRr9Kr03x1ozGwg5v9NQBKn3kndp6LSoSlVg-jhU,87
28
+ robotcode_robot-0.82.2.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
29
+ robotcode_robot-0.82.2.dist-info/RECORD,,