15
15
cast ,
16
16
)
17
17
18
- # from ....utils.async_itertools import async_next
18
+ from ....utils .async_itertools import async_next
19
19
from ....utils .async_tools import threaded
20
20
from ....utils .logging import LoggingDescriptor
21
-
22
- # from ....utils.uri import Uri
23
21
from ...common .decorators import language_id
24
22
from ...common .lsp_types import (
25
23
AnnotatedTextEdit ,
36
34
)
37
35
from ...common .parts .rename import CantRenameException
38
36
from ...common .text_document import TextDocument
39
-
40
- # from ..diagnostics.entities import VariableDefinition
37
+ from ..diagnostics .entities import VariableDefinition , VariableDefinitionType
41
38
from ..diagnostics .library_doc import KeywordDoc
42
- from ..utils .ast_utils import ( # HasTokens,; Statement,; get_tokens_at_position,
39
+ from ..utils .ast_utils import (
40
+ HasTokens ,
41
+ Statement ,
43
42
Token ,
44
43
get_nodes_at_position ,
44
+ get_tokens_at_position ,
45
45
range_from_token ,
46
46
)
47
47
@@ -148,67 +148,119 @@ async def collect_prepare(
148
148
async def _prepare_rename_default (
149
149
self , nodes : List [ast .AST ], document : TextDocument , position : Position
150
150
) -> Optional [PrepareRenameResult ]:
151
- pass
151
+ result = await self ._find_default (nodes , document , position )
152
+ if result is not None :
153
+ var , token = result
154
+
155
+ if var .type == VariableDefinitionType .BUILTIN_VARIABLE :
156
+ self .parent .window .show_message ("You cannot rename a builtin variable, only references are renamed." )
157
+
158
+ elif var .type == VariableDefinitionType .IMPORTED_VARIABLE :
159
+ self .parent .window .show_message (
160
+ "You are about to rename an imported variable. "
161
+ "Only references are renamed and you have to rename the variable definition yourself."
162
+ )
163
+ elif var .type == VariableDefinitionType .COMMAND_LINE_VARIABLE :
164
+ self .parent .window .show_message (
165
+ "You are about to rename a variable defined at commandline. "
166
+ "Only references are renamed and you have to rename the variable definition yourself."
167
+ )
168
+ elif var .type == VariableDefinitionType .ENVIRONMENT_VARIABLE :
169
+ self .parent .window .show_message (
170
+ "You are about to rename an environment variable. "
171
+ "Only references are renamed and you have to rename the variable definition yourself."
172
+ )
173
+
174
+ return PrepareRenameResultWithPlaceHolder (range_from_token (token ), token .value )
175
+
176
+ return None
152
177
153
178
async def _rename_default (
154
179
self , nodes : List [ast .AST ], document : TextDocument , position : Position , new_name : str
155
180
) -> Optional [WorkspaceEdit ]:
156
- # from robot.parsing.lexer.tokens import Token as RobotToken
157
-
158
- # namespace = await self.parent.documents_cache.get_namespace(document)
159
- # if namespace is None:
160
- # return None
161
-
162
- # if not nodes:
163
- # return None
164
-
165
- # node = nodes[-1]
166
-
167
- # if not isinstance(node, HasTokens):
168
- # return None
169
-
170
- # tokens = get_tokens_at_position(node, position)
171
-
172
- # token_and_var: Optional[Tuple[Token, VariableDefinition]] = None
173
-
174
- # for token in tokens:
175
- # token_and_var = await async_next(
176
- # (
177
- # (var_token, var)
178
- # async for var_token, var in self.iter_variables_from_token(token, namespace, nodes, position)
179
- # if position in range_from_token(var_token)
180
- # ),
181
- # None,
182
- # )
183
-
184
- # if (
185
- # token_and_var is None
186
- # and isinstance(node, Statement)
187
- # and isinstance(node, self.get_expression_statement_types())
188
- # and (token := node.get_token(RobotToken.ARGUMENT)) is not None
189
- # and position in range_from_token(token)
190
- # ):
191
- # token_and_var = await async_next(
192
- # (
193
- # (var_token, var)
194
- # async for var_token, var in self.iter_expression_variables_from_token(
195
- # token, namespace, nodes, position
196
- # )
197
- # if position in range_from_token(var_token)
198
- # ),
199
- # None,
200
- # )
201
-
202
- # if token_and_var is not None:
203
- # _, variable = token_and_var
204
-
205
- # return [
206
- # DocumentHighlight(e.range, DocumentHighlightKind.TEXT)
207
- # for e in await self.parent.robot_references.find_variable_references_in_file(document, variable)
208
- # ]
181
+ result = await self ._find_default (nodes , document , position )
182
+
183
+ if result is not None :
184
+ var , _ = result
185
+
186
+ references = await self .parent .robot_references .find_variable_references (
187
+ document ,
188
+ var ,
189
+ include_declaration = var .type
190
+ in [
191
+ VariableDefinitionType .VARIABLE ,
192
+ VariableDefinitionType .ARGUMENT ,
193
+ VariableDefinitionType .LOCAL_VARIABLE ,
194
+ ],
195
+ )
196
+ changes : List [Union [TextDocumentEdit , CreateFile , RenameFile , DeleteFile ]] = []
197
+
198
+ for reference in references :
199
+ changes .append (
200
+ TextDocumentEdit (
201
+ OptionalVersionedTextDocumentIdentifier (reference .uri , None ),
202
+ [AnnotatedTextEdit (reference .range , new_name , annotation_id = "rename_variable" )],
203
+ )
204
+ )
205
+
206
+ return WorkspaceEdit (
207
+ document_changes = changes ,
208
+ change_annotations = {"rename_variable" : ChangeAnnotation ("Rename Variable" , False )},
209
+ )
209
210
210
211
return None
211
212
213
+ async def _find_default (
214
+ self , nodes : List [ast .AST ], document : TextDocument , position : Position
215
+ ) -> Optional [Tuple [VariableDefinition , Token ]]:
216
+ from robot .parsing .lexer .tokens import Token as RobotToken
217
+
218
+ namespace = await self .parent .documents_cache .get_namespace (document )
219
+ if namespace is None :
220
+ return None
221
+
222
+ if not nodes :
223
+ return None
224
+
225
+ node = nodes [- 1 ]
226
+
227
+ if not isinstance (node , HasTokens ):
228
+ return None
229
+
230
+ tokens = get_tokens_at_position (node , position )
231
+
232
+ token_and_var : Optional [Tuple [VariableDefinition , Token ]] = None
233
+
234
+ for token in tokens :
235
+ token_and_var = await async_next (
236
+ (
237
+ (var , var_token )
238
+ async for var_token , var in self .iter_variables_from_token (token , namespace , nodes , position )
239
+ if position in range_from_token (var_token )
240
+ ),
241
+ None ,
242
+ )
243
+
244
+ if (
245
+ token_and_var is None
246
+ and isinstance (node , Statement )
247
+ and isinstance (node , self .get_expression_statement_types ())
248
+ and (token := node .get_token (RobotToken .ARGUMENT )) is not None
249
+ and position in range_from_token (token )
250
+ ):
251
+ token_and_var = await async_next (
252
+ (
253
+ (var , var_token )
254
+ async for var_token , var in self .iter_expression_variables_from_token (
255
+ token , namespace , nodes , position
256
+ )
257
+ if position in range_from_token (var_token )
258
+ ),
259
+ None ,
260
+ )
261
+
262
+ return token_and_var
263
+
212
264
def _prepare_rename_keyword (self , result : Optional [Tuple [KeywordDoc , Token ]]) -> Optional [PrepareRenameResult ]:
213
265
if result is not None :
214
266
kw_doc , token = result
@@ -230,7 +282,7 @@ async def _rename_keyword(
230
282
self , document : TextDocument , new_name : str , result : Optional [Tuple [KeywordDoc , Token ]]
231
283
) -> Optional [WorkspaceEdit ]:
232
284
if result is not None :
233
- kw_doc , token = result
285
+ kw_doc , _ = result
234
286
235
287
references = await self .parent .robot_references .find_keyword_references (
236
288
document , kw_doc , include_declaration = kw_doc .is_resource_keyword
@@ -241,12 +293,13 @@ async def _rename_keyword(
241
293
changes .append (
242
294
TextDocumentEdit (
243
295
OptionalVersionedTextDocumentIdentifier (reference .uri , None ),
244
- [AnnotatedTextEdit (reference .range , new_name , annotation_id = "a " )],
296
+ [AnnotatedTextEdit (reference .range , new_name , annotation_id = "rename_keyword " )],
245
297
)
246
298
)
247
299
248
300
return WorkspaceEdit (
249
- document_changes = changes , change_annotations = {"a" : ChangeAnnotation ("refactor" , False , "replace call" )}
301
+ document_changes = changes ,
302
+ change_annotations = {"rename_keyword" : ChangeAnnotation ("Rename Keyword" , False )},
250
303
)
251
304
252
305
return None
@@ -404,7 +457,7 @@ async def _find_Fixture( # noqa: N802
404
457
r .end .character = r .start .character + len (kw_namespace )
405
458
kw_range .start .character = r .end .character + 1
406
459
if position in r :
407
- # TODO highlight namespaces
460
+ # TODO namespaces
408
461
return None
409
462
410
463
if position in kw_range and keyword_doc is not None and not keyword_doc .is_error_handler :
@@ -456,7 +509,7 @@ async def _find_Template_or_TestTemplate( # noqa: N802
456
509
r .end .character = r .start .character + len (kw_namespace )
457
510
kw_range .start .character = r .end .character + 1
458
511
if position in r :
459
- # TODO highlight namespaces
512
+ # TODO namespaces
460
513
return None
461
514
462
515
if not keyword_doc .is_error_handler :
0 commit comments