Skip to content

Commit 4a854d1

Browse files
committed
Add 'Rules' and 'Rule_File' GPR attributes
1 parent a050779 commit 4a854d1

File tree

22 files changed

+308
-33
lines changed

22 files changed

+308
-33
lines changed

lkql_checker/doc/gnatcheck_rm/using_gnatcheck.rst

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,27 +331,49 @@ the ``Check`` package in the GPR file you're providing to GNATcheck through the
331331
Inside this package you can define the following attributes to configure
332332
GNATcheck:
333333

334-
* ``Switches``
334+
``Rules``
335+
Value is a list of rules to enable when invoking ``gnatcheck`` on this
336+
project. Values provided in this attribute behave as the ones provided with
337+
the ``--rule`` switch.
338+
339+
If the ``--rule`` switch is set when calling ``gnatcheck`` on a project file
340+
defining this attribute, then, values are concatenated.
341+
342+
``Rule_File``
343+
Value is a path to a LKQL rule file. The path is relative to the project
344+
file that defines this attribute. See :ref:`LKQL_options_file` for more
345+
information.
346+
347+
If the ``--rule-file`` switch is set when calling ``gnatcheck`` on a project
348+
file defining this attribute, then, an error is emitted and ``gnatcheck``
349+
will exit with an error code.
350+
351+
``Switches``
335352
Index is a language name. Value is a list of additional switches to be used
336353
when invoking ``gnatcheck``.
337354

355+
If a switch is provided in both command-line and ``Switches`` attribute,
356+
then, the value provided through the command-line is used.
357+
338358
.. attention::
339359

340360
There are several command-line switches that you cannot pass through the
341361
``Switches`` attribute:
342362

363+
* ``--version``
364+
* ``--help``
343365
* ``-P``
344366
* ``-U``
345367
* ``-Xname=value``
346368
* ``-eL``
347-
* ``-r, --rule [rule_name]``
348-
* ``--rule-file=filename``
369+
* ``-r, --rule [rule_name]`` (use ``Rules`` attribute instead)
370+
* ``--rule-file=filename`` (use ``Rule_File`` attribute instead)
349371

350372
If you're providing one of those switches through the ``Switches`` or the
351-
``Default_Switches`` attribute, GNATcheck will raise an error message and
373+
``Default_Switches`` attribute, GNATcheck will emit an error message and
352374
exit with an error code.
353375

354-
* ``Default_Switches``
376+
``Default_Switches``
355377
Same as ``Switches``, but provided additional switches will apply only if
356378
there is no applicable ``Switches`` attribute.
357379

lkql_checker/src/gnatcheck-projects.adb

Lines changed: 121 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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
------------------------

lkql_checker/src/gnatcheck-projects.ads

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,12 @@ package Gnatcheck.Projects is
249249
-- If ``Prepend`` is set to True, add the rule option at the start of
250250
-- the processing list.
251251

252+
procedure Add_Rule_By_Name
253+
(Rule_Name : String;
254+
Prepend : Boolean := False);
255+
-- Use ``Add_Rule_Option`` to forge a new rule option enabling the given
256+
-- rule without any parameter.
257+
252258
procedure Set_LKQL_Rule_File (File : String);
253259
-- Set the given ``File`` as the LKQL rule file to process during the
254260
-- execution of ``Process_Rule_Options``.

lkql_checker/src/gnatcheck_main.adb

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
--
55

66
with Ada.Calendar;
7-
with Ada.Characters.Handling; use Ada.Characters.Handling;
87
with Ada.Command_Line;
98
with Ada.Directories;
109
with Ada.Environment_Variables;
@@ -468,13 +467,7 @@ begin
468467
-- second argument parsing to avoid duplicate rule names coming from the
469468
-- command-line.
470469
for Rule of Arg.Rules.Get loop
471-
declare
472-
Lower_Rule : constant String := To_Lower (To_String (Rule));
473-
Prefix : constant String :=
474-
(if Lower_Rule = "all" then "+" else "+R");
475-
begin
476-
Add_Rule_Option (Prefix & Lower_Rule, Prepend => True);
477-
end;
470+
Add_Rule_By_Name (To_String (Rule), Prepend => True);
478471
end loop;
479472

480473
-- Then analyze the command-line parameters
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
project Invalid is
2+
for Source_Dirs use ("src");
3+
4+
package Check is
5+
for Rule_File use ("rule_config.lkql");
6+
end Check;
7+
end Invalid;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
project Prj is
2+
for Source_Dirs use ("src");
3+
4+
package Check is
5+
for Rule_File use "rule_config.lkql";
6+
end Check;
7+
end Prj;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
val rules = @{
2+
goto_statements
3+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
procedure Main is
2+
begin
3+
goto lbl; -- FLAG (2)
4+
<<lbl>>
5+
end Main;
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Without additional rule file
2+
============================
3+
4+
main.adb:3:04: goto statement
5+
6+
With additional rule file
7+
=========================
8+
9+
gnatcheck: only one LKQL configuration file is allowed
10+
main.adb:3:04: goto statement
11+
>>>program returned status code 6
12+
13+
With invalid attribute value
14+
============================
15+
16+
gnatcheck: invalid.gpr:5:11: error: attribute "Check'Rule_File" expects a single value
17+
try "gnatcheck --help" for more information.
18+
>>>program returned status code 2
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
driver: gnatcheck
2+
format: brief
3+
project: prj.gpr
4+
tests:
5+
- label: Without additional rule file
6+
- label: With additional rule file
7+
lkql_rule_file: other.lkql
8+
- label: With invalid attribute value
9+
project: invalid.gpr

0 commit comments

Comments
 (0)