robotcode-robot 0.83.2__py3-none-any.whl → 0.84.0__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.
- robotcode/robot/__version__.py +1 -1
- robotcode/robot/config/model.py +3 -2
- robotcode/robot/diagnostics/diagnostics_modifier.py +201 -0
- robotcode/robot/diagnostics/document_cache_helper.py +8 -3
- robotcode/robot/diagnostics/entities.py +2 -6
- robotcode/robot/diagnostics/errors.py +2 -0
- robotcode/robot/diagnostics/library_doc.py +7 -7
- robotcode/robot/diagnostics/namespace.py +8 -55
- robotcode/robot/diagnostics/namespace_analyzer.py +3 -18
- robotcode/robot/utils/ast.py +3 -3
- robotcode/robot/utils/match.py +4 -1
- {robotcode_robot-0.83.2.dist-info → robotcode_robot-0.84.0.dist-info}/METADATA +2 -2
- {robotcode_robot-0.83.2.dist-info → robotcode_robot-0.84.0.dist-info}/RECORD +15 -14
- {robotcode_robot-0.83.2.dist-info → robotcode_robot-0.84.0.dist-info}/WHEEL +1 -1
- {robotcode_robot-0.83.2.dist-info → robotcode_robot-0.84.0.dist-info}/licenses/LICENSE.txt +0 -0
robotcode/robot/__version__.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.
|
1
|
+
__version__ = "0.84.0"
|
robotcode/robot/config/model.py
CHANGED
@@ -291,8 +291,9 @@ class BaseOptions(ValidateMixin):
|
|
291
291
|
for key, item in value.items():
|
292
292
|
append_name(field)
|
293
293
|
if isinstance(item, list):
|
294
|
-
|
295
|
-
|
294
|
+
str_item = [str(i) for i in item]
|
295
|
+
separator = ";" if any(True for s in str_item if ":" in s) else ":"
|
296
|
+
result.append(f"{key}{separator if item else ''}{separator.join(str_item)}")
|
296
297
|
else:
|
297
298
|
result.append(f"{key}:{item}")
|
298
299
|
else:
|
@@ -0,0 +1,201 @@
|
|
1
|
+
import functools
|
2
|
+
import re as re
|
3
|
+
from ast import AST
|
4
|
+
from collections import defaultdict
|
5
|
+
from dataclasses import dataclass
|
6
|
+
from typing import Dict, List, Optional, Set, Union
|
7
|
+
|
8
|
+
from robot.parsing.lexer.tokens import Token
|
9
|
+
from robot.parsing.model.blocks import Block, File
|
10
|
+
from robot.parsing.model.statements import Comment, Statement
|
11
|
+
from robotcode.core.lsp.types import Diagnostic, DiagnosticSeverity
|
12
|
+
|
13
|
+
from ..utils.visitor import Visitor
|
14
|
+
|
15
|
+
ACTIONS = ["ignore", "error", "warn", "information", "hint", "reset"]
|
16
|
+
|
17
|
+
ROBOTCODE_ACTION_AND_CODES_PATTERN = re.compile(rf"(?P<action>{'|'.join(ACTIONS)})(\[(?P<codes>[^\]]*?)\])?")
|
18
|
+
|
19
|
+
|
20
|
+
@dataclass
|
21
|
+
class RulesAndCodes:
|
22
|
+
codes: Dict[Union[str, int], Set[int]]
|
23
|
+
actions: Dict[int, Dict[Union[str, int], str]]
|
24
|
+
|
25
|
+
|
26
|
+
_translation_table = str.maketrans("", "", "_- ")
|
27
|
+
|
28
|
+
ROBOTCODE_MARKER = "robotcode:"
|
29
|
+
|
30
|
+
|
31
|
+
class DisablersVisitor(Visitor):
|
32
|
+
|
33
|
+
def __init__(self) -> None:
|
34
|
+
super().__init__()
|
35
|
+
|
36
|
+
self._file_lineno = 0
|
37
|
+
self._file_end_lineno = 0
|
38
|
+
self.current_block: Optional[Block] = None
|
39
|
+
self.rules_and_codes: RulesAndCodes = RulesAndCodes(defaultdict(set), defaultdict(dict))
|
40
|
+
|
41
|
+
@property
|
42
|
+
def file_lineno(self) -> int:
|
43
|
+
return self._file_lineno
|
44
|
+
|
45
|
+
@property
|
46
|
+
def file_end_lineno(self) -> int:
|
47
|
+
return self._file_end_lineno
|
48
|
+
|
49
|
+
def visit_File(self, node: File) -> None: # noqa: N802
|
50
|
+
self._file_lineno = node.lineno - 1
|
51
|
+
self._file_end_lineno = node.end_lineno - 1
|
52
|
+
|
53
|
+
self.generic_visit(node)
|
54
|
+
|
55
|
+
def visit_Comment(self, node: Comment) -> None: # noqa: N802
|
56
|
+
self._handle_comment(node)
|
57
|
+
|
58
|
+
self.generic_visit(node)
|
59
|
+
|
60
|
+
def visit_Block(self, node: Block) -> None: # noqa: N802
|
61
|
+
self.current_block = node
|
62
|
+
self.generic_visit(node)
|
63
|
+
|
64
|
+
def visit_Statement(self, node: Statement) -> None: # noqa: N802
|
65
|
+
self._handle_statement_comments(node)
|
66
|
+
self.generic_visit(node)
|
67
|
+
|
68
|
+
def _parse_robotcode_disabler(self, comment: str) -> Dict[str, List[str]]:
|
69
|
+
result: Dict[str, List[str]] = {}
|
70
|
+
|
71
|
+
comment = comment.strip()
|
72
|
+
m = ROBOTCODE_ACTION_AND_CODES_PATTERN.match(comment)
|
73
|
+
if m is None:
|
74
|
+
return result
|
75
|
+
|
76
|
+
for m in ROBOTCODE_ACTION_AND_CODES_PATTERN.finditer(comment):
|
77
|
+
action = m.group("action")
|
78
|
+
messages = m.group("codes")
|
79
|
+
result[action] = (
|
80
|
+
[m.strip().translate(_translation_table).lower() for m in messages.split(",")]
|
81
|
+
if messages is not None
|
82
|
+
else ["*"]
|
83
|
+
)
|
84
|
+
|
85
|
+
return result
|
86
|
+
|
87
|
+
def _handle_statement_comments(self, node: Statement) -> None:
|
88
|
+
first_comment = True
|
89
|
+
has_marker = False
|
90
|
+
|
91
|
+
for token in node.get_tokens(Token.COMMENT):
|
92
|
+
value = token.value.strip()
|
93
|
+
if first_comment and value.startswith("#"):
|
94
|
+
value = value[1:].strip()
|
95
|
+
first_comment = False
|
96
|
+
|
97
|
+
if not value:
|
98
|
+
continue
|
99
|
+
|
100
|
+
if not has_marker and value.startswith(ROBOTCODE_MARKER):
|
101
|
+
has_marker = True
|
102
|
+
value = value[10:]
|
103
|
+
|
104
|
+
if not value:
|
105
|
+
continue
|
106
|
+
|
107
|
+
if has_marker:
|
108
|
+
actions = self._parse_robotcode_disabler(value)
|
109
|
+
|
110
|
+
if not actions:
|
111
|
+
break
|
112
|
+
|
113
|
+
for action, codes in actions.items():
|
114
|
+
for code in codes:
|
115
|
+
self.rules_and_codes.codes[code].add(token.lineno - 1)
|
116
|
+
self.rules_and_codes.actions[token.lineno - 1][code] = action
|
117
|
+
|
118
|
+
def _handle_comment(self, node: Comment) -> None:
|
119
|
+
first_comment = True
|
120
|
+
has_marker = False
|
121
|
+
|
122
|
+
start_lineno = node.lineno - 1
|
123
|
+
end_lineno = self.file_end_lineno
|
124
|
+
|
125
|
+
if node.tokens[0].type == Token.SEPARATOR and self.current_block is not None:
|
126
|
+
end_lineno = self.current_block.end_lineno - 1
|
127
|
+
for token in node.get_tokens(Token.COMMENT):
|
128
|
+
value = token.value.strip()
|
129
|
+
if first_comment and value.startswith("#"):
|
130
|
+
value = value[1:].strip()
|
131
|
+
first_comment = False
|
132
|
+
|
133
|
+
if not value:
|
134
|
+
continue
|
135
|
+
|
136
|
+
if not has_marker and value.startswith(ROBOTCODE_MARKER):
|
137
|
+
has_marker = True
|
138
|
+
value = value[10:]
|
139
|
+
|
140
|
+
if not value:
|
141
|
+
continue
|
142
|
+
|
143
|
+
if has_marker:
|
144
|
+
actions = self._parse_robotcode_disabler(value)
|
145
|
+
|
146
|
+
if not actions:
|
147
|
+
break
|
148
|
+
|
149
|
+
for action, codes in actions.items():
|
150
|
+
for code in codes:
|
151
|
+
self.rules_and_codes.codes[code].update(range(start_lineno, end_lineno + 1))
|
152
|
+
for i in range(start_lineno, end_lineno + 1):
|
153
|
+
self.rules_and_codes.actions[i][code] = action
|
154
|
+
|
155
|
+
|
156
|
+
class DiagnosticsModifier:
|
157
|
+
def __init__(self, model: AST) -> None:
|
158
|
+
self.model = model
|
159
|
+
|
160
|
+
@functools.cached_property
|
161
|
+
def rules_and_codes(self) -> RulesAndCodes:
|
162
|
+
visitor = DisablersVisitor()
|
163
|
+
visitor.visit(self.model)
|
164
|
+
return visitor.rules_and_codes
|
165
|
+
|
166
|
+
def modify_diagnostic(self, diagnostic: Diagnostic) -> Optional[Diagnostic]:
|
167
|
+
if diagnostic.code is not None:
|
168
|
+
code = (
|
169
|
+
str(diagnostic.code).translate(_translation_table).lower()
|
170
|
+
if diagnostic.code is not None
|
171
|
+
else "unknowncode"
|
172
|
+
)
|
173
|
+
|
174
|
+
lines = self.rules_and_codes.codes.get(code)
|
175
|
+
|
176
|
+
if lines is None or lines is not None and diagnostic.range.start.line not in lines:
|
177
|
+
code = "*"
|
178
|
+
lines = self.rules_and_codes.codes.get(code)
|
179
|
+
|
180
|
+
if lines is not None and diagnostic.range.start.line in lines:
|
181
|
+
actions = self.rules_and_codes.actions.get(diagnostic.range.start.line)
|
182
|
+
if actions is not None:
|
183
|
+
action = actions.get(code)
|
184
|
+
if action is not None:
|
185
|
+
if action == "ignore":
|
186
|
+
return None
|
187
|
+
if action == "reset":
|
188
|
+
pass # do nothing
|
189
|
+
elif action == "error":
|
190
|
+
diagnostic.severity = DiagnosticSeverity.ERROR
|
191
|
+
elif action == "warn":
|
192
|
+
diagnostic.severity = DiagnosticSeverity.WARNING
|
193
|
+
elif action == "information":
|
194
|
+
diagnostic.severity = DiagnosticSeverity.INFORMATION
|
195
|
+
elif action == "hint":
|
196
|
+
diagnostic.severity = DiagnosticSeverity.HINT
|
197
|
+
|
198
|
+
return diagnostic
|
199
|
+
|
200
|
+
def modify_diagnostics(self, diagnostics: List[Diagnostic]) -> List[Diagnostic]:
|
201
|
+
return [d for d in map(self.modify_diagnostic, diagnostics) if d is not None]
|
@@ -26,6 +26,7 @@ from robotcode.core.text_document import TextDocument
|
|
26
26
|
from robotcode.core.uri import Uri
|
27
27
|
from robotcode.core.utils.logging import LoggingDescriptor
|
28
28
|
from robotcode.core.workspace import Workspace, WorkspaceFolder
|
29
|
+
from robotcode.robot.diagnostics.diagnostics_modifier import DiagnosticsModifier
|
29
30
|
|
30
31
|
from ..config.model import RobotBaseProfile
|
31
32
|
from ..utils import get_robot_version
|
@@ -453,9 +454,7 @@ class DocumentsCacheHelper:
|
|
453
454
|
return result
|
454
455
|
|
455
456
|
def get_only_initialized_namespace(self, document: TextDocument) -> Optional[Namespace]:
|
456
|
-
|
457
|
-
|
458
|
-
return result
|
457
|
+
return cast(Optional[Namespace], document.get_data(self.INITIALIZED_NAMESPACE))
|
459
458
|
|
460
459
|
def __get_namespace_for_document_type(
|
461
460
|
self, document: TextDocument, document_type: Optional[DocumentType]
|
@@ -579,3 +578,9 @@ class DocumentsCacheHelper:
|
|
579
578
|
def calc_cache_path(self, folder_uri: Uri) -> Path:
|
580
579
|
# TODO: cache path should be configurable, save cache in vscode workspace folder or in robotcode cache folder
|
581
580
|
return folder_uri.to_path()
|
581
|
+
|
582
|
+
def get_diagnostic_modifier(self, document: TextDocument) -> DiagnosticsModifier:
|
583
|
+
return document.get_cache(self.__get_diagnostic_modifier)
|
584
|
+
|
585
|
+
def __get_diagnostic_modifier(self, document: TextDocument) -> DiagnosticsModifier:
|
586
|
+
return DiagnosticsModifier(self.get_model(document, False))
|
@@ -12,7 +12,9 @@ from typing import (
|
|
12
12
|
)
|
13
13
|
|
14
14
|
from robot.parsing.lexer.tokens import Token
|
15
|
+
from robot.variables.search import search_variable
|
15
16
|
from robotcode.core.lsp.types import Position, Range
|
17
|
+
from robotcode.robot.utils.match import normalize
|
16
18
|
|
17
19
|
from ..utils.ast import range_from_token
|
18
20
|
|
@@ -131,9 +133,6 @@ class InvalidVariableError(Exception):
|
|
131
133
|
|
132
134
|
class VariableMatcher:
|
133
135
|
def __init__(self, name: str) -> None:
|
134
|
-
from robot.variables.search import search_variable
|
135
|
-
from robotcode.robot.utils.match import normalize
|
136
|
-
|
137
136
|
self.name = name
|
138
137
|
|
139
138
|
match = search_variable(name, "$@&%", ignore_errors=True)
|
@@ -146,9 +145,6 @@ class VariableMatcher:
|
|
146
145
|
self.normalized_name = str(normalize(self.base))
|
147
146
|
|
148
147
|
def __eq__(self, o: object) -> bool:
|
149
|
-
from robot.utils.normalizing import normalize
|
150
|
-
from robot.variables.search import search_variable
|
151
|
-
|
152
148
|
if isinstance(o, VariableMatcher):
|
153
149
|
return o.normalized_name == self.normalized_name
|
154
150
|
|
@@ -86,10 +86,10 @@ from robotcode.robot.utils.match import normalize, normalize_namespace
|
|
86
86
|
from robotcode.robot.utils.stubs import HasError, HasErrors
|
87
87
|
|
88
88
|
if get_robot_version() < (7, 0):
|
89
|
-
from robot.running.handlers import _PythonHandler, _PythonInitHandler
|
90
|
-
from robot.running.model import ResourceFile
|
91
|
-
from robot.running.usererrorhandler import UserErrorHandler
|
92
|
-
from robot.running.userkeyword import UserLibrary
|
89
|
+
from robot.running.handlers import _PythonHandler, _PythonInitHandler # pyright: ignore[reportMissingImports]
|
90
|
+
from robot.running.model import ResourceFile # pyright: ignore[reportMissingImports]
|
91
|
+
from robot.running.usererrorhandler import UserErrorHandler # pyright: ignore[reportMissingImports]
|
92
|
+
from robot.running.userkeyword import UserLibrary # pyright: ignore[reportMissingImports]
|
93
93
|
|
94
94
|
robot_notset = ArgInfo.NOTSET
|
95
95
|
|
@@ -1960,7 +1960,7 @@ def get_library_doc(
|
|
1960
1960
|
return_type=(
|
1961
1961
|
(
|
1962
1962
|
str(kw[1].args.return_type)
|
1963
|
-
if kw[1].args.return_type is not None and kw[1].args.return_type
|
1963
|
+
if kw[1].args.return_type is not None and kw[1].args.return_type is not type(None)
|
1964
1964
|
else None
|
1965
1965
|
)
|
1966
1966
|
if get_robot_version() >= (7, 0)
|
@@ -2636,7 +2636,7 @@ def get_model_doc(
|
|
2636
2636
|
message=error,
|
2637
2637
|
type_name="ModelError",
|
2638
2638
|
source=source,
|
2639
|
-
line_no=node.lineno,
|
2639
|
+
line_no=node.lineno, # type: ignore
|
2640
2640
|
)
|
2641
2641
|
)
|
2642
2642
|
if append_model_errors:
|
@@ -2648,7 +2648,7 @@ def get_model_doc(
|
|
2648
2648
|
message=e,
|
2649
2649
|
type_name="ModelError",
|
2650
2650
|
source=source,
|
2651
|
-
line_no=node.lineno,
|
2651
|
+
line_no=node.lineno, # type: ignore
|
2652
2652
|
)
|
2653
2653
|
)
|
2654
2654
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import ast
|
2
2
|
import enum
|
3
3
|
import itertools
|
4
|
-
import re
|
5
4
|
import time
|
6
5
|
import weakref
|
7
6
|
from collections import OrderedDict, defaultdict
|
@@ -97,9 +96,6 @@ from .library_doc import (
|
|
97
96
|
resolve_robot_variables,
|
98
97
|
)
|
99
98
|
|
100
|
-
EXTRACT_COMMENT_PATTERN = re.compile(r".*(?:^ *|\t+| {2,})#(?P<comment>.*)$")
|
101
|
-
ROBOTCODE_PATTERN = re.compile(r"(?P<marker>\brobotcode\b)\s*:\s*(?P<rule>\b\w+\b)")
|
102
|
-
|
103
99
|
|
104
100
|
class DiagnosticsError(Exception):
|
105
101
|
pass
|
@@ -454,7 +450,7 @@ class BlockVariableVisitor(OnlyArgumentsVisitor):
|
|
454
450
|
source=self.namespace.source,
|
455
451
|
)
|
456
452
|
|
457
|
-
if var_name not in self._results or type(self._results[var_name])
|
453
|
+
if var_name not in self._results or type(self._results[var_name]) is not type(var):
|
458
454
|
if isinstance(var, LocalVariableDefinition) or not any(
|
459
455
|
l for l in self.namespace.get_global_variables() if l.matcher == var.matcher
|
460
456
|
):
|
@@ -542,7 +538,7 @@ class BlockVariableVisitor(OnlyArgumentsVisitor):
|
|
542
538
|
source=self.namespace.source,
|
543
539
|
)
|
544
540
|
|
545
|
-
if var_name not in self._results or type(self._results[var_name])
|
541
|
+
if var_name not in self._results or type(self._results[var_name]) is type(var):
|
546
542
|
if isinstance(var, LocalVariableDefinition) or not any(
|
547
543
|
l for l in self.namespace.get_global_variables() if l.matcher == var.matcher
|
548
544
|
):
|
@@ -1803,8 +1799,6 @@ class Namespace:
|
|
1803
1799
|
related_information: Optional[List[DiagnosticRelatedInformation]] = None,
|
1804
1800
|
data: Optional[Any] = None,
|
1805
1801
|
) -> None:
|
1806
|
-
if self._should_ignore(range):
|
1807
|
-
return
|
1808
1802
|
|
1809
1803
|
self._diagnostics.append(
|
1810
1804
|
Diagnostic(
|
@@ -1840,12 +1834,7 @@ class Namespace:
|
|
1840
1834
|
start_time = time.monotonic()
|
1841
1835
|
|
1842
1836
|
try:
|
1843
|
-
result = NamespaceAnalyzer(
|
1844
|
-
self.model,
|
1845
|
-
self,
|
1846
|
-
self.create_finder(),
|
1847
|
-
self.get_ignored_lines(self.document) if self.document is not None else [],
|
1848
|
-
).run()
|
1837
|
+
result = NamespaceAnalyzer(self.model, self, self.create_finder()).run()
|
1849
1838
|
|
1850
1839
|
self._diagnostics += result.diagnostics
|
1851
1840
|
self._keyword_references = result.keyword_references
|
@@ -1916,42 +1905,6 @@ class Namespace:
|
|
1916
1905
|
handle_bdd_style=handle_bdd_style,
|
1917
1906
|
)
|
1918
1907
|
|
1919
|
-
@classmethod
|
1920
|
-
def get_ignored_lines(cls, document: TextDocument) -> List[int]:
|
1921
|
-
return document.get_cache(cls.__get_ignored_lines)
|
1922
|
-
|
1923
|
-
@staticmethod
|
1924
|
-
def __get_ignored_lines(document: TextDocument) -> List[int]:
|
1925
|
-
result = []
|
1926
|
-
lines = document.get_lines()
|
1927
|
-
for line_no, line in enumerate(lines):
|
1928
|
-
comment = EXTRACT_COMMENT_PATTERN.match(line)
|
1929
|
-
if comment and comment.group("comment"):
|
1930
|
-
for match in ROBOTCODE_PATTERN.finditer(comment.group("comment")):
|
1931
|
-
if match.group("rule") == "ignore":
|
1932
|
-
result.append(line_no)
|
1933
|
-
|
1934
|
-
return result
|
1935
|
-
|
1936
|
-
@classmethod
|
1937
|
-
def should_ignore(cls, document: Optional[TextDocument], range: Range) -> bool:
|
1938
|
-
return cls.__should_ignore(
|
1939
|
-
cls.get_ignored_lines(document) if document is not None else [],
|
1940
|
-
range,
|
1941
|
-
)
|
1942
|
-
|
1943
|
-
def _should_ignore(self, range: Range) -> bool:
|
1944
|
-
if self._ignored_lines is None:
|
1945
|
-
self._ignored_lines = self.get_ignored_lines(self.document) if self.document is not None else []
|
1946
|
-
|
1947
|
-
return self.__should_ignore(self._ignored_lines, range)
|
1948
|
-
|
1949
|
-
@staticmethod
|
1950
|
-
def __should_ignore(lines: List[int], range: Range) -> bool:
|
1951
|
-
import builtins
|
1952
|
-
|
1953
|
-
return any(line_no in lines for line_no in builtins.range(range.start.line, range.end.line + 1))
|
1954
|
-
|
1955
1908
|
|
1956
1909
|
class DiagnosticsEntry(NamedTuple):
|
1957
1910
|
message: str
|
@@ -2083,7 +2036,7 @@ class KeywordFinder:
|
|
2083
2036
|
DiagnosticsEntry(
|
2084
2037
|
self._create_multiple_keywords_found_message(name, found, implicit=False),
|
2085
2038
|
DiagnosticSeverity.ERROR,
|
2086
|
-
Error.
|
2039
|
+
Error.MULTIPLE_KEYWORDS,
|
2087
2040
|
)
|
2088
2041
|
)
|
2089
2042
|
raise CancelSearchError
|
@@ -2118,7 +2071,7 @@ class KeywordFinder:
|
|
2118
2071
|
DiagnosticsEntry(
|
2119
2072
|
self._create_multiple_keywords_found_message(name, found, implicit=False),
|
2120
2073
|
DiagnosticSeverity.ERROR,
|
2121
|
-
Error.
|
2074
|
+
Error.MULTIPLE_KEYWORDS,
|
2122
2075
|
)
|
2123
2076
|
)
|
2124
2077
|
raise CancelSearchError
|
@@ -2266,7 +2219,7 @@ class KeywordFinder:
|
|
2266
2219
|
DiagnosticsEntry(
|
2267
2220
|
self._create_multiple_keywords_found_message(name, found),
|
2268
2221
|
DiagnosticSeverity.ERROR,
|
2269
|
-
Error.
|
2222
|
+
Error.MULTIPLE_KEYWORDS,
|
2270
2223
|
)
|
2271
2224
|
)
|
2272
2225
|
raise CancelSearchError
|
@@ -2320,7 +2273,7 @@ class KeywordFinder:
|
|
2320
2273
|
DiagnosticsEntry(
|
2321
2274
|
self._create_multiple_keywords_found_message(name, found),
|
2322
2275
|
DiagnosticSeverity.ERROR,
|
2323
|
-
Error.
|
2276
|
+
Error.MULTIPLE_KEYWORDS,
|
2324
2277
|
)
|
2325
2278
|
)
|
2326
2279
|
raise CancelSearchError
|
@@ -2342,7 +2295,7 @@ class KeywordFinder:
|
|
2342
2295
|
DiagnosticsEntry(
|
2343
2296
|
self._create_custom_and_standard_keyword_conflict_warning_message(custom, standard),
|
2344
2297
|
DiagnosticSeverity.WARNING,
|
2345
|
-
Error.
|
2298
|
+
Error.CONFLICTING_LIBRARY_KEYWORDS,
|
2346
2299
|
)
|
2347
2300
|
)
|
2348
2301
|
|
@@ -117,14 +117,12 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
|
|
117
117
|
model: ast.AST,
|
118
118
|
namespace: Namespace,
|
119
119
|
finder: KeywordFinder,
|
120
|
-
ignored_lines: List[int],
|
121
120
|
) -> None:
|
122
121
|
super().__init__()
|
123
122
|
|
124
123
|
self.model = model
|
125
124
|
self.namespace = namespace
|
126
125
|
self.finder = finder
|
127
|
-
self._ignored_lines = ignored_lines
|
128
126
|
|
129
127
|
self.current_testcase_or_keyword_name: Optional[str] = None
|
130
128
|
self.test_template: Optional[TestTemplate] = None
|
@@ -261,8 +259,6 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
|
|
261
259
|
)
|
262
260
|
)
|
263
261
|
)
|
264
|
-
# r.start.character = 0
|
265
|
-
# r.end.character = 0
|
266
262
|
|
267
263
|
var_def = self.namespace.find_variable(
|
268
264
|
name,
|
@@ -450,15 +446,6 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
|
|
450
446
|
finally:
|
451
447
|
self.node_stack = self.node_stack[:-1]
|
452
448
|
|
453
|
-
def _should_ignore(self, range: Range) -> bool:
|
454
|
-
import builtins
|
455
|
-
|
456
|
-
for line_no in builtins.range(range.start.line, range.end.line + 1):
|
457
|
-
if line_no in self._ignored_lines:
|
458
|
-
return True
|
459
|
-
|
460
|
-
return False
|
461
|
-
|
462
449
|
def append_diagnostics(
|
463
450
|
self,
|
464
451
|
range: Range,
|
@@ -471,8 +458,6 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
|
|
471
458
|
related_information: Optional[List[DiagnosticRelatedInformation]] = None,
|
472
459
|
data: Optional[Any] = None,
|
473
460
|
) -> None:
|
474
|
-
if self._should_ignore(range):
|
475
|
-
return
|
476
461
|
|
477
462
|
self._diagnostics.append(
|
478
463
|
Diagnostic(
|
@@ -1167,7 +1152,7 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
|
|
1167
1152
|
for v in entries.values():
|
1168
1153
|
if v.import_source == self.namespace.source and v.import_range == range_from_token(name_token):
|
1169
1154
|
for k in self._namespace_references:
|
1170
|
-
if type(k)
|
1155
|
+
if type(k) is type(v) and k.library_doc.source_or_origin == v.library_doc.source_or_origin:
|
1171
1156
|
self._namespace_references[k].add(
|
1172
1157
|
Location(self.namespace.document.document_uri, v.import_range)
|
1173
1158
|
)
|
@@ -1192,7 +1177,7 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
|
|
1192
1177
|
for v in entries.values():
|
1193
1178
|
if v.import_source == self.namespace.source and v.import_range == range_from_token(name_token):
|
1194
1179
|
for k in self._namespace_references:
|
1195
|
-
if type(k)
|
1180
|
+
if type(k) is type(v) and k.library_doc.source_or_origin == v.library_doc.source_or_origin:
|
1196
1181
|
self._namespace_references[k].add(
|
1197
1182
|
Location(self.namespace.document.document_uri, v.import_range)
|
1198
1183
|
)
|
@@ -1217,7 +1202,7 @@ class NamespaceAnalyzer(Visitor, ModelHelper):
|
|
1217
1202
|
for v in entries.values():
|
1218
1203
|
if v.import_source == self.namespace.source and v.import_range == range_from_token(name_token):
|
1219
1204
|
for k in self._namespace_references:
|
1220
|
-
if type(k)
|
1205
|
+
if type(k) is type(v) and k.library_doc.source_or_origin == v.library_doc.source_or_origin:
|
1221
1206
|
self._namespace_references[k].add(
|
1222
1207
|
Location(self.namespace.document.document_uri, v.import_range)
|
1223
1208
|
)
|
robotcode/robot/utils/ast.py
CHANGED
@@ -129,10 +129,10 @@ def range_from_node(
|
|
129
129
|
return Range(start=first_range.start, end=last_range.end)
|
130
130
|
|
131
131
|
return Range(
|
132
|
-
start=Position(line=node.lineno - 1, character=node.col_offset),
|
132
|
+
start=Position(line=node.lineno - 1, character=node.col_offset), # type: ignore
|
133
133
|
end=Position(
|
134
|
-
line=node.end_lineno - 1 if node.end_lineno is not None else -1,
|
135
|
-
character=node.end_col_offset if node.end_col_offset is not None else -1,
|
134
|
+
line=node.end_lineno - 1 if node.end_lineno is not None else -1, # type: ignore
|
135
|
+
character=node.end_col_offset if node.end_col_offset is not None else -1, # type: ignore
|
136
136
|
),
|
137
137
|
)
|
138
138
|
|
robotcode/robot/utils/match.py
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
from functools import lru_cache
|
2
2
|
|
3
|
+
_transform_table = str.maketrans("", "", "_ ")
|
4
|
+
|
3
5
|
|
4
6
|
@lru_cache(maxsize=5000)
|
5
7
|
def normalize(text: str) -> str:
|
6
|
-
return text.lower().replace("_", "").replace(" ", "")
|
8
|
+
# return text.lower().replace("_", "").replace(" ", "")
|
9
|
+
return text.casefold().translate(_transform_table)
|
7
10
|
|
8
11
|
|
9
12
|
@lru_cache(maxsize=5000)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: robotcode-robot
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.84.0
|
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.
|
29
|
+
Requires-Dist: robotcode-core==0.84.0
|
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,29 +1,30 @@
|
|
1
1
|
robotcode/robot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
robotcode/robot/__version__.py,sha256=
|
2
|
+
robotcode/robot/__version__.py,sha256=KIiYae8LGfAm2z2vAqeoEPgeYngLtYMZnQCGOUKk3Nk,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
|
6
|
-
robotcode/robot/config/model.py,sha256=
|
6
|
+
robotcode/robot/config/model.py,sha256=AZFvuMCUuws5EbvX_Bk-b96tiKnIqm7REU_wO1RLJFM,88462
|
7
7
|
robotcode/robot/config/utils.py,sha256=c_WZg39DJgM6kXcAH_h-v68qhf1eStJ0TslTawaJoZw,2827
|
8
8
|
robotcode/robot/diagnostics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
-
robotcode/robot/diagnostics/
|
10
|
-
robotcode/robot/diagnostics/
|
11
|
-
robotcode/robot/diagnostics/
|
9
|
+
robotcode/robot/diagnostics/diagnostics_modifier.py,sha256=9AFptQsdw_TvgBkKqutpvI8WKsOUXipXQDOExarJJy4,6903
|
10
|
+
robotcode/robot/diagnostics/document_cache_helper.py,sha256=pa9AdSbEFZJ6VSdZluGyfzyZPjzBfNFAv5pXJEM-7fc,22664
|
11
|
+
robotcode/robot/diagnostics/entities.py,sha256=AtrqPAS3XUC-8VpFmqMXfMKjQHmfxXZlyGWWFaEBpQA,10979
|
12
|
+
robotcode/robot/diagnostics/errors.py,sha256=1DNxi1lbz4HAWocCi-4zY1IgUGO3J04kY_sBgYfkeX0,1520
|
12
13
|
robotcode/robot/diagnostics/imports_manager.py,sha256=qE__lm0Hsj3R0gUauXRmbWJPYihNjk3O-c5hcICGQjc,56251
|
13
|
-
robotcode/robot/diagnostics/library_doc.py,sha256=
|
14
|
+
robotcode/robot/diagnostics/library_doc.py,sha256=CHgyC9GMRQFP3fGTxWa139rIcGIk8Ys6Q_ZIDSgse7k,97324
|
14
15
|
robotcode/robot/diagnostics/model_helper.py,sha256=_5ixKKMrb-nY-uvV8_WjJ1rlNlz7gT7kHM5NYi_hjVg,30232
|
15
|
-
robotcode/robot/diagnostics/namespace.py,sha256=
|
16
|
-
robotcode/robot/diagnostics/namespace_analyzer.py,sha256=
|
16
|
+
robotcode/robot/diagnostics/namespace.py,sha256=IwWie61qd5iGMdpI285IH0jKgJWS5xRmt98lldTHxSw,89539
|
17
|
+
robotcode/robot/diagnostics/namespace_analyzer.py,sha256=G9xgJ-hPunXxfpKmZEf0xop8sIp4IhjdM3Z3C9vQU-g,50479
|
17
18
|
robotcode/robot/diagnostics/workspace_config.py,sha256=lWNq1KmGGJ9cHFNHn0QTCBHHzgz4AewTw0l-W4TKrj0,1803
|
18
19
|
robotcode/robot/utils/__init__.py,sha256=OjNPMn_XSnfaMCyKd8Kmq6vlRt6mIGlzW4qiiD3ykUg,447
|
19
|
-
robotcode/robot/utils/ast.py,sha256=
|
20
|
+
robotcode/robot/utils/ast.py,sha256=p3S6f1mmimI47HVchGezt93jygEqs-oxKeiyqbUm0R4,10241
|
20
21
|
robotcode/robot/utils/markdownformatter.py,sha256=IVVnCYJLpX8-sK73n3AjtjBVirB-Xa3U2ZudAtFUOD0,11621
|
21
|
-
robotcode/robot/utils/match.py,sha256=
|
22
|
+
robotcode/robot/utils/match.py,sha256=ofyfXgrvVddl7a064Dk5Kiqp3a-n_6gTIgqDbL3E80Q,632
|
22
23
|
robotcode/robot/utils/robot_path.py,sha256=qKBh1cEnReBBLKkWu4gB9EzM-scAwE4xJc1m6v2LRN0,1786
|
23
24
|
robotcode/robot/utils/stubs.py,sha256=6-DMI_CQVJHDgG13t-zINKGCRb_Q7MQPm0_AkfhAEvE,748
|
24
25
|
robotcode/robot/utils/variables.py,sha256=fEl8S37lb_mD4hn2MZRAlkiuLGBjAOeZVK0r2o2CfPw,742
|
25
26
|
robotcode/robot/utils/visitor.py,sha256=uYLqEhGPmzWKWI3SSrmCaYMwtKvNShvbiPZ4b3FavX8,3241
|
26
|
-
robotcode_robot-0.
|
27
|
-
robotcode_robot-0.
|
28
|
-
robotcode_robot-0.
|
29
|
-
robotcode_robot-0.
|
27
|
+
robotcode_robot-0.84.0.dist-info/METADATA,sha256=L3XwWzyT6nrMj9hWOPAplkITehYAVXkbDSqkT9porE8,2240
|
28
|
+
robotcode_robot-0.84.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
29
|
+
robotcode_robot-0.84.0.dist-info/licenses/LICENSE.txt,sha256=B05uMshqTA74s-0ltyHKI6yoPfJ3zYgQbvcXfDVGFf8,10280
|
30
|
+
robotcode_robot-0.84.0.dist-info/RECORD,,
|
File without changes
|