1515-- of the license. --
1616-- ----------------------------------------------------------------------------
1717
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 ;
1923with VSS.String_Vectors ;
2024with VSS.JSON.Streams ;
2125with LSP.Enumerations ;
22- with LSP.Structures.LSPAny_Vectors ; use LSP.Structures.LSPAny_Vectors;
26+ with LSP.Structures.LSPAny_Vectors ; use LSP.Structures.LSPAny_Vectors;
2327
2428package body LSP.Ada_Handlers.Project_Attributes_Commands is
2529
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+
2659 -- ----------
2760 -- Create --
2861 -- ----------
2962
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
3366 is
3467 use VSS.JSON.Streams;
3568 use VSS.Strings;
@@ -77,6 +110,9 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
77110 Response : in out LSP.Structures.LSPAny_Or_Null;
78111 Error : in out LSP.Errors.ResponseError_Optional)
79112 is
113+ use VSS.Strings;
114+ use VSS.String_Vectors;
115+
80116 procedure Append (Item : VSS.JSON.Streams.JSON_Stream_Element);
81117 -- Append the given item to the JSON response
82118
@@ -89,7 +125,7 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
89125 Response.Value.Append (Item);
90126 end Append ;
91127
92- Attr_Id : constant GPR2.Q_Optional_Attribute_Id :=
128+ Attr_Id : constant GPR2.Q_Optional_Attribute_Id :=
93129 (Pack =>
94130 GPR2." +"
95131 (Optional_Name_Type
@@ -98,17 +134,56 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
98134 GPR2." +"
99135 (Optional_Name_Type
100136 (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 := [];
111146 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+
112187 -- Return an error if the attribute is not known.
113188 if not Is_Known then
114189 Error :=
@@ -121,17 +196,31 @@ package body LSP.Ada_Handlers.Project_Attributes_Commands is
121196
122197 Response := (Is_Null => False, Value => <>);
123198
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
127203 Append ((Kind => VSS.JSON.Streams.Start_Array));
204+
128205 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);
130217 end loop ;
218+
131219 Append ((Kind => VSS.JSON.Streams.End_Array));
132220 else
133221 Append
134- (Item => (VSS.JSON.Streams.String_Value, Values.First_Element));
222+ (Item =>
223+ (VSS.JSON.Streams.String_Value, Values.First_Element));
135224 end if ;
136225 end Execute ;
137226
0 commit comments