Skip to content

Commit 0b37a57

Browse files
committed
Merge branch 'lal_refactor_17' into 'master'
Extract variable implementation See merge request eng/ide/ada_language_server!2030
2 parents c609f3b + 9557a01 commit 0b37a57

File tree

11 files changed

+646
-0
lines changed

11 files changed

+646
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
section below it for the last release. -->
55
## \<next>
66

7+
* New refactoring: [Extract Variable](https://github.com/AdaCore/ada_language_server/blob/master/doc/refactoring_tools.md#extract-variable)
78
* Added a `Ada: Report Issue` command that opens the [VS Code Issue Reporter](https://code.visualstudio.com/docs/supporting/FAQ#_report-an-issue-with-a-vs-code-extension) with an extension-specific template
89
* Add `begin` and `private` destinations to `texDocument/definition` response triggered
910
respectively on subprograms and packages (e.g: ctrl-click on a subprogram name will

doc/refactoring_tools.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
* [Change Parameter Type](#change-parameter-type)
1313
* [Change Parameter Default Value](#change-parameter-default-value)
1414
* [Extract Subprogram](#extract-subprogram)
15+
* [Extract Variable](#extract-variable)
1516
* [Pull Up Declaration](#pull-up-declaration)
1617
* [Suppress Separate](#suppress-separate)
1718
* [Introduce Parameter](#introduce-parameter)
@@ -132,6 +133,16 @@ Demo source is `extract_subprogram/` in [Code Samples](https://github.com/AdaCor
132133

133134
![extract_subprogram](media/extract_subprogram.gif)
134135

136+
## Extract Variable
137+
138+
**Command name:** `als-refactor-extract-variable`
139+
140+
* Extract an expression to the new variable.
141+
* The new variable is created in the nearest declarative part.
142+
* The assignment is done as close to the original location as possible.
143+
144+
See `src/lal_refactor-extract_variable.ads` in [LAL Refactor repository](https://github.com/AdaCore/lal-refactor).
145+
135146
## Pull Up Declaration
136147

137148
**Command name:** `als-refactor-pull_up_declaration`

source/ada/lsp-ada_driver.adb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ with LSP.Ada_Handlers.Refactor.Change_Parameter_Mode;
6868
with LSP.Ada_Handlers.Refactor.Change_Parameters_Default_Value;
6969
with LSP.Ada_Handlers.Refactor.Change_Parameters_Type;
7070
with LSP.Ada_Handlers.Refactor.Extract_Subprogram;
71+
with LSP.Ada_Handlers.Refactor.Extract_Variable;
7172
with LSP.Ada_Handlers.Refactor.Auto_Import;
7273
with LSP.Ada_Handlers.Refactor.Introduce_Parameter;
7374
with LSP.Ada_Handlers.Refactor.Move_Parameter;
@@ -218,6 +219,8 @@ procedure LSP.Ada_Driver is
218219
(LSP.Ada_Handlers.Refactor.Suppress_Seperate.Command'Tag);
219220
LSP.Ada_Commands.Register
220221
(LSP.Ada_Handlers.Refactor.Extract_Subprogram.Command'Tag);
222+
LSP.Ada_Commands.Register
223+
(LSP.Ada_Handlers.Refactor.Extract_Variable.Command'Tag);
221224
LSP.Ada_Commands.Register
222225
(LSP.Ada_Handlers.Refactor.Introduce_Parameter.Command'Tag);
223226
LSP.Ada_Commands.Register
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
------------------------------------------------------------------------------
2+
-- Language Server Protocol --
3+
-- --
4+
-- Copyright (C) 2022-2023, AdaCore --
5+
-- --
6+
-- This is free software; you can redistribute it and/or modify it under --
7+
-- terms of the GNU General Public License as published by the Free Soft- --
8+
-- ware Foundation; either version 3, or (at your option) any later ver- --
9+
-- sion. This software is distributed in the hope that it will be useful, --
10+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
11+
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
12+
-- License for more details. You should have received a copy of the GNU --
13+
-- General Public License distributed with this software; see file --
14+
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
15+
-- of the license. --
16+
------------------------------------------------------------------------------
17+
18+
with Langkit_Support.Slocs; use Langkit_Support.Slocs;
19+
20+
with Libadalang.Analysis; use Libadalang.Analysis;
21+
22+
with LAL_Refactor; use LAL_Refactor;
23+
with LAL_Refactor.Extract_Variable;
24+
use LAL_Refactor.Extract_Variable;
25+
26+
with VSS.JSON.Streams;
27+
28+
with LSP.Enumerations;
29+
with LSP.Structures.LSPAny_Vectors; use LSP.Structures.LSPAny_Vectors;
30+
31+
package body LSP.Ada_Handlers.Refactor.Extract_Variable is
32+
33+
pragma Warnings (Off);
34+
35+
----------------
36+
-- Initialize --
37+
----------------
38+
39+
procedure Initialize
40+
(Self : in out Command'Class;
41+
Context : LSP.Ada_Contexts.Context;
42+
Where : LSP.Structures.Location) is
43+
begin
44+
Self.Context_Id := Context.Id;
45+
Self.Section_To_Extract_SLOC := Where;
46+
end Initialize;
47+
48+
------------------------
49+
-- Append_Code_Action --
50+
------------------------
51+
52+
procedure Append_Code_Action
53+
(Self : in out Command;
54+
Context : LSP.Ada_Context_Sets.Context_Access;
55+
Commands_Vector : in out LSP.Structures.Command_Or_CodeAction_Vector;
56+
Where : LSP.Structures.Location)
57+
is
58+
Code_Action : LSP.Structures.CodeAction;
59+
60+
begin
61+
Self.Initialize
62+
(Context => Context.all,
63+
Where => Where);
64+
65+
Code_Action :=
66+
(title => "Extract Variable",
67+
kind =>
68+
(Is_Set => True,
69+
Value => LSP.Enumerations.RefactorExtract),
70+
diagnostics => <>,
71+
edit => (Is_Set => False),
72+
isPreferred => (Is_Set => False),
73+
disabled => (Is_Set => False),
74+
command =>
75+
(Is_Set => True,
76+
Value =>
77+
(title => "",
78+
command => VSS.Strings.Conversions.To_Virtual_String
79+
(Command'External_Tag),
80+
arguments => Self.Write_Command)),
81+
data => <>);
82+
83+
Commands_Vector.Append
84+
(LSP.Structures.Command_Or_CodeAction'
85+
(Is_Command => False, CodeAction => Code_Action));
86+
end Append_Code_Action;
87+
88+
------------
89+
-- Create --
90+
------------
91+
92+
overriding function Create
93+
(Any : not null access LSP.Structures.LSPAny_Vector)
94+
return Command
95+
is
96+
use VSS.JSON.Streams;
97+
use VSS.Strings;
98+
use LSP.Structures.JSON_Event_Vectors;
99+
100+
C : Cursor := Any.First;
101+
begin
102+
return Self : Command do
103+
pragma Assert (Element (C).Kind = Start_Array);
104+
Next (C);
105+
pragma Assert (Element (C).Kind = Start_Object);
106+
Next (C);
107+
108+
while Has_Element (C)
109+
and then Element (C).Kind /= End_Object
110+
loop
111+
pragma Assert (Element (C).Kind = Key_Name);
112+
declare
113+
Key : constant Virtual_String := Element (C).Key_Name;
114+
begin
115+
Next (C);
116+
117+
if Key = "context_id" then
118+
Self.Context_Id := Element (C).String_Value;
119+
120+
elsif Key = "section_to_extract_sloc" then
121+
Self.Section_To_Extract_SLOC := From_Any (C);
122+
123+
else
124+
Skip_Value (C);
125+
end if;
126+
end;
127+
128+
Next (C);
129+
end loop;
130+
end return;
131+
end Create;
132+
133+
--------------
134+
-- Refactor --
135+
--------------
136+
137+
overriding procedure Refactor
138+
(Self : Command;
139+
Handler : not null access LSP.Ada_Handlers.Message_Handler'Class;
140+
Edits : out LAL_Refactor.Refactoring_Edits)
141+
is
142+
Message_Handler : LSP.Ada_Handlers.Message_Handler renames
143+
LSP.Ada_Handlers.Message_Handler (Handler.all);
144+
Context : LSP.Ada_Contexts.Context renames
145+
Message_Handler.Contexts.Get (Self.Context_Id).all;
146+
147+
function Analysis_Units return Analysis_Unit_Array is
148+
(Context.Analysis_Units);
149+
-- Provides the Context Analysis_Unit_Array to the Mode_Changer
150+
151+
File : constant GNATCOLL.VFS.Virtual_File :=
152+
Message_Handler.To_File (Self.Section_To_Extract_SLOC.uri);
153+
154+
Unit : constant Analysis_Unit := Context.Get_AU (File);
155+
Section_To_Extract : constant Source_Location_Range :=
156+
(Langkit_Support.Slocs.Line_Number
157+
(Self.Section_To_Extract_SLOC.a_range.start.line) + 1,
158+
Langkit_Support.Slocs.Line_Number
159+
(Self.Section_To_Extract_SLOC.a_range.an_end.line) + 1,
160+
Column_Number
161+
(Self.Section_To_Extract_SLOC.a_range.start.character) + 1,
162+
Column_Number
163+
(Self.Section_To_Extract_SLOC.a_range.an_end.character) + 1);
164+
165+
Extractor : constant Variable_Extractor :=
166+
Create_Variable_Extractor
167+
(Unit => Unit,
168+
Section_To_Extract => Section_To_Extract,
169+
Variable_Name =>
170+
Default_Extracted_Variable_Name
171+
(Unit => Unit,
172+
Location =>
173+
(Section_To_Extract.Start_Line,
174+
Section_To_Extract.Start_Column)));
175+
begin
176+
Edits := Extractor.Refactor (Analysis_Units'Access);
177+
end Refactor;
178+
179+
-------------------
180+
-- Write_Command --
181+
-------------------
182+
183+
function Write_Command
184+
(Self : Command) return LSP.Structures.LSPAny_Vector
185+
is
186+
use VSS.JSON.Streams;
187+
188+
Result : LSP.Structures.LSPAny_Vector;
189+
begin
190+
Result.Append (JSON_Stream_Element'(Kind => Start_Array));
191+
Result.Append (JSON_Stream_Element'(Kind => Start_Object));
192+
193+
-- "context_id"
194+
Add_Key ("context_id", Result);
195+
To_Any (Self.Context_Id, Result);
196+
197+
-- "section_to_extract_sloc"
198+
Add_Key ("section_to_extract_sloc", Result);
199+
To_Any (Self.Section_To_Extract_SLOC, Result);
200+
201+
Result.Append (JSON_Stream_Element'(Kind => End_Object));
202+
Result.Append (JSON_Stream_Element'(Kind => End_Array));
203+
204+
return Result;
205+
end Write_Command;
206+
207+
end LSP.Ada_Handlers.Refactor.Extract_Variable;
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
------------------------------------------------------------------------------
2+
-- Language Server Protocol --
3+
-- --
4+
-- Copyright (C) 2025, AdaCore --
5+
-- --
6+
-- This is free software; you can redistribute it and/or modify it under --
7+
-- terms of the GNU General Public License as published by the Free Soft- --
8+
-- ware Foundation; either version 3, or (at your option) any later ver- --
9+
-- sion. This software is distributed in the hope that it will be useful, --
10+
-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- --
11+
-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
12+
-- License for more details. You should have received a copy of the GNU --
13+
-- General Public License distributed with this software; see file --
14+
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy --
15+
-- of the license. --
16+
------------------------------------------------------------------------------
17+
--
18+
-- Implementation of the refactoring command to extract variable
19+
20+
with VSS.Strings;
21+
22+
with LSP.Ada_Contexts;
23+
with LSP.Server_Jobs;
24+
25+
package LSP.Ada_Handlers.Refactor.Extract_Variable is
26+
27+
type Command is new LSP.Ada_Handlers.Refactor.Command with private;
28+
29+
overriding function Name (Self : Command) return String
30+
is ("Extract Variable");
31+
32+
procedure Append_Code_Action
33+
(Self : in out Command;
34+
Context : LSP.Ada_Context_Sets.Context_Access;
35+
Commands_Vector : in out LSP.Structures.Command_Or_CodeAction_Vector;
36+
Where : LSP.Structures.Location);
37+
-- Initializes Self and appends it to Commands_Vector
38+
39+
private
40+
41+
type Command is new LSP.Ada_Handlers.Refactor.Command with record
42+
Context_Id : VSS.Strings.Virtual_String;
43+
Section_To_Extract_SLOC : LSP.Structures.Location;
44+
end record;
45+
46+
overriding
47+
function Create
48+
(Any : not null access LSP.Structures.LSPAny_Vector)
49+
return Command;
50+
-- Reads Any and creates a new Command
51+
52+
overriding
53+
procedure Refactor
54+
(Self : Command;
55+
Handler : not null access LSP.Ada_Handlers.Message_Handler'Class;
56+
Edits : out LAL_Refactor.Refactoring_Edits);
57+
-- Executes Self by computing the necessary refactorings
58+
59+
overriding function Priority (Self : Command)
60+
return LSP.Server_Jobs.Job_Priority
61+
is (LSP.Server_Jobs.Low);
62+
63+
procedure Initialize
64+
(Self : in out Command'Class;
65+
Context : LSP.Ada_Contexts.Context;
66+
Where : LSP.Structures.Location);
67+
-- Initializes Self
68+
69+
function Write_Command
70+
(Self : Command) return LSP.Structures.LSPAny_Vector;
71+
72+
for Command'External_Tag use "als-refactor-extract-variable";
73+
74+
end LSP.Ada_Handlers.Refactor.Extract_Variable;

0 commit comments

Comments
 (0)