11-- ----------------------------------------------------------------------------
22-- Language Server Protocol --
33-- --
4- -- Copyright (C) 2020-2023 , AdaCore --
4+ -- Copyright (C) 2020-2022 , AdaCore --
55-- --
66-- This is free software; you can redistribute it and/or modify it under --
77-- terms of the GNU General Public License as published by the Free Soft- --
1616-- ----------------------------------------------------------------------------
1717
1818with Ada.Strings.UTF_Encoding ;
19+ with Ada.Strings.Unbounded ;
1920with Ada.Strings.Wide_Wide_Unbounded ;
2021
2122with Langkit_Support.Text ;
2223
2324with Libadalang.Analysis ;
25+ with Libadalang.Common ;
26+
27+ with Laltools.Common ;
2428
25- with LSP.Commands ;
2629with LSP.Messages ;
2730
2831with VSS.Strings.Conversions ;
32+ with LSP.Commands ;
2933
30- package body LSP.Ada_Handlers.Refactor.Auto_Import is
34+ package body LSP.Ada_Handlers.Refactor.Imports_Commands is
3135
3236 -- --------------
3337 -- Initialize --
@@ -42,11 +46,8 @@ package body LSP.Ada_Handlers.Refactor.Auto_Import is
4246 begin
4347 Self.Context := Context.Id;
4448 Self.Where := Where;
45- Self.Suggestion :=
46- (Import =>
47- VSS.Strings.Conversions.To_Unbounded_Wide_Wide_String (With_Clause),
48- Qualifier =>
49- VSS.Strings.Conversions.To_Unbounded_Wide_Wide_String (Prefix));
49+ Self.With_Clause := With_Clause;
50+ Self.Prefix := Prefix;
5051 end Initialize ;
5152
5253 -- ----------
@@ -73,25 +74,10 @@ package body LSP.Ada_Handlers.Refactor.Auto_Import is
7374 LSP.Types.Read_String (JS, V.Context);
7475 elsif Key = " where" then
7576 LSP.Messages.TextDocumentPositionParams'Read (JS, V.Where);
76- elsif Key = " import" then
77- declare
78- Import : VSS.Strings.Virtual_String;
79- begin
80- LSP.Types.Read_String (JS, Import);
81- V.Suggestion.Import :=
82- VSS.Strings.Conversions.To_Unbounded_Wide_Wide_String
83- (Import);
84- end ;
85-
86- elsif Key = " qualifier" then
87- declare
88- Qualififer : VSS.Strings.Virtual_String;
89- begin
90- LSP.Types.Read_String (JS, Qualififer);
91- V.Suggestion.Qualifier :=
92- VSS.Strings.Conversions.To_Unbounded_Wide_Wide_String
93- (Qualififer);
94- end ;
77+ elsif Key = " with_clause" then
78+ LSP.Types.Read_String (JS, V.With_Clause);
79+ elsif Key = " prefix" then
80+ LSP.Types.Read_String (JS, V.Prefix);
9581 else
9682 JS.Skip_Value;
9783 end if ;
@@ -110,13 +96,13 @@ package body LSP.Ada_Handlers.Refactor.Auto_Import is
11096 Context : Context_Access;
11197 Where : LSP.Messages.Location;
11298 Commands_Vector : in out LSP.Messages.CodeAction_Vector;
113- Suggestion : LAL_Refactor.Auto_Import.Import_Type )
99+ Suggestion : LAL_Refactor.Refactor_Imports.Import_Suggestion )
114100 is
115101 Pointer : LSP.Commands.Command_Pointer;
116102 Item : LSP.Messages.CodeAction;
117103
118104 function Create_Suggestion_Title
119- (Suggestion : LAL_Refactor.Auto_Import.Import_Type )
105+ (Suggestion : LAL_Refactor.Refactor_Imports.Import_Suggestion )
120106 return VSS.Strings.Virtual_String;
121107 -- Creates the suggestion text that will be shown by the client to
122108 -- to the developer. The text is costumized based on the need of
@@ -126,17 +112,42 @@ package body LSP.Ada_Handlers.Refactor.Auto_Import is
126112 -- Create_Suggestions_Title --
127113 -- ----------------------------
128114 function Create_Suggestion_Title
129- (Suggestion : LAL_Refactor.Auto_Import.Import_Type )
115+ (Suggestion : LAL_Refactor.Refactor_Imports.Import_Suggestion )
130116 return VSS.Strings.Virtual_String
131117 is
132- use Ada.Strings.Wide_Wide_Unbounded;
118+ Title : Ada.Strings.Wide_Wide_Unbounded.
119+ Unbounded_Wide_Wide_String
120+ := Ada.Strings.Wide_Wide_Unbounded.
121+ Null_Unbounded_Wide_Wide_String;
122+ use type Ada.Strings.Wide_Wide_Unbounded.
123+ Unbounded_Wide_Wide_String;
133124
134- Title : constant Langkit_Support.Text.Unbounded_Text_Type :=
135- " Qualify with " & Suggestion.Qualifier;
136125 begin
137- return
138- VSS.Strings.To_Virtual_String
139- (Langkit_Support.Text.To_Text (Title));
126+ if Suggestion.With_Clause_Text /= " " then
127+ if Suggestion.Prefix_Text /= " " then
128+ -- Add with clause and prefix
129+ Title :=
130+ Title
131+ & " Add 'with' clause for "
132+ & Suggestion.With_Clause_Text
133+ & " and prefix the object with "
134+ & Suggestion.Prefix_Text;
135+
136+ else
137+ -- Add with clause and leave the prefix as it is
138+ Title :=
139+ Title
140+ & " Add 'with' clause for "
141+ & Suggestion.With_Clause_Text;
142+ end if ;
143+ else
144+ -- Only add prefix
145+
146+ Title := Title & " Prefix the object with "
147+ & Suggestion.Prefix_Text;
148+ end if ;
149+ return VSS.Strings.To_Virtual_String
150+ (Langkit_Support.Text.To_Text (Title));
140151 end Create_Suggestion_Title ;
141152
142153 begin
@@ -146,15 +157,15 @@ package body LSP.Ada_Handlers.Refactor.Auto_Import is
146157 Where.span.first),
147158 With_Clause =>
148159 VSS.Strings.Conversions.To_Virtual_String
149- (Suggestion.Import ),
160+ (Suggestion.With_Clause_Text ),
150161 Prefix =>
151162 VSS.Strings.Conversions.To_Virtual_String
152- (Suggestion.Qualifier ));
163+ (Suggestion.Prefix_Text ));
153164 Pointer.Set (Self);
154165 Item :=
155166 (title => Create_Suggestion_Title (Suggestion),
156167 kind => (Is_Set => True,
157- Value => LSP.Messages.QuickFix ),
168+ Value => LSP.Messages.RefactorRewrite ),
158169 diagnostics => (Is_Set => False),
159170 disabled => (Is_Set => False),
160171 edit => (Is_Set => False),
@@ -177,20 +188,119 @@ package body LSP.Ada_Handlers.Refactor.Auto_Import is
177188 Document : LSP.Ada_Documents.Document_Access)
178189 return LAL_Refactor.Refactoring_Edits
179190 is
191+ use Langkit_Support.Text;
180192 use Libadalang.Analysis;
181- use LAL_Refactor.Auto_Import;
193+ use Libadalang.Common;
194+ use Libadalang.Slocs;
195+ use LAL_Refactor;
196+ use VSS.Strings;
197+ use VSS.Strings.Conversions;
182198
183- Name : constant Libadalang.Analysis.Name :=
184- Document.Get_Node_At (Context, Self.Where.position).As_Name ;
199+ Node : Ada_Node :=
200+ Document.Get_Node_At (Context, Self.Where.position);
185201
186- function Units return Analysis_Unit_Array is ([]) ;
202+ Edits : LAL_Refactor.Refactoring_Edits ;
187203
188204 begin
189- return
190- Create_Auto_Importer
191- (Name,
192- Self.Suggestion)
193- .Refactor (Units'Access );
205+ -- Add prefix
206+
207+ if not Self.Prefix.Is_Empty
208+ and then Node.Kind in Ada_Identifier
209+ then
210+ -- If this is a DottedName them remove the current prefix and replace
211+ -- it by the suggested one. Otherwise, just add the prepend the
212+ -- prefix
213+
214+ while Node.Parent.Kind in Ada_Dotted_Name_Range loop
215+ Node := Node.Parent;
216+ end loop ;
217+
218+ if Node.Kind in Ada_Dotted_Name_Range then
219+ Node := Node.As_Dotted_Name.F_Suffix.As_Ada_Node;
220+ end if ;
221+
222+ if Node.Parent.Kind = Ada_Dotted_Name then
223+ -- Node.Parent is the full Dotted Name: this includes the
224+ -- current prefixes and the identifier. Using this SLOC instead
225+ -- of only the current prefixes SLOC is better since this covers
226+ -- cases when the Dotted Name is splitted in multiple lines.
227+
228+ Safe_Insert
229+ (Edits => Edits.Text_Edits,
230+ File_Name => Node.Unit.Get_Filename,
231+ Edit =>
232+ Text_Edit'
233+ (Location =>
234+ Make_Range
235+ (Start_Sloc
236+ (Node.Parent.As_Dotted_Name.F_Prefix.Sloc_Range),
237+ Start_Sloc (Node.Sloc_Range)),
238+ Text =>
239+ Ada.Strings.Unbounded.To_Unbounded_String
240+ (To_UTF8 (To_Wide_Wide_String (Self.Prefix)))));
241+
242+ else
243+ Safe_Insert
244+ (Edits => Edits.Text_Edits,
245+ File_Name => Node.Unit.Get_Filename,
246+ Edit =>
247+ Text_Edit'
248+ (Location =>
249+ Make_Range
250+ (Start_Sloc (Node.Sloc_Range),
251+ Start_Sloc (Node.Sloc_Range)),
252+ Text =>
253+ Ada.Strings.Unbounded.To_Unbounded_String
254+ (To_UTF8 (To_Wide_Wide_String (Self.Prefix)))));
255+ end if ;
256+ end if ;
257+
258+ -- Add with clause
259+
260+ if not Self.With_Clause.Is_Empty then
261+ declare
262+ Last : Boolean;
263+ S : constant Libadalang.Slocs.Source_Location :=
264+ Laltools.Common.Get_Insert_With_Location
265+ (Node => Laltools.Common.Get_Compilation_Unit (Node),
266+ Pack_Name =>
267+ VSS.Strings.Conversions.To_Wide_Wide_String
268+ (Self.With_Clause),
269+ Last => Last);
270+ begin
271+ if S /= Libadalang.Slocs.No_Source_Location then
272+ if Last then
273+ Safe_Insert
274+ (Edits => Edits.Text_Edits,
275+ File_Name => Node.Unit.Get_Filename,
276+ Edit =>
277+ Text_Edit'
278+ (Location => Make_Range (S, S),
279+ Text =>
280+ Ada.Strings.Unbounded.To_Unbounded_String
281+ (To_UTF8 (To_Wide_Wide_String
282+ (Document.Line_Terminator
283+ & " with " & Self.With_Clause & " ;" )))));
284+
285+ else
286+ Safe_Insert
287+ (Edits => Edits.Text_Edits,
288+ File_Name => Node.Unit.Get_Filename,
289+ Edit =>
290+ Text_Edit'
291+ (Location => Make_Range (S, S),
292+ Text =>
293+ Ada.Strings.Unbounded.To_Unbounded_String
294+ (To_UTF8 (To_Wide_Wide_String
295+ (" with " & Self.With_Clause & " ;"
296+ & Document.Line_Terminator)))));
297+ end if ;
298+
299+ end if ;
300+ end ;
301+ end if ;
302+
303+ return Edits;
194304 end Command_To_Refactoring_Edits ;
195305
196306 -- ------------
@@ -235,15 +345,11 @@ package body LSP.Ada_Handlers.Refactor.Auto_Import is
235345 LSP.Types.Write_String (S, V.Context);
236346 JS.Key (" where" );
237347 LSP.Messages.TextDocumentPositionParams'Write (S, V.Where);
238- JS.Key (" import" );
239- LSP.Types.Write_String
240- (S,
241- VSS.Strings.Conversions.To_Virtual_String (V.Suggestion.Import));
242- JS.Key (" qualifier" );
243- LSP.Types.Write_String
244- (S,
245- VSS.Strings.Conversions.To_Virtual_String (V.Suggestion.Qualifier));
348+ JS.Key (" with_clause" );
349+ LSP.Types.Write_String (S, V.With_Clause);
350+ JS.Key (" prefix" );
351+ LSP.Types.Write_String (S, V.Prefix);
246352 JS.End_Object;
247353 end Write_Command ;
248354
249- end LSP.Ada_Handlers.Refactor.Auto_Import ;
355+ end LSP.Ada_Handlers.Refactor.Imports_Commands ;
0 commit comments