robotcode-robot 0.93.1__py3-none-any.whl → 0.94.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- robotcode/robot/__version__.py +1 -1
- robotcode/robot/diagnostics/document_cache_helper.py +11 -6
- robotcode/robot/diagnostics/entities.py +2 -2
- robotcode/robot/diagnostics/errors.py +6 -1
- robotcode/robot/diagnostics/imports_manager.py +77 -37
- robotcode/robot/diagnostics/keyword_finder.py +458 -0
- robotcode/robot/diagnostics/library_doc.py +20 -14
- robotcode/robot/diagnostics/model_helper.py +42 -27
- robotcode/robot/diagnostics/namespace.py +142 -552
- robotcode/robot/diagnostics/namespace_analyzer.py +952 -462
- robotcode/robot/utils/markdownformatter.py +8 -11
- robotcode/robot/utils/visitor.py +7 -13
- {robotcode_robot-0.93.1.dist-info → robotcode_robot-0.94.0.dist-info}/METADATA +2 -2
- robotcode_robot-0.94.0.dist-info/RECORD +31 -0
- robotcode_robot-0.93.1.dist-info/RECORD +0 -30
- {robotcode_robot-0.93.1.dist-info → robotcode_robot-0.94.0.dist-info}/WHEEL +0 -0
- {robotcode_robot-0.93.1.dist-info → robotcode_robot-0.94.0.dist-info}/licenses/LICENSE.txt +0 -0
@@ -6,7 +6,9 @@ import token as python_token
|
|
6
6
|
from io import StringIO
|
7
7
|
from tokenize import TokenError, generate_tokens
|
8
8
|
from typing import (
|
9
|
+
TYPE_CHECKING,
|
9
10
|
Any,
|
11
|
+
Callable,
|
10
12
|
Iterator,
|
11
13
|
List,
|
12
14
|
Optional,
|
@@ -17,6 +19,7 @@ from typing import (
|
|
17
19
|
Union,
|
18
20
|
)
|
19
21
|
|
22
|
+
from robot.errors import VariableError
|
20
23
|
from robot.parsing.lexer.tokens import Token
|
21
24
|
from robot.utils.escaping import split_from_equals, unescape
|
22
25
|
from robot.variables.finders import NOT_FOUND, NumberFinder
|
@@ -37,13 +40,16 @@ from .entities import (
|
|
37
40
|
VariableDefinition,
|
38
41
|
VariableNotFoundDefinition,
|
39
42
|
)
|
43
|
+
from .keyword_finder import DEFAULT_BDD_PREFIXES
|
40
44
|
from .library_doc import (
|
41
45
|
ArgumentInfo,
|
42
46
|
KeywordArgumentKind,
|
43
47
|
KeywordDoc,
|
44
48
|
LibraryDoc,
|
45
49
|
)
|
46
|
-
|
50
|
+
|
51
|
+
if TYPE_CHECKING:
|
52
|
+
from .namespace import Namespace
|
47
53
|
|
48
54
|
|
49
55
|
class ModelHelper:
|
@@ -52,7 +58,7 @@ class ModelHelper:
|
|
52
58
|
cls,
|
53
59
|
keyword_doc: Optional[KeywordDoc],
|
54
60
|
argument_tokens: List[Token],
|
55
|
-
namespace: Namespace,
|
61
|
+
namespace: "Namespace",
|
56
62
|
position: Position,
|
57
63
|
) -> Tuple[Optional[Tuple[Optional[KeywordDoc], Token]], List[Token]]:
|
58
64
|
if keyword_doc is None or not keyword_doc.is_any_run_keyword():
|
@@ -200,7 +206,7 @@ class ModelHelper:
|
|
200
206
|
keyword_name: Optional[str],
|
201
207
|
keyword_token: Token,
|
202
208
|
argument_tokens: List[Token],
|
203
|
-
namespace: Namespace,
|
209
|
+
namespace: "Namespace",
|
204
210
|
position: Position,
|
205
211
|
analyse_run_keywords: bool = True,
|
206
212
|
) -> Optional[Tuple[Optional[KeywordDoc], Token]]:
|
@@ -222,7 +228,7 @@ class ModelHelper:
|
|
222
228
|
|
223
229
|
@classmethod
|
224
230
|
def get_namespace_info_from_keyword_token(
|
225
|
-
cls, namespace: Namespace, keyword_token: Token
|
231
|
+
cls, namespace: "Namespace", keyword_token: Token
|
226
232
|
) -> Tuple[Optional[LibraryEntry], Optional[str]]:
|
227
233
|
lib_entry: Optional[LibraryEntry] = None
|
228
234
|
kw_namespace: Optional[str] = None
|
@@ -243,7 +249,7 @@ class ModelHelper:
|
|
243
249
|
|
244
250
|
return lib_entry, kw_namespace
|
245
251
|
|
246
|
-
|
252
|
+
match_extended = re.compile(
|
247
253
|
r"""
|
248
254
|
(.+?) # base name (group 1)
|
249
255
|
([^\s\w].+) # extended part (group 2)
|
@@ -254,7 +260,7 @@ class ModelHelper:
|
|
254
260
|
@staticmethod
|
255
261
|
def iter_expression_variables_from_token(
|
256
262
|
expression: Token,
|
257
|
-
namespace: Namespace,
|
263
|
+
namespace: "Namespace",
|
258
264
|
nodes: Optional[List[ast.AST]],
|
259
265
|
position: Optional[Position] = None,
|
260
266
|
skip_commandline_variables: bool = False,
|
@@ -354,27 +360,36 @@ class ModelHelper:
|
|
354
360
|
ignore_errors: bool = False,
|
355
361
|
*,
|
356
362
|
extra_types: Optional[Set[str]] = None,
|
363
|
+
exception_handler: Optional[Callable[[Exception, Token], None]] = None,
|
357
364
|
) -> Iterator[Token]:
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
365
|
+
if exception_handler is not None:
|
366
|
+
ignore_errors = False
|
367
|
+
try:
|
368
|
+
for t in tokenize_variables(token, identifiers, ignore_errors, extra_types=extra_types):
|
369
|
+
if t.type == Token.VARIABLE:
|
370
|
+
var, rest = cls.remove_index_from_variable_token(t)
|
371
|
+
if var is not None:
|
372
|
+
yield var
|
373
|
+
if rest is not None:
|
374
|
+
yield from cls.tokenize_variables(
|
375
|
+
rest,
|
376
|
+
identifiers,
|
377
|
+
ignore_errors,
|
378
|
+
extra_types=extra_types,
|
379
|
+
)
|
380
|
+
else:
|
381
|
+
yield t
|
382
|
+
except VariableError as e:
|
383
|
+
if exception_handler is not None:
|
384
|
+
exception_handler(e, token)
|
385
|
+
elif not ignore_errors:
|
386
|
+
raise
|
372
387
|
|
373
388
|
@classmethod
|
374
389
|
def iter_variables_from_token(
|
375
390
|
cls,
|
376
391
|
token: Token,
|
377
|
-
namespace: Namespace,
|
392
|
+
namespace: "Namespace",
|
378
393
|
nodes: Optional[List[ast.AST]],
|
379
394
|
position: Optional[Position] = None,
|
380
395
|
skip_commandline_variables: bool = False,
|
@@ -413,7 +428,7 @@ class ModelHelper:
|
|
413
428
|
):
|
414
429
|
yield v
|
415
430
|
elif base == "" and return_not_found:
|
416
|
-
yield (
|
431
|
+
yield ( # TODO: robotframework ignores this case, should we do the same or raise an error/hint?
|
417
432
|
sub_token,
|
418
433
|
VariableNotFoundDefinition(
|
419
434
|
sub_token.lineno,
|
@@ -481,7 +496,7 @@ class ModelHelper:
|
|
481
496
|
and sub_token.value[1:2] == "{"
|
482
497
|
and sub_token.value[-1:] == "}"
|
483
498
|
):
|
484
|
-
match = cls.
|
499
|
+
match = cls.match_extended.match(name[2:-1])
|
485
500
|
if match is not None:
|
486
501
|
base_name, _ = match.groups()
|
487
502
|
name = f"{name[0]}{{{base_name.strip()}}}"
|
@@ -557,7 +572,7 @@ class ModelHelper:
|
|
557
572
|
BDD_TOKEN = re.compile(r"^(Given|When|Then|And|But)$", flags=re.IGNORECASE)
|
558
573
|
|
559
574
|
@classmethod
|
560
|
-
def split_bdd_prefix(cls, namespace: Namespace, token: Token) -> Tuple[Optional[Token], Optional[Token]]:
|
575
|
+
def split_bdd_prefix(cls, namespace: "Namespace", token: Token) -> Tuple[Optional[Token], Optional[Token]]:
|
561
576
|
bdd_token = None
|
562
577
|
|
563
578
|
parts = token.value.split()
|
@@ -590,7 +605,7 @@ class ModelHelper:
|
|
590
605
|
return bdd_token, token
|
591
606
|
|
592
607
|
@classmethod
|
593
|
-
def strip_bdd_prefix(cls, namespace: Namespace, token: Token) -> Token:
|
608
|
+
def strip_bdd_prefix(cls, namespace: "Namespace", token: Token) -> Token:
|
594
609
|
if get_robot_version() < (6, 0):
|
595
610
|
bdd_match = cls.BDD_TOKEN_REGEX.match(token.value)
|
596
611
|
if bdd_match:
|
@@ -627,7 +642,7 @@ class ModelHelper:
|
|
627
642
|
return token
|
628
643
|
|
629
644
|
@classmethod
|
630
|
-
def is_bdd_token(cls, namespace: Namespace, token: Token) -> bool:
|
645
|
+
def is_bdd_token(cls, namespace: "Namespace", token: Token) -> bool:
|
631
646
|
if get_robot_version() < (6, 0):
|
632
647
|
bdd_match = cls.BDD_TOKEN.match(token.value)
|
633
648
|
return bool(bdd_match)
|
@@ -651,7 +666,7 @@ class ModelHelper:
|
|
651
666
|
@classmethod
|
652
667
|
def get_keyword_definition_at_line(cls, library_doc: LibraryDoc, value: str, line: int) -> Optional[KeywordDoc]:
|
653
668
|
return next(
|
654
|
-
(k for k in library_doc.keywords.
|
669
|
+
(k for k in library_doc.keywords.iter_all(value) if k.line_no == line),
|
655
670
|
None,
|
656
671
|
)
|
657
672
|
|