liblal_refactor_25.0.0_15241508/src/lal_refactor-extract_subprogram.ads

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
--
--  Copyright (C) 2022-2023, AdaCore
--
--  SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
--

--  This package contains refactoring tools that allow extracting statements
--  and expressions into new subprograms

with Libadalang.Common; use Libadalang.Common;

private with Ada.Containers;
private with Ada.Containers.Indefinite_Hashed_Maps;
private with Ada.Containers.Indefinite_Ordered_Sets;

package LAL_Refactor.Extract_Subprogram is

   type Available_Subprogram_Kinds_Type is array (Ada_Subp_Kind) of Boolean;

   function Is_Extract_Subprogram_Available
     (Unit                       : Analysis_Unit;
      Section_To_Extract         : Source_Location_Range;
      Available_Subprogram_Kinds : out Available_Subprogram_Kinds_Type)
      return Boolean;
   --  Checks if Section_To_Extract is a set of statements that can be
   --  extracted into a subprogram.

   function Default_Extracted_Subprogram_Name
     (Unit            : Analysis_Unit;
      Location        : Source_Location)
      return Unbounded_String;
   --  Assuming the Location is within a set of statements that can be
   --  extracted, returns a name for the extracted subprogram.
   --  The name will be "Extracted_<_N>" where N is a suffix to avoid
   --  collisions in the declarative part where the statements will be
   --  extracted.

   type Subprogram_Extractor is new Refactoring_Tool with private;

   function Create_Subprogram_Extractor
     (Unit               : Analysis_Unit;
      Section_To_Extract : Source_Location_Range;
      Subprogram_Kind    : Ada_Subp_Kind;
      Subprogram_Name    : Unbounded_String)
      return Subprogram_Extractor;
   --  Subprogram_Extractor constructor.
   --  The section to extract needs to be validated by
   --  Is_Extract_Subprogram_Available.
   --  Subprogram_Kind must be one of the available kinds in the
   --  Available_Subprogram_Kinds parameter of Is_Extract_Subprogram_Available.
   --  Is the inputs are not valid, the Refactor might succeed but generate
   --  invalid code, or a Constrained_Error might be raised to to invalid
   --  node conversions.

   overriding
   function Refactor
     (Self           : Subprogram_Extractor;
      Analysis_Units : access function return Analysis_Unit_Array)
      return Refactoring_Edits;

private

   function "<" (L, R : Defining_Name) return Boolean is
     (L.Sloc_Range < R.Sloc_Range);
   --  < operator used for ordered sets, ordering the Defining_Names by
   --  SLOC

   package Defining_Name_Ordered_Sets is new
     Ada.Containers.Indefinite_Ordered_Sets
       (Element_Type        => Defining_Name,
        "<"                 => LAL_Refactor.Extract_Subprogram."<",
        "="                 => "=");

   subtype Defining_Name_Ordered_Set is Defining_Name_Ordered_Sets.Set;

   function Defining_Name_Hash
     (Node : Defining_Name'Class)
      return Ada.Containers.Hash_Type
   is (Hash (Node.As_Ada_Node));
   --  Casts Node to an Ada_Node and calls Libadalang.Analysis.Hash on it

   package Defining_Name_To_Ada_Mode_Maps is new
     Ada.Containers.Indefinite_Hashed_Maps
       (Key_Type        => Defining_Name'Class,
        Element_Type    => Ada_Mode,
        Hash            => Defining_Name_Hash,
        Equivalent_Keys => "=",
        "="             => "=");

   subtype Parameters_Mode_Map is Defining_Name_To_Ada_Mode_Maps.Map;

   package Defining_Name_To_Basic_Decl_Maps is new
     Ada.Containers.Indefinite_Hashed_Maps
       (Key_Type        => Defining_Name'Class,
        Element_Type    => Basic_Decl'Class,
        Hash            => Defining_Name_Hash,
        Equivalent_Keys => "=",
        "="             => "=");

   subtype Parameters_Type_Map is Defining_Name_To_Basic_Decl_Maps.Map;

   package String_Vectors is new
     Ada.Containers.Indefinite_Vectors (Natural, String);

   subtype String_Vector is String_Vectors.Vector;

   package Stmt_Vectors is new
     Ada.Containers.Indefinite_Vectors (Natural, Stmt'Class);

   subtype Stmt_Vector is Stmt_Vectors.Vector;

   type Subprogram_Extractor is new Refactoring_Tool with
      record
         Unit        : Analysis_Unit;
         Start_Token : Token_Reference;
         End_Token   : Token_Reference;
         Start_Stmt  : Stmt;
         End_Stmt    : Stmt;
         Name        : Unbounded_String;
         Kind        : Ada_Subp_Kind;
      end record;

   type Extract_Subprogram_Strategy is abstract tagged
      record
         Unit        : Analysis_Unit;
         Start_Token : Token_Reference;
         End_Token   : Token_Reference;
         Start_Stmt  : Stmt;
         End_Stmt    : Stmt;
         Name        : Unbounded_String;
      end record;

   function Extract
     (Self : Extract_Subprogram_Strategy'Class)
      return Refactoring_Edits;
   --  Extracts a subprogram

   function Get_Local_Declarations
     (Self : Extract_Subprogram_Strategy)
      return Defining_Name_Ordered_Set;
   --  Find all object declaration that are candidates to be parameters of
   --  the extracted subprogram

   function Get_Parameters_To_Extract
     (Self       : Extract_Subprogram_Strategy;
      Candidates : Defining_Name_Ordered_Set;
      Statements : Stmt_Vector)
      return Defining_Name_Ordered_Set is abstract;
   --  Filters Candidates by checking which ones are references in
   --  Statements. These will need to be parameters of the extracted function.
   --  Additional checks might be needed, depending what kind of subprogram
   --  we're extracting.

   function Get_Parameters_Mode
     (Self       : Extract_Subprogram_Strategy;
      Parameters : Defining_Name_Ordered_Set;
      Statements : Stmt_Vector)
      return Parameters_Mode_Map is abstract;
   --  For each Parameter of Parameters, compute its mode based on its usage in
   --  Statements, i.e., if it is read or written.

   function Get_Parameters_Type
     (Self       : Extract_Subprogram_Strategy;
      Parameters : Defining_Name_Ordered_Set)
      return Parameters_Type_Map;
   --  For each Parameter of Parameters, compute its type

   function Build_Extracted_Subprogram_Parameters
     (Self            : Extract_Subprogram_Strategy;
      Parameters      : Defining_Name_Ordered_Set;
      Parameters_Mode : Parameters_Mode_Map;
      Parameters_Type : Parameters_Type_Map)
      return String_Vector;
   --  Returns a String_Vector with all the Param_Specs of the extracted
   --  subprogram.

   function Build_Extracted_Subprogram_Statements
     (Self : Extract_Subprogram_Strategy)
      return String_Vector is abstract;
   --  Returns a String_Vector with all Stmts of the extracted subprogram

   function Build_Extracted_Subprogram
     (Self        : Extract_Subprogram_Strategy;
      Params      : String_Vector;
      Statements  : String_Vector;
      Offset      : Natural;
      Indentation : Natural := 3)
      return String is abstract;
   --  Returns the Ada code of the extracted subprogram

   function Build_Extracted_Subprogram_Call
     (Self       : Extract_Subprogram_Strategy;
      Name       : String;
      Parameters : String_Vector)
      return String is abstract;
   --  Returns the Ada code of the extracted subprogram call

   type Procedure_Extractor is new Extract_Subprogram_Strategy with
     null record;

   overriding
   function Get_Parameters_To_Extract
     (Self       : Procedure_Extractor;
      Candidates : Defining_Name_Ordered_Set;
      Statements : Stmt_Vector)
      return Defining_Name_Ordered_Set;

   overriding
   function Get_Parameters_Mode
     (Self       : Procedure_Extractor;
      Parameters : Defining_Name_Ordered_Set;
      Statements : Stmt_Vector)
      return Parameters_Mode_Map;

   overriding
   function Build_Extracted_Subprogram_Statements
     (Self : Procedure_Extractor)
      return String_Vector;

   overriding
   function Build_Extracted_Subprogram
     (Self        : Procedure_Extractor;
      Params      : String_Vector;
      Statements  : String_Vector;
      Offset      : Natural;
      Indentation : Natural := 3)
      return String;

   overriding
   function Build_Extracted_Subprogram_Call
     (Self       : Procedure_Extractor;
      Name       : String;
      Parameters : String_Vector)
      return String;

   type Function_Extractor is new Extract_Subprogram_Strategy with
     null record;

   overriding
   function Get_Parameters_To_Extract
     (Self       : Function_Extractor;
      Candidates : Defining_Name_Ordered_Set;
      Statements : Stmt_Vector)
      return Defining_Name_Ordered_Set;

   overriding
   function Get_Parameters_Mode
     (Self       : Function_Extractor;
      Parameters : Defining_Name_Ordered_Set;
      Statements : Stmt_Vector)
      return Parameters_Mode_Map;

   overriding
   function Build_Extracted_Subprogram_Statements
     (Self : Function_Extractor)
      return String_Vector;

   overriding
   function Build_Extracted_Subprogram
     (Self        : Function_Extractor;
      Params      : String_Vector;
      Statements  : String_Vector;
      Offset      : Natural;
      Indentation : Natural := 3)
      return String;

   overriding
   function Build_Extracted_Subprogram_Call
     (Self       : Function_Extractor;
      Name       : String;
      Parameters : String_Vector)
      return String;

end LAL_Refactor.Extract_Subprogram;