1616-- ----------------------------------------------------------------------------
1717
1818with Ada.Strings.UTF_Encoding ;
19+ with Ada.Strings.Unbounded ;
1920with Ada.Strings.Wide_Wide_Unbounded ;
2021
2122with Langkit_Support.Text ;
@@ -122,13 +123,25 @@ package body LSP.Ada_Handlers.Refactor_Imports_Commands is
122123 Null_Unbounded_Wide_Wide_String;
123124 use type Ada.Strings.Wide_Wide_Unbounded.
124125 Unbounded_Wide_Wide_String;
126+
125127 begin
126128 if Suggestion.With_Clause_Text /= " " then
127- -- Add with clause and prefix
129+ if Suggestion.Prefix_Text /= " " then
130+ -- Add with clause and prefix
131+ Title :=
132+ Title
133+ & " Add 'with' clause for "
134+ & Suggestion.With_Clause_Text
135+ & " and prefix the object with "
136+ & Suggestion.Prefix_Text;
128137
129- Title := Title & " Add 'with' clause for "
130- & Suggestion.With_Clause_Text & " and prefix the object with "
131- & Suggestion.Prefix_Text;
138+ else
139+ -- Add with clause and leave the prefix as it is
140+ Title :=
141+ Title
142+ & " Add 'with' clause for "
143+ & Suggestion.With_Clause_Text;
144+ end if ;
132145 else
133146 -- Only add prefix
134147
@@ -167,96 +180,84 @@ package body LSP.Ada_Handlers.Refactor_Imports_Commands is
167180 Commands_Vector.Append (Item);
168181 end Append_Suggestion ;
169182
170- -- -----------
171- -- Execute --
172- -- -----------
183+ -- --------------------------------
184+ -- Command_To_Refactoring_Edits --
185+ -- --------------------------------
173186
174- overriding procedure Execute
175- (Self : Command;
176- Handler : not null access LSP.Server_Notification_Receivers.
177- Server_Notification_Receiver'Class;
178- Client : not null access LSP.Client_Message_Receivers.
179- Client_Message_Receiver'Class;
180- Error : in out LSP.Errors.Optional_ResponseError)
187+ function Command_To_Refactoring_Edits
188+ (Self : Command;
189+ Context : LSP.Ada_Contexts.Context;
190+ Document : LSP.Ada_Documents.Document_Access)
191+ return Laltools.Refactor.Refactoring_Edits
181192 is
182- use type Libadalang.Common.Ada_Node_Kind_Type;
183- use type Libadalang.Slocs.Source_Location;
184- use type VSS.Strings.Virtual_String;
185-
186- Message_Handler : LSP.Ada_Handlers.Message_Handler renames
187- LSP.Ada_Handlers.Message_Handler (Handler.all );
188- Context : LSP.Ada_Contexts.Context renames
189- Message_Handler.Contexts.Get (Self.Context).all ;
190-
191- Document : constant LSP.Ada_Documents.Document_Access :=
192- Message_Handler.Get_Open_Document (Self.Where.textDocument.uri);
193- Apply : LSP.Messages.Client_Requests.Workspace_Apply_Edit_Request;
194- Node : constant Libadalang.Analysis.Ada_Node :=
193+ use Langkit_Support.Text;
194+ use Libadalang.Analysis;
195+ use Libadalang.Common;
196+ use Libadalang.Slocs;
197+ use Laltools.Refactor;
198+ use VSS.Strings;
199+ use VSS.Strings.Conversions;
200+
201+ Node : Ada_Node :=
195202 Document.Get_Node_At (Context, Self.Where.position);
196- Loc : LSP.Messages.Location;
197- Edit : LSP.Messages.AnnotatedTextEdit;
198203
199- Edits : LSP.Messages.WorkspaceEdit renames Apply.params.edit;
200- Version : constant LSP.Messages.VersionedTextDocumentIdentifier :=
201- Document.Versioned_Identifier;
202- begin
203- Apply.params.label :=
204- (Is_Set => True,
205- Value =>
206- VSS.Strings.Conversions.To_Virtual_String (Command'External_Tag));
207- if Message_Handler.Versioned_Documents then
208- Edits.documentChanges.Append
209- (LSP.Messages.Document_Change'
210- (Kind => LSP.Messages.Text_Document_Edit,
211- Text_Document_Edit =>
212- (textDocument => (Version.uri, (True, Version.version)),
213- edits => <>)));
214- end if ;
204+ Edits : Laltools.Refactor.Refactoring_Edits;
215205
216- -- Add prefix.
206+ begin
207+ -- Add prefix
217208
218209 if not Self.Prefix.Is_Empty
219- and then Node.Kind = Libadalang.Common. Ada_Identifier
210+ and then Node.Kind in Ada_Identifier
220211 then
221212 -- If this is a DottedName them remove the current prefix and replace
222213 -- it by the suggested one. Otherwise, just add the prepend the
223214 -- prefix
224215
225- if Node.Parent.Kind = Libadalang.Common.Ada_Dotted_Name then
216+ while Node.Parent.Kind in Ada_Dotted_Name_Range loop
217+ Node := Node.Parent;
218+ end loop ;
219+
220+ if Node.Kind in Ada_Dotted_Name_Range then
221+ Node := Node.As_Dotted_Name.F_Suffix.As_Ada_Node;
222+ end if ;
223+
224+ if Node.Parent.Kind = Ada_Dotted_Name then
226225 -- Node.Parent is the full Dotted Name: this includes the
227226 -- current prefixes and the identifier. Using this SLOC instead
228227 -- of only the current prefixes SLOC is better since this covers
229228 -- cases when the Dotted Name is splitted in multiple lines.
230229
231- Loc := LSP.Lal_Utils.Get_Node_Location (Node.Parent);
232- Edit.span := (Loc.span.first, Loc.span.last);
233- Edit.newText :=
234- Self.Prefix & VSS.Strings.To_Virtual_String (Node.Text);
235- else
236- Loc := LSP.Lal_Utils.Get_Node_Location (Node);
237- Edit.span := (Loc.span.first, Loc.span.first);
238- Edit.newText := Self.Prefix;
239- end if ;
230+ Safe_Insert
231+ (Edits => Edits.Text_Edits,
232+ File_Name => Node.Unit.Get_Filename,
233+ Edit =>
234+ Text_Edit'
235+ (Location =>
236+ Make_Range
237+ (Start_Sloc
238+ (Node.Parent.As_Dotted_Name.F_Prefix.Sloc_Range),
239+ Start_Sloc (Node.Sloc_Range)),
240+ Text =>
241+ Ada.Strings.Unbounded.To_Unbounded_String
242+ (To_UTF8 (To_Wide_Wide_String (Self.Prefix)))));
240243
241- if Message_Handler.Versioned_Documents then
242- Edits.documentChanges (1 ).Text_Document_Edit.edits.Append (Edit);
243244 else
244- if Edits.changes.Contains (Self.Where.textDocument.uri) then
245- Edits.changes (Self.Where.textDocument.uri).Append
246- (LSP.Messages.TextEdit (Edit));
247- else
248- declare
249- Text_Edits : LSP.Messages.TextEdit_Vector;
250- begin
251- Text_Edits.Append (LSP.Messages.TextEdit (Edit));
252- Edits.changes.Include
253- (Self.Where.textDocument.uri, Text_Edits);
254- end ;
255- end if ;
245+ Safe_Insert
246+ (Edits => Edits.Text_Edits,
247+ File_Name => Node.Unit.Get_Filename,
248+ Edit =>
249+ Text_Edit'
250+ (Location =>
251+ Make_Range
252+ (Start_Sloc (Node.Sloc_Range),
253+ Start_Sloc (Node.Sloc_Range)),
254+ Text =>
255+ Ada.Strings.Unbounded.To_Unbounded_String
256+ (To_UTF8 (To_Wide_Wide_String (Self.Prefix))))) ;
256257 end if ;
257258 end if ;
258259
259- -- Add with clause.
260+ -- Add with clause
260261
261262 if not Self.With_Clause.Is_Empty then
262263 declare
@@ -270,39 +271,84 @@ package body LSP.Ada_Handlers.Refactor_Imports_Commands is
270271 Last => Last);
271272 begin
272273 if S /= Libadalang.Slocs.No_Source_Location then
273- Edit.span := LSP.Lal_Utils.To_Span (S);
274274 if Last then
275- Edit.newText :=
276- Document.Line_Terminator
277- & " with " & Self.With_Clause & " ;" ;
275+ Safe_Insert
276+ (Edits => Edits.Text_Edits,
277+ File_Name => Node.Unit.Get_Filename,
278+ Edit =>
279+ Text_Edit'
280+ (Location => Make_Range (S, S),
281+ Text =>
282+ Ada.Strings.Unbounded.To_Unbounded_String
283+ (To_UTF8 (To_Wide_Wide_String
284+ (Document.Line_Terminator
285+ & " with " & Self.With_Clause & " ;" )))));
278286
279287 else
280- Edit.newText :=
281- " with " & Self.With_Clause & " ;"
282- & Document.Line_Terminator;
288+ Safe_Insert
289+ (Edits => Edits.Text_Edits,
290+ File_Name => Node.Unit.Get_Filename,
291+ Edit =>
292+ Text_Edit'
293+ (Location => Make_Range (S, S),
294+ Text =>
295+ Ada.Strings.Unbounded.To_Unbounded_String
296+ (To_UTF8 (To_Wide_Wide_String
297+ (" with " & Self.With_Clause & " ;"
298+ & Document.Line_Terminator)))));
283299 end if ;
284300
285- if Message_Handler.Versioned_Documents then
286- Edits.documentChanges (1 ).Text_Document_Edit.edits.Append
287- (Edit);
288- else
289- if Edits.changes.Contains (Self.Where.textDocument.uri) then
290- Edits.changes (Self.Where.textDocument.uri).Append
291- (LSP.Messages.TextEdit (Edit));
292- else
293- declare
294- Text_Edits : LSP.Messages.TextEdit_Vector;
295- begin
296- Text_Edits.Append (LSP.Messages.TextEdit (Edit));
297- Edits.changes.Include
298- (Self.Where.textDocument.uri, Text_Edits);
299- end ;
300- end if ;
301- end if ;
302301 end if ;
303302 end ;
304303 end if ;
305304
305+ return Edits;
306+ end Command_To_Refactoring_Edits ;
307+
308+ -- -----------
309+ -- Execute --
310+ -- -----------
311+
312+ overriding procedure Execute
313+ (Self : Command;
314+ Handler : not null access LSP.Server_Notification_Receivers.
315+ Server_Notification_Receiver'Class;
316+ Client : not null access LSP.Client_Message_Receivers.
317+ Client_Message_Receiver'Class;
318+ Error : in out LSP.Errors.Optional_ResponseError)
319+ is
320+ use Laltools.Refactor;
321+ use LSP.Messages;
322+ use LSP.Types;
323+ use VSS.Strings;
324+ use VSS.Strings.Conversions;
325+
326+ Message_Handler : LSP.Ada_Handlers.Message_Handler renames
327+ LSP.Ada_Handlers.Message_Handler (Handler.all );
328+ Context : LSP.Ada_Contexts.Context renames
329+ Message_Handler.Contexts.Get (Self.Context).all ;
330+
331+ Document : constant LSP.Ada_Documents.Document_Access :=
332+ Message_Handler.Get_Open_Document (Self.Where.textDocument.uri);
333+
334+ Apply : Client_Requests.Workspace_Apply_Edit_Request;
335+ Workspace_Edits : WorkspaceEdit renames Apply.params.edit;
336+ Label : Optional_Virtual_String renames Apply.params.label;
337+
338+ Edits : constant Refactoring_Edits :=
339+ Self.Command_To_Refactoring_Edits (Context, Document);
340+
341+ begin
342+ Workspace_Edits :=
343+ LSP.Lal_Utils.To_Workspace_Edit
344+ (Edits => Edits,
345+ Resource_Operations => Message_Handler.Resource_Operations,
346+ Versioned_Documents => Message_Handler.Versioned_Documents,
347+ Document_Provider => Message_Handler'Access );
348+ Label :=
349+ (Is_Set => True,
350+ Value => To_Virtual_String (Command'External_Tag));
351+
306352 Client.On_Workspace_Apply_Edit_Request (Apply);
307353
308354 exception
0 commit comments