robotcode-robot 1.3.0.dev3__py3-none-any.whl → 1.3.0.dev5__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/diagnostics/entities.py +18 -2
- robotcode/robot/diagnostics/keyword_finder.py +43 -12
- robotcode/robot/diagnostics/library_doc.py +11 -5
- robotcode/robot/diagnostics/namespace.py +225 -194
- robotcode/robot/diagnostics/namespace_analyzer.py +173 -157
- robotcode/robot/utils/ast.py +7 -5
- robotcode/robot/utils/variables.py +99 -24
- {robotcode_robot-1.3.0.dev3.dist-info → robotcode_robot-1.3.0.dev5.dist-info}/METADATA +2 -2
- {robotcode_robot-1.3.0.dev3.dist-info → robotcode_robot-1.3.0.dev5.dist-info}/RECORD +12 -12
- {robotcode_robot-1.3.0.dev3.dist-info → robotcode_robot-1.3.0.dev5.dist-info}/WHEEL +0 -0
- {robotcode_robot-1.3.0.dev3.dist-info → robotcode_robot-1.3.0.dev5.dist-info}/licenses/LICENSE.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
import ast
|
2
2
|
import functools
|
3
|
-
import itertools
|
4
3
|
import os
|
4
|
+
import re
|
5
5
|
import token as python_token
|
6
6
|
from collections import defaultdict
|
7
7
|
from concurrent.futures import CancelledError
|
@@ -47,6 +47,7 @@ from robotcode.core.utils.logging import LoggingDescriptor
|
|
47
47
|
|
48
48
|
from ..utils import get_robot_version
|
49
49
|
from ..utils.ast import (
|
50
|
+
get_first_variable_token,
|
50
51
|
is_not_variable_token,
|
51
52
|
range_from_node,
|
52
53
|
range_from_node_or_token,
|
@@ -58,14 +59,13 @@ from ..utils.variables import (
|
|
58
59
|
InvalidVariableError,
|
59
60
|
VariableMatcher,
|
60
61
|
contains_variable,
|
61
|
-
is_scalar_assign,
|
62
|
-
is_variable,
|
63
62
|
search_variable,
|
64
63
|
split_from_equals,
|
65
64
|
)
|
66
65
|
from ..utils.visitor import Visitor
|
67
66
|
from .entities import (
|
68
67
|
ArgumentDefinition,
|
68
|
+
EmbeddedArgumentDefinition,
|
69
69
|
EnvironmentVariableDefinition,
|
70
70
|
GlobalVariableDefinition,
|
71
71
|
LibraryEntry,
|
@@ -195,14 +195,15 @@ class NamespaceAnalyzer(Visitor):
|
|
195
195
|
if name_token.value is not None:
|
196
196
|
matcher = search_variable(
|
197
197
|
name_token.value[:-1].rstrip() if name_token.value.endswith("=") else name_token.value,
|
198
|
+
parse_type=True,
|
198
199
|
ignore_errors=True,
|
199
200
|
)
|
200
|
-
if not matcher.is_assign(allow_assign_mark=True) or matcher.name is None:
|
201
|
+
if not matcher.is_assign(allow_assign_mark=True, allow_nested=True) or matcher.name is None:
|
201
202
|
return
|
202
203
|
|
203
204
|
name = matcher.name
|
204
205
|
|
205
|
-
stripped_name_token = strip_variable_token(name_token, matcher=matcher)
|
206
|
+
stripped_name_token = strip_variable_token(name_token, matcher=matcher, parse_type=True)
|
206
207
|
|
207
208
|
r = range_from_token(stripped_name_token)
|
208
209
|
|
@@ -221,14 +222,15 @@ class NamespaceAnalyzer(Visitor):
|
|
221
222
|
var_def = VariableDefinition(
|
222
223
|
name=name,
|
223
224
|
name_token=stripped_name_token,
|
224
|
-
line_no=
|
225
|
-
col_offset=
|
226
|
-
end_line_no=
|
227
|
-
end_col_offset=
|
225
|
+
line_no=stripped_name_token.lineno,
|
226
|
+
col_offset=stripped_name_token.col_offset,
|
227
|
+
end_line_no=stripped_name_token.lineno,
|
228
|
+
end_col_offset=stripped_name_token.end_col_offset,
|
228
229
|
source=self._namespace.source,
|
229
230
|
has_value=has_value,
|
230
231
|
resolvable=True,
|
231
232
|
value=value,
|
233
|
+
value_type=matcher.type,
|
232
234
|
)
|
233
235
|
|
234
236
|
add_to_references = True
|
@@ -322,26 +324,25 @@ class NamespaceAnalyzer(Visitor):
|
|
322
324
|
|
323
325
|
if get_robot_version() >= (7, 0):
|
324
326
|
|
325
|
-
def visit_Var(self, node:
|
327
|
+
def visit_Var(self, node: Var) -> None: # noqa: N802
|
326
328
|
self._analyze_statement_variables(node)
|
327
329
|
|
328
|
-
|
329
|
-
if
|
330
|
+
name_token = node.get_token(Token.VARIABLE)
|
331
|
+
if name_token is None:
|
330
332
|
return
|
331
333
|
|
332
334
|
try:
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
335
|
+
matcher = search_variable(
|
336
|
+
name_token.value[:-1].rstrip() if name_token.value.endswith("=") else name_token.value,
|
337
|
+
parse_type=True,
|
338
|
+
ignore_errors=True,
|
339
|
+
)
|
340
|
+
if not matcher.is_assign(allow_assign_mark=True) or matcher.name is None:
|
338
341
|
return
|
339
342
|
|
340
|
-
|
341
|
-
Token(variable.type, var_name, variable.lineno, variable.col_offset, variable.error)
|
342
|
-
)
|
343
|
+
stripped_name_token = strip_variable_token(name_token, matcher=matcher, parse_type=True)
|
343
344
|
|
344
|
-
scope =
|
345
|
+
scope = node.scope
|
345
346
|
if scope:
|
346
347
|
scope = scope.upper()
|
347
348
|
|
@@ -355,13 +356,14 @@ class NamespaceAnalyzer(Visitor):
|
|
355
356
|
var_type = LocalVariableDefinition
|
356
357
|
|
357
358
|
var = var_type(
|
358
|
-
name=
|
359
|
-
name_token=strip_variable_token(
|
360
|
-
line_no=
|
361
|
-
col_offset=
|
362
|
-
end_line_no=
|
363
|
-
end_col_offset=
|
359
|
+
name=matcher.name,
|
360
|
+
name_token=strip_variable_token(stripped_name_token),
|
361
|
+
line_no=stripped_name_token.lineno,
|
362
|
+
col_offset=stripped_name_token.col_offset,
|
363
|
+
end_line_no=stripped_name_token.lineno,
|
364
|
+
end_col_offset=stripped_name_token.end_col_offset,
|
364
365
|
source=self._namespace.source,
|
366
|
+
value_type=matcher.type,
|
365
367
|
)
|
366
368
|
|
367
369
|
if var.matcher not in self._variables:
|
@@ -371,7 +373,7 @@ class NamespaceAnalyzer(Visitor):
|
|
371
373
|
existing_var = self._variables[var.matcher]
|
372
374
|
|
373
375
|
location = Location(
|
374
|
-
self._namespace.document_uri, range_from_token(strip_variable_token(
|
376
|
+
self._namespace.document_uri, range_from_token(strip_variable_token(stripped_name_token))
|
375
377
|
)
|
376
378
|
self._variable_references[existing_var].add(location)
|
377
379
|
if existing_var in self._overridden_variables:
|
@@ -1135,6 +1137,8 @@ class NamespaceAnalyzer(Visitor):
|
|
1135
1137
|
self._current_testcase_or_keyword_name = None
|
1136
1138
|
self._current_keyword_doc = None
|
1137
1139
|
|
1140
|
+
EMBEDDED_ARGUMENTS_MATCHER = re.compile("([^:]+): ([^:]+)(:(.*))?")
|
1141
|
+
|
1138
1142
|
def visit_KeywordName(self, node: KeywordName) -> None: # noqa: N802
|
1139
1143
|
name_token = node.get_token(Token.KEYWORD_NAME)
|
1140
1144
|
|
@@ -1144,14 +1148,28 @@ class NamespaceAnalyzer(Visitor):
|
|
1144
1148
|
tokenize_variables(name_token, identifiers="$", ignore_errors=True),
|
1145
1149
|
):
|
1146
1150
|
if variable_token.value:
|
1147
|
-
|
1148
|
-
if
|
1151
|
+
matcher = search_variable(variable_token.value, "$", ignore_errors=True)
|
1152
|
+
if matcher.base is None:
|
1149
1153
|
continue
|
1150
|
-
|
1151
|
-
|
1154
|
+
if ":" not in matcher.base:
|
1155
|
+
name = matcher.base
|
1156
|
+
pattern = None
|
1157
|
+
type = None
|
1158
|
+
elif get_robot_version() >= (7, 3):
|
1159
|
+
re_match = self.EMBEDDED_ARGUMENTS_MATCHER.fullmatch(matcher.base)
|
1160
|
+
if re_match:
|
1161
|
+
name, type, _, pattern = re_match.groups()
|
1162
|
+
else:
|
1163
|
+
name, pattern = matcher.base.split(":", 1)
|
1164
|
+
type = None
|
1165
|
+
else:
|
1166
|
+
name, pattern = matcher.base.split(":", 1)
|
1167
|
+
type = None
|
1168
|
+
|
1169
|
+
full_name = f"{matcher.identifier}{{{name}}}"
|
1152
1170
|
var_token = strip_variable_token(variable_token)
|
1153
1171
|
var_token.value = name
|
1154
|
-
arg_def =
|
1172
|
+
arg_def = EmbeddedArgumentDefinition(
|
1155
1173
|
name=full_name,
|
1156
1174
|
name_token=var_token,
|
1157
1175
|
line_no=variable_token.lineno,
|
@@ -1160,32 +1178,19 @@ class NamespaceAnalyzer(Visitor):
|
|
1160
1178
|
end_col_offset=variable_token.end_col_offset,
|
1161
1179
|
source=self._namespace.source,
|
1162
1180
|
keyword_doc=self._current_keyword_doc,
|
1181
|
+
value_type=type,
|
1182
|
+
pattern=pattern,
|
1163
1183
|
)
|
1164
1184
|
|
1165
1185
|
self._variables[arg_def.matcher] = arg_def
|
1166
1186
|
self._variable_references[arg_def] = set()
|
1167
1187
|
|
1168
|
-
def _get_variable_token(self, token: Token) -> Optional[Token]:
|
1169
|
-
return next(
|
1170
|
-
(
|
1171
|
-
v
|
1172
|
-
for v in itertools.dropwhile(
|
1173
|
-
lambda t: t.type in Token.NON_DATA_TOKENS,
|
1174
|
-
tokenize_variables(token, ignore_errors=True, extra_types={Token.VARIABLE}),
|
1175
|
-
)
|
1176
|
-
if v.type == Token.VARIABLE
|
1177
|
-
),
|
1178
|
-
None,
|
1179
|
-
)
|
1180
|
-
|
1181
1188
|
def _visit_Arguments(self, node: Statement) -> None: # noqa: N802
|
1182
1189
|
args: Dict[VariableMatcher, VariableDefinition] = {}
|
1183
1190
|
|
1184
|
-
|
1185
|
-
|
1186
|
-
for argument_token in arguments:
|
1191
|
+
for argument_token in node.get_tokens(Token.ARGUMENT):
|
1187
1192
|
try:
|
1188
|
-
argument =
|
1193
|
+
argument = get_first_variable_token(argument_token)
|
1189
1194
|
|
1190
1195
|
if argument is not None and argument.value != "@{}":
|
1191
1196
|
if len(argument_token.value) > len(argument.value):
|
@@ -1199,18 +1204,23 @@ class NamespaceAnalyzer(Visitor):
|
|
1199
1204
|
)
|
1200
1205
|
)
|
1201
1206
|
|
1202
|
-
matcher = VariableMatcher(argument.value)
|
1207
|
+
matcher = VariableMatcher(argument.value, parse_type=True, ignore_errors=True)
|
1208
|
+
if not matcher.is_variable() or matcher.name is None:
|
1209
|
+
continue
|
1210
|
+
|
1211
|
+
stripped_argument_token = strip_variable_token(argument, parse_type=True, matcher=matcher)
|
1203
1212
|
|
1204
1213
|
if matcher not in args:
|
1205
1214
|
arg_def = ArgumentDefinition(
|
1206
|
-
name=
|
1207
|
-
name_token=
|
1208
|
-
line_no=
|
1209
|
-
col_offset=
|
1210
|
-
end_line_no=
|
1211
|
-
end_col_offset=
|
1215
|
+
name=matcher.name,
|
1216
|
+
name_token=stripped_argument_token,
|
1217
|
+
line_no=stripped_argument_token.lineno,
|
1218
|
+
col_offset=stripped_argument_token.col_offset,
|
1219
|
+
end_line_no=stripped_argument_token.lineno,
|
1220
|
+
end_col_offset=stripped_argument_token.end_col_offset,
|
1212
1221
|
source=self._namespace.source,
|
1213
1222
|
keyword_doc=self._current_keyword_doc,
|
1223
|
+
value_type=matcher.type,
|
1214
1224
|
)
|
1215
1225
|
|
1216
1226
|
args[matcher] = arg_def
|
@@ -1220,10 +1230,7 @@ class NamespaceAnalyzer(Visitor):
|
|
1220
1230
|
self._variable_references[arg_def] = set()
|
1221
1231
|
else:
|
1222
1232
|
self._variable_references[args[matcher]].add(
|
1223
|
-
Location(
|
1224
|
-
self._namespace.document_uri,
|
1225
|
-
range_from_token(strip_variable_token(argument)),
|
1226
|
-
)
|
1233
|
+
Location(self._namespace.document_uri, range_from_token(stripped_argument_token))
|
1227
1234
|
)
|
1228
1235
|
|
1229
1236
|
except (VariableError, InvalidVariableError):
|
@@ -1232,75 +1239,79 @@ class NamespaceAnalyzer(Visitor):
|
|
1232
1239
|
def _analyze_assign_statement(self, node: Statement) -> None:
|
1233
1240
|
token_with_assign_mark: Optional[Token] = None
|
1234
1241
|
for assign_token in node.get_tokens(Token.ASSIGN):
|
1235
|
-
|
1242
|
+
try:
|
1243
|
+
if token_with_assign_mark is not None:
|
1244
|
+
r = range_from_token(token_with_assign_mark)
|
1245
|
+
r.start.character = r.end.character - 1
|
1246
|
+
self._append_diagnostics(
|
1247
|
+
range=r,
|
1248
|
+
message="Assign mark '=' can be used only with the last variable.",
|
1249
|
+
severity=DiagnosticSeverity.ERROR,
|
1250
|
+
code=Error.ASSIGN_MARK_ALLOWED_ONLY_ON_LAST_VAR,
|
1251
|
+
)
|
1236
1252
|
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
code=Error.ASSIGN_MARK_ALLOWED_ONLY_ON_LAST_VAR,
|
1253
|
+
if assign_token.value.endswith("="):
|
1254
|
+
token_with_assign_mark = assign_token
|
1255
|
+
|
1256
|
+
matcher = search_variable(
|
1257
|
+
assign_token.value[:-1].rstrip() if assign_token.value.endswith("=") else assign_token.value,
|
1258
|
+
parse_type=True,
|
1259
|
+
ignore_errors=True,
|
1245
1260
|
)
|
1246
1261
|
|
1247
|
-
|
1248
|
-
|
1262
|
+
if not matcher.is_assign(allow_assign_mark=True) or matcher.name is None:
|
1263
|
+
return
|
1249
1264
|
|
1250
|
-
|
1251
|
-
if variable_token is not None:
|
1252
|
-
matcher = VariableMatcher(variable_token.value)
|
1253
|
-
stripped_variable_token = strip_variable_token(variable_token, matcher=matcher)
|
1254
|
-
if matcher.name is None:
|
1255
|
-
return
|
1265
|
+
stripped_name_token = strip_variable_token(assign_token, matcher=matcher, parse_type=True)
|
1256
1266
|
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
),
|
1271
|
-
)
|
1272
|
-
return
|
1273
|
-
else:
|
1274
|
-
existing_var = next(
|
1275
|
-
(
|
1276
|
-
v
|
1277
|
-
for k, v in self._variables.items()
|
1278
|
-
if k == matcher
|
1279
|
-
and v.type in [VariableDefinitionType.ARGUMENT, VariableDefinitionType.LOCAL_VARIABLE]
|
1267
|
+
if matcher.items:
|
1268
|
+
existing_var = self._find_variable(matcher.name)
|
1269
|
+
if existing_var is None:
|
1270
|
+
self._handle_find_variable_result(
|
1271
|
+
stripped_name_token,
|
1272
|
+
VariableNotFoundDefinition(
|
1273
|
+
stripped_name_token.lineno,
|
1274
|
+
stripped_name_token.col_offset,
|
1275
|
+
stripped_name_token.lineno,
|
1276
|
+
stripped_name_token.end_col_offset,
|
1277
|
+
self._namespace.source,
|
1278
|
+
matcher.name,
|
1279
|
+
stripped_name_token,
|
1280
1280
|
),
|
1281
|
-
None,
|
1282
1281
|
)
|
1282
|
+
return
|
1283
|
+
else:
|
1284
|
+
existing_var = next(
|
1285
|
+
(
|
1286
|
+
v
|
1287
|
+
for k, v in self._variables.items()
|
1288
|
+
if k == matcher
|
1289
|
+
and v.type in [VariableDefinitionType.ARGUMENT, VariableDefinitionType.LOCAL_VARIABLE]
|
1290
|
+
),
|
1291
|
+
None,
|
1292
|
+
)
|
1283
1293
|
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1290
|
-
|
1291
|
-
|
1292
|
-
|
1293
|
-
|
1294
|
-
|
1295
|
-
|
1296
|
-
|
1297
|
-
|
1298
|
-
|
1299
|
-
|
1300
|
-
|
1301
|
-
|
1302
|
-
)
|
1294
|
+
if existing_var is None:
|
1295
|
+
var_def = LocalVariableDefinition(
|
1296
|
+
name=matcher.name,
|
1297
|
+
name_token=stripped_name_token,
|
1298
|
+
line_no=stripped_name_token.lineno,
|
1299
|
+
col_offset=stripped_name_token.col_offset,
|
1300
|
+
end_line_no=stripped_name_token.lineno,
|
1301
|
+
end_col_offset=stripped_name_token.end_col_offset,
|
1302
|
+
source=self._namespace.source,
|
1303
|
+
value_type=matcher.type,
|
1304
|
+
)
|
1305
|
+
self._variables[matcher] = var_def
|
1306
|
+
self._variable_references[var_def] = set()
|
1307
|
+
self._local_variable_assignments[var_def].add(var_def.range)
|
1308
|
+
else:
|
1309
|
+
self._variable_references[existing_var].add(
|
1310
|
+
Location(
|
1311
|
+
self._namespace.document_uri,
|
1312
|
+
range_from_token(stripped_name_token),
|
1303
1313
|
)
|
1314
|
+
)
|
1304
1315
|
|
1305
1316
|
except (VariableError, InvalidVariableError):
|
1306
1317
|
pass
|
@@ -1313,24 +1324,27 @@ class NamespaceAnalyzer(Visitor):
|
|
1313
1324
|
def visit_ForHeader(self, node: Statement) -> None: # noqa: N802
|
1314
1325
|
self._analyze_statement_variables(node)
|
1315
1326
|
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
if
|
1320
|
-
existing_var = self._find_variable(
|
1327
|
+
for variable_token in node.get_tokens(Token.VARIABLE):
|
1328
|
+
matcher = search_variable(variable_token.value, ignore_errors=True, parse_type=True)
|
1329
|
+
|
1330
|
+
if matcher.name is not None and matcher.is_scalar_assign():
|
1331
|
+
existing_var = self._find_variable(matcher.name)
|
1332
|
+
|
1333
|
+
stripped_variable_token = strip_variable_token(variable_token, parse_type=True, matcher=matcher)
|
1321
1334
|
|
1322
1335
|
if existing_var is None or existing_var.type not in [
|
1323
1336
|
VariableDefinitionType.ARGUMENT,
|
1324
1337
|
VariableDefinitionType.LOCAL_VARIABLE,
|
1325
1338
|
]:
|
1326
1339
|
var_def = LocalVariableDefinition(
|
1327
|
-
name=
|
1328
|
-
name_token=
|
1329
|
-
line_no=
|
1330
|
-
col_offset=
|
1331
|
-
end_line_no=
|
1332
|
-
end_col_offset=
|
1340
|
+
name=matcher.name,
|
1341
|
+
name_token=stripped_variable_token,
|
1342
|
+
line_no=stripped_variable_token.lineno,
|
1343
|
+
col_offset=stripped_variable_token.col_offset,
|
1344
|
+
end_line_no=stripped_variable_token.lineno,
|
1345
|
+
end_col_offset=stripped_variable_token.end_col_offset,
|
1333
1346
|
source=self._namespace.source,
|
1347
|
+
value_type=matcher.type,
|
1334
1348
|
)
|
1335
1349
|
self._variables[var_def.matcher] = var_def
|
1336
1350
|
self._variable_references[var_def] = set()
|
@@ -1342,7 +1356,7 @@ class NamespaceAnalyzer(Visitor):
|
|
1342
1356
|
self._variable_references[existing_var].add(
|
1343
1357
|
Location(
|
1344
1358
|
self._namespace.document_uri,
|
1345
|
-
range_from_token(
|
1359
|
+
range_from_token(stripped_variable_token),
|
1346
1360
|
)
|
1347
1361
|
)
|
1348
1362
|
|
@@ -1352,31 +1366,33 @@ class NamespaceAnalyzer(Visitor):
|
|
1352
1366
|
|
1353
1367
|
variable_token = node.get_token(Token.VARIABLE)
|
1354
1368
|
|
1355
|
-
if variable_token is not None
|
1369
|
+
if variable_token is not None:
|
1356
1370
|
try:
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
)
|
1369
|
-
|
1370
|
-
)
|
1371
|
-
|
1372
|
-
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
|
1378
|
-
|
1379
|
-
|
1371
|
+
matcher = search_variable(variable_token.value, ignore_errors=True)
|
1372
|
+
if not matcher.is_scalar_assign():
|
1373
|
+
return
|
1374
|
+
|
1375
|
+
if (
|
1376
|
+
next(
|
1377
|
+
(
|
1378
|
+
k
|
1379
|
+
for k, v in self._variables.items()
|
1380
|
+
if k == matcher
|
1381
|
+
and v.type in [VariableDefinitionType.ARGUMENT, VariableDefinitionType.LOCAL_VARIABLE]
|
1382
|
+
),
|
1383
|
+
None,
|
1384
|
+
)
|
1385
|
+
is None
|
1386
|
+
):
|
1387
|
+
self._variables[matcher] = LocalVariableDefinition(
|
1388
|
+
name=variable_token.value,
|
1389
|
+
name_token=strip_variable_token(variable_token),
|
1390
|
+
line_no=variable_token.lineno,
|
1391
|
+
col_offset=variable_token.col_offset,
|
1392
|
+
end_line_no=variable_token.lineno,
|
1393
|
+
end_col_offset=variable_token.end_col_offset,
|
1394
|
+
source=self._namespace.source,
|
1395
|
+
)
|
1380
1396
|
|
1381
1397
|
except (VariableError, InvalidVariableError):
|
1382
1398
|
pass
|
robotcode/robot/utils/ast.py
CHANGED
@@ -326,10 +326,12 @@ def iter_over_keyword_names_and_owners(
|
|
326
326
|
yield ".".join(tokens[:i]), ".".join(tokens[i:])
|
327
327
|
|
328
328
|
|
329
|
-
def strip_variable_token(
|
330
|
-
|
329
|
+
def strip_variable_token(
|
330
|
+
token: Token, identifiers: str = "$@&%*", parse_type: bool = False, matcher: Optional[VariableMatcher] = None
|
331
|
+
) -> Token:
|
332
|
+
if token.type in [Token.VARIABLE, Token.ASSIGN]:
|
331
333
|
if matcher is None:
|
332
|
-
matcher = search_variable(token.value, identifiers, ignore_errors=True)
|
334
|
+
matcher = search_variable(token.value, identifiers, parse_type=parse_type, ignore_errors=True)
|
333
335
|
|
334
336
|
if matcher.is_variable():
|
335
337
|
value = matcher.base
|
@@ -346,13 +348,13 @@ def strip_variable_token(token: Token, identifiers: str = "$@&%*", matcher: Opti
|
|
346
348
|
return token
|
347
349
|
|
348
350
|
|
349
|
-
def
|
351
|
+
def get_first_variable_token(token: Token, extra_types: Optional[Set[str]] = None) -> Optional[Token]:
|
350
352
|
return next(
|
351
353
|
(
|
352
354
|
v
|
353
355
|
for v in itertools.dropwhile(
|
354
356
|
lambda t: t.type in Token.NON_DATA_TOKENS,
|
355
|
-
tokenize_variables(token, ignore_errors=True),
|
357
|
+
tokenize_variables(token, ignore_errors=True, extra_types=extra_types),
|
356
358
|
)
|
357
359
|
if v.type == Token.VARIABLE
|
358
360
|
),
|