@@ -66,6 +66,10 @@ package body Gnatcheck.Projects is
6666 Project_File_Set : Boolean := False;
6767 Project_Options : GPR2.Options.Object;
6868
69+ Rules_Attr : constant GPR2.Q_Attribute_Id :=
70+ (GPR2." +" (" Check" ), GPR2." +" (" Rules" ));
71+ Rule_File_Attr : constant GPR2.Q_Attribute_Id :=
72+ (GPR2." +" (" Check" ), GPR2." +" (" Rule_File" ));
6973 Default_Switches_Attr : constant GPR2.Q_Attribute_Id :=
7074 (GPR2." +" (" Check" ), GPR2." +" (" Default_Switches" ));
7175 Switches_Attr : constant GPR2.Q_Attribute_Id :=
@@ -179,39 +183,102 @@ package body Gnatcheck.Projects is
179183 -- ------------------------
180184
181185 procedure Extract_Tool_Options (My_Project : in out Arg_Project_Type) is
182- Proj : constant GPR2.Project.View.Object :=
183- My_Project.Tree.Namespace_Root_Projects.First_Element;
184-
185186 use GPR2;
186187 use GPR2.Project.Registry.Attribute;
187188
188- Ada_Idx : constant GPR2.Project.Attribute_Index.Object :=
189+ Proj : constant GPR2.Project.View.Object :=
190+ My_Project.Tree.Namespace_Root_Projects.First_Element;
191+ Ada_Idx : constant GPR2.Project.Attribute_Index.Object :=
189192 GPR2.Project.Attribute_Index.Create (Ada_Language);
190- Attr : GPR2.Project.Attribute.Object;
191- Command_Line : GNAT.OS_Lib.Argument_List_Access;
192-
193- begin
194- if Proj.Has_Attribute (Switches_Attr, Ada_Idx) then
195- Attr := Proj.Attribute (Switches_Attr, Ada_Idx);
196-
197- if Attr.Kind = Single then
193+ List_Val : GNAT.OS_Lib.Argument_List_Access;
194+
195+ function Load_List_Attribute
196+ (Attr_Id : GPR2.Q_Attribute_Id;
197+ Indexed : Boolean := False) return GNAT.OS_Lib.Argument_List_Access;
198+ -- Load the attribute designated by ``Attr_Id`` in the project ``Proj``
199+ -- as a list value, allocating and returning an ``Argument_List_Access``
200+ -- that the caller must free after usage.
201+ -- ``Indexed`` indicates whether the attribute ``Attr_Id`` is an indexed
202+ -- attribute, if ``True`` this procedure will look at the "ada" index of
203+ -- this attribute. See ``GPR2.Project.Attribute_Index`` package for more
204+ -- information about attribute indexes.
205+
206+ function Load_Single_Attribute
207+ (Attr_Id : GPR2.Q_Attribute_Id) return String;
208+ -- Load the attribute designated by ``Attr_Id`` in the project ``Proj``
209+ -- as a single value, returning is as a ``String``.
210+
211+ function Load_List_Attribute
212+ (Attr_Id : GPR2.Q_Attribute_Id;
213+ Indexed : Boolean := False) return GNAT.OS_Lib.Argument_List_Access
214+ is
215+ Attr : constant GPR2.Project.Attribute.Object :=
216+ (if Indexed
217+ then Proj.Attribute (Attr_Id, Ada_Idx)
218+ else Proj.Attribute (Attr_Id));
219+ Res : GNAT.OS_Lib.Argument_List_Access;
220+ begin
221+ if Attr.Kind /= List then
198222 Error
199- (String (Proj.Path_Name.Simple_Name)
200- & " : Check.Default_Switches value must be a list" );
223+ (String (Proj.Path_Name.Simple_Name) & " : " & Image (Attr_Id) &
224+ " value must be a list" );
201225 raise Parameter_Error;
202226 end if ;
203227
204- Command_Line := new String_List
228+ Res := new String_List
205229 (Attr.Values.First_Index .. Attr.Values.Last_Index);
206230 for J in Attr.Values.First_Index .. Attr.Values.Last_Index loop
207- Command_Line (J) := new String'(Attr.Values.Element (J).Text);
231+ Res (J) := new String'(Attr.Values.Element (J).Text);
232+ end loop ;
233+
234+ return Res;
235+ end Load_List_Attribute ;
236+
237+ function Load_Single_Attribute
238+ (Attr_Id : GPR2.Q_Attribute_Id) return String
239+ is
240+ Attr : constant GPR2.Project.Attribute.Object :=
241+ Proj.Attribute (Attr_Id);
242+ begin
243+ if Attr.Kind /= Single then
244+ Error
245+ (String (Proj.Path_Name.Simple_Name) & " : " & Image (Attr_Id) &
246+ " value must be a single value" );
247+ raise Parameter_Error;
248+ end if ;
249+
250+ return Attr.Value.Text;
251+ end Load_Single_Attribute ;
252+
253+ begin
254+ -- Process the rule list
255+ if Proj.Has_Attribute (Rules_Attr) then
256+ List_Val := Load_List_Attribute (Rules_Attr);
257+ for Rule of List_Val.all loop
258+ Add_Rule_By_Name (Rule.all , Prepend => True);
208259 end loop ;
260+ Free (List_Val);
261+ end if ;
262+
263+ -- Process the LKQL rule file
264+ -- Process the rule list
265+ if Proj.Has_Attribute (Rule_File_Attr) then
266+ declare
267+ Rule_File : constant String :=
268+ Load_Single_Attribute (Rule_File_Attr);
269+ begin
270+ Set_LKQL_Rule_File
271+ (My_Project.Get_Project_Relative_File (Rule_File));
272+ end ;
273+ end if ;
209274
275+ -- Process additional GNATcheck switches
276+ if Proj.Has_Attribute (Switches_Attr, Ada_Idx) then
277+ List_Val := Load_List_Attribute (Switches_Attr, Indexed => True);
210278 Scan_Arguments
211279 (My_Project => My_Project,
212- Args => Command_Line);
213-
214- Free (Command_Line);
280+ Args => List_Val);
281+ Free (List_Val);
215282 end if ;
216283 end Extract_Tool_Options ;
217284
@@ -666,6 +733,26 @@ package body Gnatcheck.Projects is
666733 " Builder. The first string should always be -rules to specify " &
667734 " that all the other options belong to the -rules section of " &
668735 " the parameters to 'gnatcheck'." );
736+ Add
737+ (Rules_Attr,
738+ Index_Type => GPR2.Project.Registry.Attribute.No_Index,
739+ Value => List,
740+ Value_Case_Sensitive => False,
741+ Is_Allowed_In => Everywhere);
742+ GPR2.Project.Registry.Attribute.Description.Set_Attribute_Description
743+ (Rules_Attr,
744+ " Value is a list of GNATcheck rule names to enable when running " &
745+ " GNATcheck on this project." );
746+ Add
747+ (Rule_File_Attr,
748+ Index_Type => GPR2.Project.Registry.Attribute.No_Index,
749+ Value => Single,
750+ Value_Case_Sensitive => True,
751+ Is_Allowed_In => Everywhere);
752+ GPR2.Project.Registry.Attribute.Description.Set_Attribute_Description
753+ (Rule_File_Attr,
754+ " Value is the name of an LKQL rule file to use when running " &
755+ " GNATcheck in this project." );
669756 Add
670757 (Switches_Attr,
671758 Index_Type => Language_Index,
@@ -1002,6 +1089,21 @@ package body Gnatcheck.Projects is
10021089 end if ;
10031090 end Add_Rule_Option ;
10041091
1092+ -- --------------------
1093+ -- Add_Rule_By_Name --
1094+ -- --------------------
1095+
1096+ procedure Add_Rule_By_Name
1097+ (Rule_Name : String;
1098+ Prepend : Boolean := False)
1099+ is
1100+ Lower_Rule : constant String := To_Lower (Rule_Name);
1101+ Prefix : constant String :=
1102+ (if Lower_Rule = " all" then " +" else " +R" );
1103+ begin
1104+ Add_Rule_Option (Prefix & Lower_Rule, Prepend => Prepend);
1105+ end Add_Rule_By_Name ;
1106+
10051107 -- ----------------------
10061108 -- Set_LKQL_Rule_File --
10071109 -- ----------------------
@@ -1152,15 +1254,16 @@ package body Gnatcheck.Projects is
11521254 -- loop
11531255 if Args_From_Project then
11541256 declare
1155- In_Project_Msg : constant String := " forbidden in project file" ;
1257+ In_Project_Msg : constant String :=
1258+ " is forbidden in project file" ;
11561259 begin
1157- Disallow (Arg.Aggregate_Subproject.This, In_Project_Msg);
1158- Disallow (Arg.Project_File.This, In_Project_Msg);
1159- Disallow (Arg.Transitive_Closure.This, In_Project_Msg);
1160- Disallow (Arg.Scenario_Vars.This, In_Project_Msg);
1161- Disallow (Arg.Follow_Symbolic_Links.This, In_Project_Msg);
1162- Disallow (Arg.Rules.This, In_Project_Msg);
1163- Disallow (Arg.Rule_File.This, In_Project_Msg);
1260+ Disallow (Arg.Aggregate_Subproject.This, " -A " & In_Project_Msg);
1261+ Disallow (Arg.Project_File.This, " -P " & In_Project_Msg);
1262+ Disallow (Arg.Transitive_Closure.This, " -U " & In_Project_Msg);
1263+ Disallow (Arg.Scenario_Vars.This, " -Xname=val " & In_Project_Msg);
1264+ Disallow (Arg.Follow_Symbolic_Links.This, " -eL " & In_Project_Msg);
1265+ Disallow (Arg.Rules.This, " -r " & In_Project_Msg);
1266+ Disallow (Arg.Rule_File.This, " --rule-file " & In_Project_Msg);
11641267 end ;
11651268 end if ;
11661269
0 commit comments