Skip to content

Commit 7428418

Browse files
committed
correct handling of argument definition wich contains a default value with variable
1 parent 7f688cb commit 7428418

File tree

2 files changed

+86
-46
lines changed

2 files changed

+86
-46
lines changed

robotcode/language_server/robotframework/diagnostics/namespace.py

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,19 @@ async def visit_Variable(self, node: ast.AST) -> None: # noqa: N802
141141

142142

143143
class BlockVariableVisitor(AsyncVisitor):
144-
async def get(self, source: str, model: ast.AST, position: Optional[Position] = None) -> List[VariableDefinition]:
144+
def __init__(self, source: str, position: Optional[Position] = None, in_args: bool = True) -> None:
145+
super().__init__()
146+
145147
self.source = source
146148
self.position = position
149+
self.in_args = in_args
147150

148151
self._results: Dict[str, VariableDefinition] = {}
149152

153+
async def get(self, model: ast.AST) -> List[VariableDefinition]:
154+
155+
self._results = {}
156+
150157
await self.visit(model)
151158

152159
return list(self._results.values())
@@ -178,10 +185,10 @@ async def visit_KeywordName(self, node: ast.AST) -> None: # noqa: N802
178185
self._results[name] = ArgumentDefinition(
179186
name=name,
180187
name_token=strip_variable_token(variable_token),
181-
line_no=n.lineno,
182-
col_offset=n.col_offset,
183-
end_line_no=n.lineno,
184-
end_col_offset=n.end_col_offset,
188+
line_no=variable_token.lineno,
189+
col_offset=variable_token.col_offset,
190+
end_line_no=variable_token.lineno,
191+
end_col_offset=variable_token.end_col_offset,
185192
source=self.source,
186193
)
187194

@@ -212,13 +219,16 @@ async def visit_Arguments(self, node: ast.AST) -> None: # noqa: N802
212219
argument = self.get_variable_token(argument_token)
213220

214221
if argument is not None:
222+
if self.in_args and self.position is not None and self.position > range_from_token(argument).end:
223+
break
224+
215225
self._results[argument.value] = ArgumentDefinition(
216226
name=argument.value,
217227
name_token=strip_variable_token(argument),
218-
line_no=n.lineno,
219-
col_offset=n.col_offset,
220-
end_line_no=n.lineno,
221-
end_col_offset=n.end_col_offset,
228+
line_no=argument.lineno,
229+
col_offset=argument.col_offset,
230+
end_line_no=argument.lineno,
231+
end_col_offset=argument.end_col_offset,
222232
source=self.source,
223233
)
224234

@@ -241,10 +251,10 @@ async def visit_ExceptHeader(self, node: ast.AST) -> None: # noqa: N802
241251
self._results[variable.value] = LocalVariableDefinition(
242252
name=variable.value,
243253
name_token=strip_variable_token(variable),
244-
line_no=n.lineno,
245-
col_offset=n.col_offset,
246-
end_line_no=n.lineno,
247-
end_col_offset=n.end_col_offset,
254+
line_no=variable.lineno,
255+
col_offset=variable.col_offset,
256+
end_line_no=variable.lineno,
257+
end_col_offset=variable.end_col_offset,
248258
source=self.source,
249259
)
250260

@@ -276,10 +286,10 @@ async def visit_KeywordCall(self, node: ast.AST) -> None: # noqa: N802
276286
self._results[variable_token.value] = LocalVariableDefinition(
277287
name=variable_token.value,
278288
name_token=strip_variable_token(variable_token),
279-
line_no=n.lineno,
280-
col_offset=n.col_offset,
281-
end_line_no=n.lineno,
282-
end_col_offset=n.end_col_offset,
289+
line_no=variable_token.lineno,
290+
col_offset=variable_token.col_offset,
291+
end_line_no=variable_token.lineno,
292+
end_col_offset=variable_token.end_col_offset,
283293
source=self.source,
284294
)
285295

@@ -311,10 +321,10 @@ async def visit_InlineIfHeader(self, node: ast.AST) -> None: # noqa: N802
311321
self._results[variable_token.value] = LocalVariableDefinition(
312322
name=variable_token.value,
313323
name_token=strip_variable_token(variable_token),
314-
line_no=n.lineno,
315-
col_offset=n.col_offset,
316-
end_line_no=n.lineno,
317-
end_col_offset=n.end_col_offset,
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,
318328
source=self.source,
319329
)
320330

@@ -333,10 +343,10 @@ async def visit_ForHeader(self, node: ast.AST) -> None: # noqa: N802
333343
self._results[variable_token.value] = LocalVariableDefinition(
334344
name=variable_token.value,
335345
name_token=strip_variable_token(variable_token),
336-
line_no=n.lineno,
337-
col_offset=n.col_offset,
338-
end_line_no=n.lineno,
339-
end_col_offset=n.end_col_offset,
346+
line_no=variable_token.lineno,
347+
col_offset=variable_token.col_offset,
348+
end_line_no=variable_token.lineno,
349+
end_col_offset=variable_token.end_col_offset,
340350
source=self.source,
341351
)
342352

@@ -749,14 +759,17 @@ async def yield_variables(
749759
skip_commandline_variables: bool = False,
750760
) -> AsyncGenerator[Tuple[VariableMatcher, VariableDefinition], None]:
751761
from robot.parsing.model.blocks import Keyword, TestCase
762+
from robot.parsing.model.statements import Arguments
752763

753764
# await self.ensure_initialized()
754765

755766
yielded: Dict[VariableMatcher, VariableDefinition] = {}
756767

757768
async for var in async_chain(
758769
*[
759-
await BlockVariableVisitor().get(self.source, n, position)
770+
await BlockVariableVisitor(
771+
self.source, position, isinstance(nodes[-1], Arguments) if nodes else False
772+
).get(n)
760773
for n in nodes or []
761774
if isinstance(n, (Keyword, TestCase))
762775
],

robotcode/language_server/robotframework/parts/references.py

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import ast
44
import asyncio
5+
import itertools
56
from typing import (
67
TYPE_CHECKING,
78
Any,
@@ -47,8 +48,10 @@
4748
get_nodes_at_position,
4849
get_tokens_at_position,
4950
is_not_variable_token,
51+
iter_nodes_at_position,
5052
iter_over_keyword_names_and_owners,
5153
range_from_token,
54+
tokenize_variables,
5255
)
5356
from ..utils.async_ast import iter_nodes
5457

@@ -227,21 +230,46 @@ async def find_variable_references(self, document: TextDocument, variable: Varia
227230
else await self._find_references(document, self.find_variable_references_in_file, variable)
228231
)
229232

233+
async def yield_argument_name_and_rest(self, node: ast.AST, token: Token) -> AsyncGenerator[Token, None]:
234+
from robot.parsing.lexer.tokens import Token as RobotToken
235+
from robot.parsing.model.statements import Arguments
236+
237+
if isinstance(node, Arguments) and token.type == RobotToken.ARGUMENT:
238+
argument = next(
239+
(
240+
v
241+
for v in itertools.dropwhile(
242+
lambda t: t.type in RobotToken.NON_DATA_TOKENS,
243+
tokenize_variables(token, ignore_errors=True),
244+
)
245+
if v.type == RobotToken.VARIABLE
246+
),
247+
None,
248+
)
249+
if argument is None or argument.value == token.value:
250+
yield token
251+
else:
252+
yield argument
253+
i = len(argument.value)
254+
255+
async for t in self.yield_argument_name_and_rest(
256+
node, RobotToken(token.type, token.value[i:], token.lineno, token.col_offset + i, token.error)
257+
):
258+
yield t
259+
else:
260+
yield token
261+
230262
@_logger.call
231263
async def find_variable_references_in_file(
232264
self,
233265
doc: TextDocument,
234266
variable: VariableDefinition,
235267
) -> List[Location]:
236268
from robot.parsing.lexer.tokens import Token as RobotToken
237-
from robot.parsing.model.blocks import Block, Keyword, Section, TestCase
238269

239270
namespace = await self.parent.documents_cache.get_namespace(doc)
240271
model = await self.parent.documents_cache.get_model(doc)
241272

242-
result: List[Location] = []
243-
current_block: Optional[Block] = None
244-
245273
if (
246274
variable.source
247275
and variable.source != str(doc.uri.to_path())
@@ -259,24 +287,23 @@ async def find_variable_references_in_file(
259287

260288
expression_statements = self.get_expression_statement_types()
261289

290+
result: List[Location] = []
291+
262292
async for node in iter_nodes(model):
263-
if isinstance(node, Section):
264-
current_block = None
265-
elif isinstance(node, (TestCase, Keyword)):
266-
current_block = node
267293

268294
if isinstance(node, HasTokens):
269-
for token in node.tokens:
270-
async for token_and_var in self.iter_variables_from_token(
271-
token,
272-
namespace,
273-
[*([current_block] if current_block is not None else []), node],
274-
range_from_token(token).start,
275-
):
276-
sub_token, found_variable = token_and_var
277-
278-
if found_variable == variable:
279-
result.append(Location(str(doc.uri), range_from_token(sub_token)))
295+
for token1 in node.tokens:
296+
async for token in self.yield_argument_name_and_rest(node, token1):
297+
async for token_and_var in self.iter_variables_from_token(
298+
token,
299+
namespace,
300+
[n async for n in iter_nodes_at_position(model, range_from_token(token).start)],
301+
range_from_token(token).start,
302+
):
303+
sub_token, found_variable = token_and_var
304+
305+
if found_variable == variable:
306+
result.append(Location(str(doc.uri), range_from_token(sub_token)))
280307

281308
if (
282309
isinstance(node, Statement)
@@ -286,7 +313,7 @@ async def find_variable_references_in_file(
286313
async for token_and_var in self.iter_expression_variables_from_token(
287314
token,
288315
namespace,
289-
[*([current_block] if current_block is not None else []), node],
316+
[n async for n in iter_nodes_at_position(model, range_from_token(token).start)],
290317
range_from_token(token).start,
291318
):
292319
sub_token, found_variable = token_and_var

0 commit comments

Comments
 (0)