libgpr2_24.0.0_eda3c693/src/lib/gpr2-source_info.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
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
--
--  Copyright (C) 2019-2023, AdaCore
--
--  SPDX-License-Identifier: Apache-2.0 WITH LLVM-Exception
--

--  This object stores the information from a source. Those
--  information are coming either from a source parser or a
--  compilation artifact parser. The routine Used_Backend will return
--  the kind of parser that has been used.

with Ada.Calendar;
private with Ada.Containers.Indefinite_Vectors;
private with Ada.Containers.Ordered_Maps;
private with Ada.Containers.Vectors;

with GPR2.Unit.List;
with GPR2.Containers;

with GNATCOLL.Refcount;

package GPR2.Source_Info is

   use type Containers.Count_Type;
   use type GPR2.Unit.Library_Unit_Type;

   type Object is tagged private;
   --  The source information container

   Undefined : constant Object;

   type Backend is (None, LI, Source);
   --  None   : not yet parsed, no information
   --  LI     : information from compiler generated data (.ali or .d)
   --  Parser : information from source

   subtype Implemented_Backend is Backend range LI .. Source;
   --  The implemented backends. These are the values that are possible
   --  when checking which backend has been used to compute a specific data.

   type Backend_Set is array (Implemented_Backend) of Boolean;
   --  Set of backends to use in parser

   All_Backends : constant Backend_Set;
   --  All backends allowed

   No_Backends : constant Backend_Set;
   --  No backends allowed

   function Is_Defined (Self : Object) return Boolean;
   --  Returns True if Self is defined

   type Parse_State is (No, Partial, Full);

   function Is_Parsed (Self : Object) return Parse_State;

   function Is_Parsed (Self  : Object;
                       Index : Unit_Index) return Boolean;
   --  Returns True when the Unit in the source has been computed

   function Used_Backend (Self  : Object;
                          Index : Unit_Index) return Implemented_Backend
     with Pre => Self.Is_Defined and then Self.Is_Parsed (Index);
   --  Returns the backend used to compute the source information

   function Is_Ada (Self : Object) return Boolean
     with Pre => Self.Is_Defined;
   --  Returns True if language is Ada

   function Language (Self : Object) return Language_Id
     with Pre => Self.Is_Defined;
   --  Returns the language of the source

   function Build_Timestamp (Self  : Object;
                             Index : Unit_Index) return Ada.Calendar.Time
     with Inline,
          Pre => Self.Is_Defined;
   --  Returns last modification of the source file from the time point when
   --  the last successful build was done.

   function Checksum (Self : Object) return Word
     with Pre => Self.Is_Defined;

   function Has_Units (Self : Object) return Boolean
     with Pre => Self.Is_Defined;
   --  Returns True if source is unit-based (i.e. Ada)

   function Has_Unit (Self : Object; Unit : Name_Type) return Boolean
     with Pre => Self.Is_Defined and then Self.Has_Units;
   --  Returns True if Self contains the given unit

   function Kind
     (Self  : Object;
      Index : Unit_Index := No_Index) return Unit.Library_Unit_Type
     with Pre => Self.Is_Defined
                 and then (not Self.Has_Units
                           or else Self.Has_Unit_At (Index))
                 and then (Self.Has_Units or else Index = No_Index);
   --  Returns the kind of Self's source at the given index

   function Check_Unit
     (Self : Object;
      Name : Name_Type;
      Spec : Boolean;
      Unit : out GPR2.Unit.Object) return Boolean;
   --  Check if the unit exists in the source file and set Unit and returns
   --  True if found.
   --  If Spec is True search for the unit kind in Spec_Kind.
   --  Search for the Body_Kind or S_Separate otherwise.

   function Has_Unit_At
     (Self : Object; Index : Unit_Index) return Boolean
     with Pre => Self.Is_Defined and then Self.Has_Units;
   --  Returns True if Self has a compilation unit at Index

   function Has_Single_Unit (Self : Object) return Boolean
     with Pre => Self.Is_Defined and then Self.Has_Units;
   --  Returns true if the source contains a single unit

   function Has_Index (Self : Object) return Boolean
     with Pre => Self.Is_Defined;
   --  Returns True if source contains one or more units declared in Naming
   --  package with "at" Index.

   function Unit (Self  : Object;
                  Index : Unit_Index) return GPR2.Unit.Object
     with Pre => Self.Is_Defined
                   and then Self.Has_Units and then Self.Has_Unit_At (Index);

   function Units
     (Self : Object) return GPR2.Unit.List.Object
     with Inline,
          Pre  => Self.Is_Defined and then Self.Has_Units,
          Post => Units'Result.Length > 1
                  or else Self.Has_Single_Unit;
   --  Returns all compilation units for self

   function Unit_Name (Self  : Object;
                       Index : Unit_Index := No_Index) return Name_Type
     with Pre => Self.Is_Defined and then Self.Has_Units
                 and then Self.Has_Unit_At (Index);
   --  Returns the unit name for the source Self at Index (default = 1)

   function Is_Generic
     (Self : Object; Index : Unit_Index) return Boolean
     with Pre => Self.Is_Defined
                   and then
                 (not Self.Has_Units
                  or else Self.Has_Unit_At (Index));
   --  Returns True if the source Self has the generic unit at Index

   function Is_Implementation_Required
     (Self : Object; Index : Unit_Index) return Boolean
     with Pre => Self.Is_Defined
                 and then Self.Has_Unit_At (Index);
   --  Returns True if the source for the implementation is required for the
   --  compilation. This is the case for a generic package or a package having
   --  inlined routines.

   function Context_Clause_Dependencies
     (Self  : Object;
      Index : Unit_Index)
      return GPR2.Containers.Name_Set
     with Pre => Self.Is_Defined and then Self.Has_Units
                 and then Self.Has_Unit_At (Index);
   --  Returns the list of withed unit for Self's source at Index (default = 1)

   procedure Dependencies
     (Self   : Object;
      Index  : Unit_Index;
      Action : access procedure
                 (Unit_Name : Name_Type;
                  Sfile     : Simple_Name;
                  Kind      : GPR2.Unit.Library_Unit_Type;
                  Stamp     : Ada.Calendar.Time))
     with Pre => Self.Is_Defined;
   --  Call Action for each of unit dependencies

   procedure Set_Non_Ada
     (Self     : in out Object;
      Language : Language_Id;
      Kind     : GPR2.Unit.Library_Unit_Type);

   procedure Set_Ada
     (Self  : in out Object;
      Units : GPR2.Unit.List.Object)
     with Post => Self.Is_Ada and then Self.Has_Index;
   --  Set Ada-specific info for a multi-unit source

   procedure Set_Ada
     (Self          : in out Object;
      Unit          : GPR2.Unit.Object;
      Is_RTS_Source : Boolean)
     with Pre  => Unit.Is_Defined,
          Post => Self.Is_Ada
                    and then not Self.Has_Index and then Self.Has_Single_Unit;
   --  Set Ada-specific info for a single-unit source

   procedure Update_Kind
     (Self  : in out Object;
      Kind  : GPR2.Unit.Library_Unit_Type;
      Index : Unit_Index)
     with Pre  => Self.Is_Defined
               and then Kind in GPR2.Unit.S_Spec_Only | GPR2.Unit.S_Body_Only;
   --  Update kind for the source, this is only to adjust the kind to
   --  S_Spec_Only and S_Body_Only after a source based parser has been used.

   procedure Update_Build_Timestamp
     (Self : in out Object; Stamp : Ada.Calendar.Time)
     with Pre  => Self.Is_Defined;
   --  Update source file timestamp

   procedure Reset (Self : in out Object)
     with Post => not Self.Is_Defined;
   --  Reset Self to undefined

   procedure Clear (Self : in out Object);
   --  Clear units and dependencies

   function Is_Runtime (Self : Object) return Boolean;
   --  Is the source from runtime library

private

   use Ada.Calendar;

   type Dependency (Name_Length, SFile_Length : Natural) is record
      Unit_Kind : GPR2.Unit.Library_Unit_Type;
      --  Unit kind (S_Separate for a subunit)

      Stamp     : Time := No_Time;
      --  Time stamp value. Note that this will be all zero characters for the
      --  dummy entries for missing or non-dependent files.

      Checksum  : Word := 0;
      --  Checksum value. Note that this will be all zero characters for the
      --  dummy entries for missing or non-dependent files
      --  Zero if Sfile is configuration pragmas file.

      Unit_Name : String (1 .. Name_Length);
      --  Name of the unit or subunit.
      --  Empty if Sfile is configuration pragmas file.

      Sfile     : String (1 .. SFile_Length);
      --  Base name of the source file for Ada.
      --  Full path name for none-Ada and for configuration pragmas files.
   end record;

   package Dependency_Vectors is new Ada.Containers.Indefinite_Vectors
     (Positive, Dependency);

   package Dependency_Vectors_Ref is new GNATCOLL.Refcount.Shared_Pointers
     (Dependency_Vectors.Vector);

   function Equ (L, R : Dependency_Vectors_Ref.Ref) return Boolean is
     (if L.Is_Null and then R.Is_Null then True
      elsif L.Is_Null or else R.Is_Null then False
      else Dependency_Vectors."=" (L.Get.Element.all, R.Get.Element.all));

   package Unit_Dependencies is new Ada.Containers.Ordered_Maps
     (Unit_Index, Dependency_Vectors_Ref.Ref, "=" => Equ);

   type Unit_Info is record
      Build_Timestamp : Calendar.Time := No_Time;
      Parsed          : Backend := None;
   end record;

   package Unit_Info_Vectors is new Ada.Containers.Vectors
     (Multi_Unit_Index, Unit_Info);

   type Object is tagged record
      --  Common to all sources
      Language      : Language_Id   := No_Language;
      Checksum      : Word          := 0;
      Dependencies  : Unit_Dependencies.Map;
      --  Non unit based source info
      Kind          : GPR2.Unit.Library_Unit_Type := GPR2.Unit.S_Separate;
      --  Non unit-based or single unit info
      Parsed        : Backend := None;
      LI_Timestamp  : Calendar.Time := No_Time;
      --  unit based sources properties
      Is_RTS_Source : Boolean := False;
      CU_List       : GPR2.Unit.List.Object;
      --  multi-unit specific source property
      CU_Info       : Unit_Info_Vectors.Vector;
   end record;
   --  Record that holds relevant source information, including details about
   --  the compilation unit(s) for Ada sources.

   Undefined : constant Object := (others => <>);

   All_Backends : constant Backend_Set := (others => True);
   No_Backends  : constant Backend_Set := (others => False);

   function Is_Defined (Self : Object) return Boolean is (Self /= Undefined);

   function Checksum (Self : Object) return Word is
     (Self.Checksum);

   function Has_Units (Self : Object) return Boolean is (Self.Is_Ada);

   function Used_Backend (Self  : Object;
                          Index : Unit_Index)
                          return Implemented_Backend
   is (if Index = No_Index
       then Self.Parsed
       else Self.CU_Info (Index).Parsed);

   function Has_Single_Unit (Self : Object) return Boolean is
     (Self.CU_List.Length = 1);

   function Has_Index (Self : Object) return Boolean is
     (Self.CU_List.Is_Indexed_List);

   function Is_Ada (Self : Object) return Boolean is
     (Self.Language = Ada_Language);

   function Language (Self : Object) return Language_Id is
     (Self.Language);

   function Is_Runtime (Self : Object) return Boolean is
     (Self.Is_RTS_Source);

   function Is_Parsed (Self  : Object;
                       Index : Unit_Index) return Boolean is
     (if Index = No_Index
      then Self.Parsed /= None
      else
        (if Self.CU_Info.Last_Index >= Index
         then Self.CU_Info (Index).Parsed /= None
         else False));

   function Units
     (Self : Object) return GPR2.Unit.List.Object is (Self.CU_List);

end GPR2.Source_Info;