15
15
-- of the license. --
16
16
-- ----------------------------------------------------------------------------
17
17
18
- with GPR2 ; use GPR2;
18
+ with Ada.Containers.Hashed_Sets ;
19
+
20
+ with GPR2 ; use GPR2;
21
+ with GPR2.Project.Registry.Attribute ; use GPR2.Project.Registry.Attribute;
22
+ with VSS.Strings.Hash ;
19
23
with VSS.String_Vectors ;
20
24
with VSS.JSON.Streams ;
21
25
with LSP.Enumerations ;
22
- with LSP.Structures.LSPAny_Vectors ; use LSP.Structures.LSPAny_Vectors;
26
+ with LSP.Structures.LSPAny_Vectors ; use LSP.Structures.LSPAny_Vectors;
23
27
24
28
package body LSP.Ada_Handlers.Project_Attributes_Commands is
25
29
30
+ package Virtual_String_Sets is new Ada.Containers.Hashed_Sets
31
+ (VSS.Strings.Virtual_String,
32
+ VSS.Strings.Hash,
33
+ VSS.Strings." =" ,
34
+ VSS.Strings." =" );
35
+
36
+ -- List of project attributes that should not be defined in
37
+ -- agggegate projects, but only in aggregated projects.
38
+ -- This list comes from the GPRbuild user's guide
39
+ -- (2.8.5. Syntax of aggregate projects).
40
+ Aggregatable_Attributes :
41
+ constant array (Positive range <>) of Q_Attribute_Id :=
42
+ [Languages,
43
+ Source_Files,
44
+ Source_List_File,
45
+ Source_Dirs,
46
+ Exec_Dir,
47
+ Library_Dir,
48
+ Library_Name,
49
+ Main,
50
+ Roots,
51
+ Externally_Built,
52
+ Inherit_Source_Path,
53
+ Excluded_Source_Dirs,
54
+ Locally_Removed_Files,
55
+ Excluded_Source_Files,
56
+ Excluded_Source_List_File,
57
+ Interfaces];
58
+
26
59
-- ----------
27
60
-- Create --
28
61
-- ----------
29
62
30
- overriding function Create
31
- (Any : not null access LSP.Structures.LSPAny_Vector)
32
- return Command
63
+ overriding
64
+ function Create
65
+ (Any : not null access LSP.Structures.LSPAny_Vector) return Command
33
66
is
34
67
use VSS.JSON.Streams;
35
68
use VSS.Strings;
@@ -77,6 +110,9 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
77
110
Response : in out LSP.Structures.LSPAny_Or_Null;
78
111
Error : in out LSP.Errors.ResponseError_Optional)
79
112
is
113
+ use VSS.Strings;
114
+ use VSS.String_Vectors;
115
+
80
116
procedure Append (Item : VSS.JSON.Streams.JSON_Stream_Element);
81
117
-- Append the given item to the JSON response
82
118
@@ -89,7 +125,7 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
89
125
Response.Value.Append (Item);
90
126
end Append ;
91
127
92
- Attr_Id : constant GPR2.Q_Optional_Attribute_Id :=
128
+ Attr_Id : constant GPR2.Q_Optional_Attribute_Id :=
93
129
(Pack =>
94
130
GPR2." +"
95
131
(Optional_Name_Type
@@ -98,17 +134,56 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
98
134
GPR2." +"
99
135
(Optional_Name_Type
100
136
(VSS.Strings.Conversions.To_UTF_8_String (Self.Attribute))));
101
- Is_List_Attribute : Boolean;
102
- Is_Known : Boolean;
103
- Values : constant VSS.String_Vectors.Virtual_String_Vector :=
104
- LSP.Ada_Contexts.Project_Attribute_Values
105
- (View => Handler.Project_Tree.Root_Project,
106
- Attribute => Attr_Id,
107
- Index =>
108
- VSS.Strings.Conversions.To_UTF_8_String (Self.Index),
109
- Is_List_Attribute => Is_List_Attribute,
110
- Is_Known => Is_Known);
137
+ Index : constant String :=
138
+ VSS.Strings.Conversions.To_UTF_8_String (Self.Index);
139
+ Is_List_Attribute : Boolean;
140
+ Is_Known : Boolean;
141
+ Should_Aggregate_Values : constant Boolean :=
142
+ Handler.Project_Tree.Root_Project.Kind in Aggregate_Kind
143
+ and then (for some Attr of Aggregatable_Attributes => Attr = Attr_Id);
144
+ Values : VSS.String_Vectors.Virtual_String_Vector := [];
145
+ Already_Returned_Values : Virtual_String_Sets.Set := [];
111
146
begin
147
+ -- In case of aggregate projects and when the project attribute
148
+ -- can't be defined in the aggregate root project itself (e.g: 'Main'),
149
+ -- iterate over all the aggregated projects to concatenate the
150
+ -- values instead.
151
+ if Should_Aggregate_Values then
152
+ for View of Handler.Project_Tree.Namespace_Root_Projects loop
153
+ Values.Append
154
+ (LSP.Ada_Contexts.Project_Attribute_Values
155
+ (View => View,
156
+ Attribute => Attr_Id,
157
+ Index => Index,
158
+ Is_List_Attribute => Is_List_Attribute,
159
+ Is_Known => Is_Known));
160
+
161
+ -- The queried attribute belongs to the list of all
162
+ -- the project attributes that can be aggregated when
163
+ -- dealing with a root aggregate project: ensure that GPR2
164
+ -- always know it, for each aggregated project.
165
+ pragma
166
+ Assert
167
+ (Is_Known,
168
+ VSS.Strings.Conversions.To_UTF_8_String
169
+ (" '"
170
+ & Self.Pkg
171
+ & " ."
172
+ & Self.Attribute
173
+ & " '' project attribute is unknown: project attributes "
174
+ & " that can be aggregated should always be known by GPR2" ));
175
+ end loop ;
176
+ else
177
+ Values :=
178
+ LSP.Ada_Contexts.Project_Attribute_Values
179
+ (View => Handler.Project_Tree.Root_Project,
180
+ Attribute => Attr_Id,
181
+ Index =>
182
+ VSS.Strings.Conversions.To_UTF_8_String (Self.Index),
183
+ Is_List_Attribute => Is_List_Attribute,
184
+ Is_Known => Is_Known);
185
+ end if ;
186
+
112
187
-- Return an error if the attribute is not known.
113
188
if not Is_Known then
114
189
Error :=
@@ -121,17 +196,31 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
121
196
122
197
Response := (Is_Null => False, Value => <>);
123
198
124
- -- Return a list object if we are dealing with a string list attribute,
125
- -- or a string otherwise.
126
- if Is_List_Attribute then
199
+ -- Return a list object if we are dealing with a string list attribute
200
+ -- or with aggregated values.
201
+ -- Return a simple string otherwise.
202
+ if Is_List_Attribute or else Should_Aggregate_Values then
127
203
Append ((Kind => VSS.JSON.Streams.Start_Array));
204
+
128
205
for Value of Values loop
129
- Append (Item => (VSS.JSON.Streams.String_Value, Value));
206
+
207
+ -- Filter any duplicate when dealing with aggregated values
208
+ -- since aggregated projects might have the exact same values
209
+ -- for a given attribute (e.g: 'Ada' for 'Languages' in
210
+ -- all the aggregated projects)
211
+ if not Should_Aggregate_Values
212
+ or else not Already_Returned_Values.Contains (Value)
213
+ then
214
+ Append (Item => (VSS.JSON.Streams.String_Value, Value));
215
+ end if ;
216
+ Already_Returned_Values.Include (Value);
130
217
end loop ;
218
+
131
219
Append ((Kind => VSS.JSON.Streams.End_Array));
132
220
else
133
221
Append
134
- (Item => (VSS.JSON.Streams.String_Value, Values.First_Element));
222
+ (Item =>
223
+ (VSS.JSON.Streams.String_Value, Values.First_Element));
135
224
end if ;
136
225
end Execute ;
137
226
0 commit comments