49
51
CSV_Separator : constant array (Output_Format range CSV..CSVX) of Wide_Character := (',', ';');
51
Not_Found : constant := 0;
52
Adactl_Mark : constant Wide_String := "##";
53
Adactl_Tag : constant Wide_String := "--" & Adactl_Mark;
53
Not_Found : constant := 0;
55
55
Error_Count : Natural := 0;
56
56
Warning_Count : Natural := 0;
58
58
Uncheckable_Used : array (Uncheckable_Consequence) of Boolean := (others => False);
59
Uncheckable_Types : array (Uncheckable_Consequence) of Rule_Types;
59
Uncheckable_Types : array (Uncheckable_Consequence) of Control_Kinds;
60
60
Uncheckable_Labels : array (Uncheckable_Consequence) of Ada.Strings.Wide_Unbounded.Unbounded_Wide_String;
61
type False_Positive_Info (Len : Positive) is
64
Msg : Wide_String (1 .. Len);
66
package False_Positive_List is new Linear_Queue (False_Positive_Info);
67
package False_Positive_Map is new Binary_Map (Unbounded_Wide_String, False_Positive_List.Queue);
68
False_Positive_Messages : False_Positive_Map.Map;
69
-- The above map maps Rule Id's to a list of delayed false positive messages
62
72
package Counters is new Binary_Map (Unbounded_Wide_String, Natural);
63
73
Rule_Counter : Counters.Map;
64
Stats_Counters : array (Rule_Types) of Counters.Map;
74
Stats_Counters : array (Control_Kinds) of Counters.Map;
75
-- Note on the management of stat counters:
76
-- An entry in each map of Stats_Counters is added by Rule_Manager (Init_Stats)
77
-- when a new control is added. This is necessary to know about rules that were
78
-- not triggered at all.
79
-- However, this does not guarantee that every rule is present in the map, because
80
-- of Uncheckable, which does not follow the normal naming scheme of rules.
81
-- Therefore, a default value must still be provided when fetching from those maps.
81
procedure Update (Rule_Id : in Wide_String;
82
Rule_Label : in Wide_String;
98
procedure Update (Id : in Wide_String;
99
Label : in Wide_String;
83
100
Line : in Wide_String;
84
101
Single_Line : in Boolean;
85
102
Active : in out Boolean) is
86
103
use Utilities, Ada.Strings.Wide_Fixed;
88
Pos : Natural := Index (Line, Adactl_Tag);
105
Mark1 : constant Wide_String := "--" & To_Wide_String (Adactl_Tag1);
106
Mark2 : constant Wide_String := To_Wide_String (Adactl_Tag2);
107
Pos : Natural := Index (Line, Mark1);
90
109
function Next_Word return Wide_String is
200
220
-- Active does not change
227
function "and" (Left, Right : Wide_String) return Wide_String is
229
case Format_Option is
231
return Left & ": " & Right;
233
return Left & CSV_Separator (Format_Option) & Right;
235
return Left & CSV_Separator (CSVX) & Right;
243
procedure Raw_Report (Message : Wide_String) is
244
use Ada.Wide_Text_IO;
207
procedure Report (Rule_Id : in Wide_String;
208
Rule_Label : in Wide_String;
209
Rule_Type : in Rule_Types;
211
Msg : in Wide_String) is
253
procedure Report (Rule_Id : in Wide_String;
254
Ctl_Label : in Wide_String;
255
Ctl_Kind : in Control_Kinds;
257
Msg : in Wide_String)
259
-- This one is the "true" Report procedure, i.e. the other Report procedure is just
260
-- a front-end to this one.
212
261
use Utilities, Adactl_Options;
214
Label : constant Wide_String := Choose (Rule_Label, Otherwise => Rule_Id);
263
Label : constant Wide_String := Choose (Ctl_Label, Otherwise => Rule_Id);
215
264
Line : Wide_String (1..1024);
216
265
Line_Last : Natural := 0;
262
329
Put (CSV_Separator (Format_Option));
264
331
Put (CSV_Separator (Format_Option));
265
Put (Choose (Rule_Label, Otherwise => """"""));
332
Put (Choose (Ctl_Label, Otherwise => """"""));
266
333
Put (CSV_Separator (Format_Option));
268
335
Put (CSV_Separator (Format_Option));
269
336
Put (Quote (Msg));
272
if Loc /= Null_Location then
339
if Loc = Null_Location then
340
Put (Line (1 .. Line_Last));
273
342
Put (Image (Loc));
344
Current_Col := Col (Current_Output);
345
Put (Line (1 .. Line_Last));
347
Set_Col (Current_Col + Ada.Wide_Text_IO.Count (Get_First_Column (Loc)) - 1);
276
Current_Col := Col (Current_Output);
277
Put (Line (1 .. Line_Last));
279
Set_Col (Current_Col + Ada.Wide_Text_IO.Count (Get_First_Column (Loc)) - 1);
288
359
end Issue_Message;
362
use Counters, False_Positive_Map;
291
363
Active : Boolean := True;
294
if not Ignore_Option or Format_Option = Source then
366
if Error_Count = Max_Errors or Error_Count + Warning_Count = Max_Messages then
367
-- This can happen for finalization messages after the run has been previously cancelled
368
-- due to too many errors/messages
372
-- Output delayed false positive messages for this rule
373
-- There can be such messages only if Uncheckable has been activated
374
if Is_Present (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id)) then
376
use False_Positive_List;
377
Message_Queue : constant Queue := Fetch (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id));
378
Current : Cursor := First (Message_Queue);
380
-- Delete entry in map here to avoid infinite recursion
381
-- There is no problem, since Queues are controlled, the queue will be released when
382
-- exiting the block.
383
Delete (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id));
384
while Has_Element (Current) loop
386
Mess_Info : constant False_Positive_Info := Fetch (Current);
389
To_Wide_String (Uncheckable_Labels (False_Positive)),
390
Uncheckable_Types (False_Positive),
394
Current := Next (Current);
399
if Format_Option = Source
400
or (Format_Option /= None and not Ignore_Option)
296
403
use Ada.Characters.Handling, Ada.Wide_Text_IO;
404
Source_File : File_Type;
301
408
To_String (Get_File_Name (Loc)),
302
409
Form => Implementation_Options.Form_Parameters);
304
411
for I in Natural range 1 .. Get_First_Line (Loc) - 1 loop
305
Get_Line (File, Line, Line_Last);
412
Get_Line (Source_File, Line, Line_Last);
306
413
if not Ignore_Option then
307
Update (Rule_Id, Rule_Label, Line (Line'First .. Line_Last), Single_Line => False, Active => Active);
414
Update (Rule_Id, Ctl_Label, Line (Line'First .. Line_Last), Single_Line => False, Active => Active);
311
Get_Line (File, Line, Line_Last);
418
Get_Line (Source_File, Line, Line_Last);
312
419
if not Ignore_Option then
313
Update (Rule_Id, Rule_Label, Line (Line'First .. Line_Last), Single_Line => True, Active => Active);
420
Update (Rule_Id, Ctl_Label, Line (Line'First .. Line_Last), Single_Line => True, Active => Active);
318
425
when Name_Error =>
319
426
-- if file is not found ???,
320
427
-- consider that rule is active
323
if Is_Open (File) then
430
if Is_Open (Source_File) then
353
461
if Stats_Level >= Nulls_Only then
355
463
Key : constant Unbounded_Wide_String := To_Unbounded_Wide_String (Rule_Id
356
& Choose (Rule_Label = "",
464
& Choose (Ctl_Label = "",
360
Add (Stats_Counters (Rule_Type), Key, Fetch (Stats_Counters (Rule_Type), Key) + 1);
468
Add (Stats_Counters (Ctl_Kind), Key, Fetch (Stats_Counters (Ctl_Kind), Key, Default_Value => 0) + 1);
472
if Error_Count = Max_Errors then
473
Raise_Exception (Cancellation'Identity, Message => "too many errors");
474
elsif Error_Count + Warning_Count = Max_Messages then
475
Raise_Exception (Cancellation'Identity, Message => "too many messages");
403
517
-- Uncheckable --
404
518
-----------------
406
Risk_Message : constant array (Uncheckable_Consequence) of Wide_String (1 .. 8)
407
:= ("positive", "negative");
409
520
procedure Uncheckable (Rule_Id : in Wide_String;
410
521
Risk : in Uncheckable_Consequence;
411
522
Loc : in Location;
412
523
Msg : in Wide_String)
415
Rule_Label : constant Wide_String := To_Wide_String (Uncheckable_Labels (Risk));
526
Label : constant Wide_String := To_Wide_String (Uncheckable_Labels (Risk));
417
528
if Uncheckable_Used (Risk) then
420
Uncheckable_Types (Risk),
422
Choose (Rule_Label /= "", "in rule " & Rule_Id & ": ", "")
423
& "Possible false " & Risk_Message (Risk) & ": " & Msg);
530
when False_Negative =>
533
Uncheckable_Types (Risk),
535
Choose (Label /= "", "in rule " & Rule_Id & ": ", "")
536
& "Possible false negative: " & Msg);
537
when False_Positive =>
538
-- False positive messages are delayed until the next call to Report from the
539
-- same rule. Therefore, false positive messages will not appear if there are
540
-- no messages from the rule at all.
542
use False_Positive_List, False_Positive_Map;
543
Rule_Queue : Queue := Fetch (False_Positive_Messages,
544
To_Unbounded_Wide_String (Rule_Id),
545
Default_Value => Empty_Queue);
546
Full_Msg : constant Wide_String := Choose (Label /= "", "in rule " & Rule_Id & ": ", "")
547
& "Possible false positive: " & Msg;
549
Append (Rule_Queue, (Full_Msg'Length,
552
Add (False_Positive_Messages, To_Unbounded_Wide_String (Rule_Id), Rule_Queue);
479
615
-------------------
481
617
procedure Report_Counts is
482
use Counters, Utilities, Ada.Wide_Text_IO;
618
use Counters, Ada.Wide_Text_IO;
484
620
procedure Report_One_Count (Key : in Unbounded_Wide_String; Counter_Value : in out Natural) is
486
Put (To_Wide_String (Key));
487
case Format_Option is
491
Put (CSV_Separator (Format_Option));
493
Put (Integer_Img (Counter_Value));
623
Raw_Report (To_Wide_String (Key) and Integer_Img (Counter_Value));
495
624
end Report_One_Count;
497
626
procedure Report_All_Counts is new Iterate (Report_One_Count);
499
if Is_Empty (Rule_Counter) then
628
if Is_Empty (Rule_Counter) or Format_Option = None then
589
718
Wide_Key : Wide_String := To_Wide_String (Key);
590
719
Dot_Found : Boolean := False;
592
for R in Rule_Types range Rule_Types'Succ (Rule_Types'First) .. Rule_Types'Last loop
593
Triggered_Count := Triggered_Count + Fetch (Stats_Counters (R), Key);
721
for R in Control_Kinds range Control_Kinds'Succ (Control_Kinds'First) .. Control_Kinds'Last loop
722
Triggered_Count := Triggered_Count + Fetch (Stats_Counters (R), Key, Default_Value => 0);
596
725
if Triggered_Count = 0 or else Stats_Level = Full then
597
726
case Format_Option is
727
when Gnat | Source | None =>
600
730
if Triggered_Count = 0 then
601
731
Put ("not triggered");
603
Put (To_Title (Rule_Types'Wide_Image (Rule_Types'First)));
733
Put (To_Title (Control_Kinds'Wide_Image (Control_Kinds'First)));
605
735
Put (Integer_Img (Counter_Value));
607
for R in Rule_Types range Rule_Types'Succ (Rule_Types'First) .. Rule_Types'Last loop
737
for R in Control_Kinds range Control_Kinds'Succ (Control_Kinds'First) .. Control_Kinds'Last loop
609
Put (To_Title (Rule_Types'Wide_Image (R)));
739
Put (To_Title (Control_Kinds'Wide_Image (R)));
611
Put (Integer_Img (Fetch (Stats_Counters (R), Key)));
741
Put (Integer_Img (Fetch (Stats_Counters (R), Key, Default_Value => 0)));
614
744
when CSV | CSVX =>
654
785
& CSV_Separator (Format_Option) & "Search"
655
786
& CSV_Separator (Format_Option) & "Count");
657
Report_All_Stats (Stats_Counters (Rule_Types'First));
788
Report_All_Stats (Stats_Counters (Control_Kinds'First));
660
791
if Stats_Level >= General then
662
Put ("Issued messages: Errors =" & Natural'Wide_Image (Nb_Errors));
663
Put (", Warnings =" & Natural'Wide_Image (Nb_Warnings));
793
Put ("Issued messages: Errors = " & Integer_Img (Nb_Errors));
794
Put (", Warnings = " & Integer_Img (Nb_Warnings));
666
797
end Report_Stats;
668
---------------------
669
-- Report_Counters --
670
---------------------
672
procedure Report_Counters is
677
798
end Framework.Reports;