File: gch-rules.ads

package info (click to toggle)
gch 19990519-6
  • links: PTS
  • area: main
  • in suites: potato
  • size: 500 kB
  • ctags: 19
  • sloc: ada: 1,780; perl: 1,330
file content (346 lines) | stat: -rw-r--r-- 14,801 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
------------------------------------------------------------------------------
--                                                                          --
--                            GCH COMPONENTS                                --
--                                                                          --
--                          G C H . R U L E S                               --
--                                                                          --
--                              S p e c                                     --
--                                                                          --
--                                                                          --
--              Copyright (c) 1999, Vitali Sh.Kaufman.                      --
--                                                                          --
--  Gch is distributed as free software; that is with full sources          --
--  and in the hope that it will be useful, but WITHOUT ANY WARRANTY;       --
--  without even the implied warranty of MERCHANTABILITY or FITNESS         --
--  FOR A PARTICULAR PURPOSE. You can freely copy, modify and redistribute  --
--  this software, provided that full sources are available for the version --
--  being distribute (original and modified), and for a modified version,   --
--  any changes that you have made are clearly indicated.                   --
--                                                                          --
--  Gch was developed by Vitali Sh. Kaufman using a prototype               --
--  and consultations by Sergey I. Rybin.                                   --
------------------------------------------------------------------------------

--  This package defines the rules to be checked by Gch and a top-level
--  data structure used for rule checking process.

--  ???
with Ada.Wide_Text_IO;        use Ada.Wide_Text_IO;

with Asis;                    use Asis;

with GNAT.OS_Lib;             use GNAT.OS_Lib;

with Gch.Options;         use Gch.Options;
with Gch.Globals;         use Gch.Globals;

package Gch.Rules is

   ------------------------------
   --  Rule checking functions --
   ------------------------------

--  The specs for all the functions checking particular rules should go here.
--  Rules could be "local" or "global" depending of wheither they need to
--  collect some information about the unit as a whole or not.

--  Local rules could be checked by a rule checking function
--  that is called as an pre-operation by Check_Unit_Elements,
--  an instantiation of Traverse_Unit.
--  Each global rule needs also a finalization part of rule checking function.

--  A rule "Use  named  parameter association in calls of infrequently
--  used subprograms or entries with many formal parameters" can serve as
--  an example of such global (non local) kind of rules.
--  It is impossible to recognize the violations before the whole unit
--  is checked.
--  All diagnostics of such global rules should be collected inside them until
--  a finalization part of the rule.
--
--  Array Rules contains references to all rule checking functions and a
--  Global flag that marks checking functions of global rules.

--  So, for now we have not use post-operations while traversing elements.
--  It is unclear how often they could be really useful. That is why we prefer
--  to use post-operations (finalization part of rule checking functions)
--  just for units, not for elements.
--  The decision could be change if future rule implementation analysis show
--  that element post-operations are preferable.

--  From an other side, a post-check of a single element could lead to
--  finding of several violations for several different elements. That is why
--  some potential violation buffers could be created to store such potential
--  violations before usage by such kind post-checks.

--  The specs could be removed to minimize changes needed for the rule
--  set modification but an assignment should be used instead
--  of initialization.

--  These specifications could be also used as an convenient location of
--  the rule switching comments (now they are below at Rules array
--  initialization).

   function QS_5_1_1_1 (E : Element) return Boolean;
   function QS_5_1_1_2 (E : Element) return Boolean;
   function QS_5_2_2 (E : Element) return Boolean;
   function QS_4_3_1_10 (E : Element) return Boolean;
   function QS_4_3_1_11 (E : Element) return Boolean;
   function Rule_0 (E : Element) return Boolean;
   function Rule_1 (E : Element) return Boolean;

   type Rule_Access is access function (E : Element) return Boolean;
   --  This type is used to point to rule checking routines for individual
   --  rules. A rule checking routine is a function which takes an Element
   --  and returnes True iF the rule to check is either obeyed or non
   --  applicable for an argument Element. Any exception raised in a rule
   --  checking routine should propagate out from the routine.

   type Rule_Record is record
      Diagnosis : String_Access;
      --  The diagnostic message to be generated in case of rule violation.
      Rule_Name  : String_Access;
      --  Short description (name, if possible) of the rule
      On : Boolean := True;
      --  If the rule is on; is set using rules.ini
      Global : Boolean := False;
      --  If the rule checking needs finalization
      Rule_To_Check : Rule_Access;
      --  The rule checking function
   end record;

   type Rule_Array is array (Positive range <>) of Rule_Record;

   --  The Rules array below defines a set of rules to be checked by Gch.
   --  To modify an existing rule, correct the body of the corresponding rule
   --  checking subunit. To remove a check for a given
   --  rule, use the file rules.ini.
   --  To add a check for a new rule, add the corresponding rule
   --  function, add the corresponding value (that is, the aggregate of
   --  Rule_Record type containing the reference to this function and the
   --  corresponding diagnosis) to the following initialization aggregate
   --  for Rules, and edit rules.ini in an appropriate way.

   --  Extension note : Diagnosis field could be extended if we need more
   --  detailed diagnostics connected to some rules

   --  Caution: don't use the following aggregate to enable/disable rules.
   --  Use the file rules.ini for that.

   Rules : Rule_Array := (

--  + Replacing the plus by minus and back switches the following rule
      (Diagnosis  => new String' ("unnamed nested loop"),
       Rule_Name  => new String' ("Q&S 5.1.1(1)"),
       On => True,
       Global => False,
       Rule_To_Check => QS_5_1_1_1'Access),

--  + Replacing the plus by minus and back switches the following rule
      (Diagnosis  => new String' ("exit inside unnamed loop"),
       Rule_Name  => new String' ("Q&S 5.1.1(2)"),
       On => True,
       Global => False,
       Rule_To_Check => QS_5_1_1_2'Access),

--  + Replacing the plus by minus and back switches the following rule
      (Diagnosis  => new String' ("named parameter association recommended"),
       Rule_Name  => new String' ("Q&S 5.2.2"),
       On => True,
       Global => True, --  the rule needs finalization
       Rule_To_Check => QS_5_2_2'Access),

--  + Replacing the plus by minus and back switches the following rule
      (Diagnosis  => new String' ("explicitly raised predefined exception"),
       Rule_Name  => new String' ("Q&S 4.3.1(10)"),
       On => True,
       Global => False,
       Rule_To_Check => QS_4_3_1_10'Access),

--  + Replacing the plus by minus and back switches the following rule
      (Rule_To_Check => QS_4_3_1_11'Access,
       Global => False,
       Rule_Name  => new String' ("Q&S 4.3.1(11)"),
       On => True,
       Diagnosis  => new String' ("risk of propagation beyond scope")),

--  - Replacing the plus by minus and back switches the following rule
      (Diagnosis  => new String' ("redundant 'in'"),
       Rule_Name  => new String' ("Rule_0"),
       On => True,
       Global => False,
       Rule_To_Check => Rule_0'Access),

--  + Replacing the plus by minus and back switches the following rule
      (Diagnosis  => new String' ("multi-identifier declaration"),
       Rule_Name  => new String' ("Rule_1"),
       On => True,
       Global => False,
       Rule_To_Check => Rule_1'Access)

      );  -- end of Rules array initialization

   -------------------------
   --  List of Violations --
   -------------------------

   subtype Rule_Index is Positive range Rules'Range;
   Current_Rule : Rule_Index;
   --  used to store a checking rule index (to avoid additional
   --  parameters of rule checking functions

   type Rule_Violation_Node;
   --  to form a rule violation list Diagnostics defined below

   type Rule_Violation_Node_Access is access Rule_Violation_Node;

   type Rule_Violation_Node is record

      Bad_Element : Element;
      --  A source of violation, an ASIS Element where the violation is found

      Violated_Rule  : Rule_Index;
      --  Index of violated rule in the Rules array

      Next_Node : Rule_Violation_Node_Access;
      --  A reference to next node in a list

   end record;

   Diagnostics : Rule_Violation_Node_Access;
   --  A list of violations found by Gch

   Last_Diagnosis : Rule_Violation_Node_Access;
   --  End of the list of violations found by Gch

   procedure Add_Violation (Elem : Element; Rule : Rule_Index);
   --  Adds a new violation found into Diagnostics list and
   --  changes global statistics.

private
--  contains common "private" objects for rule checking procedures
--  and also specific "private" objects for some (often global) rules
--  that are impossible to place into appropriate rule checking subunits

   package Int_IO is new Integer_IO (Integer);
   use Int_IO;
   package Nat_IO is new Integer_IO (Natural);
   use Nat_IO;

--   ---------------------------
--   --  Report_ASIS_Failure  --
--   ---------------------------

   procedure Report_ASIS_Failure (Rule : Wide_String := "");
   --  Should be called when an ASIS exception is caught in a rule checking
   --  procedure. Repots ASIS Error Status and ASIS Diagnosis. Rule should
   --  be used as some indication of the rule which check fails (if the
   --  (default) null string is used as an actual for the Rule parameter,
   --  the produced output does not mention the rule causing this failure).
   --
   --  This procedure resets the ASIS diagnosis to an empty string and it
   --  resets ASIS Status to Not_An_Error

   -----------------------------
   -- Simple_Traverse_Element --
   -----------------------------
--  It is a partial instantiation of generic Traverse_Element procedure from
--  Asis.Iterator. It allows just a single pre- Operation instead of two pre-
--  and post- operations of Traverse_Element. It seems convenient to have
--  such simplified procedure since very offen we need not any post operation
--  at all.

--  We placed the procedure inside the private part since we intend to use it
--  just for rule checking.

--  Element             - Specifies the initial element in the traversal
--  Control             - Specifies what next to do with the traversal
--  State_Information   - Specifies other information for the traversal
--
--  Traverses the element and all its component elements, if any.
--  Component elements are all elements that can be obtained by a combination
--  of the ASIS structural queries appropriate for the given element.
--
--  If an element has one or more component elements, each is called a child
--  element.  An element's parent element is its Enclosing_Element.  Children
--  with the same parent are sibling elements.  The type Traverse_Control uses
--  the terms children and siblings to control the traverse.
--
--  For each element, the formal procedure Operation is called when first
--  visiting the element.
--
--  The order of Element traversal is in terms of the textual representation of
--  the Elements.  Elements are traversed in left-to-right and
--  top-to-bottom order.
--
--  Look for more information at Asis.Iterator.Traverse_Element.

   generic

      type State_Information is limited private;

      with procedure Operation
                       (Element : in     Asis.Element;
                        Control : in out Traverse_Control;
                        State   : in out State_Information) is <>;

   procedure Simple_Traverse_Element
     (Element : in     Asis.Element;
      Control : in out Traverse_Control;
      State   : in out State_Information);

   -------------------------
   -- Objects of QS_5_2_2 --
   -------------------------

   --  As a rule to check we use the following:
   --  "Use  named  parameter association in calls of infrequently
   --  used subprograms or entries with many formal parameters".

   --  We use some parameters that clarifies the rule meaning.
   --  They are placed into the Gch.Options for some reasons
   --  that are not essential now. They could be relocated for simplicity.
   --  Renaming of these parameters are placed below.

      Infrequently : Positive renames Gch.Options.Infrequently_Used_Subprograms;
      --  Meaning of "infrequently used"

      Many : Positive renames Gch.Options.Many_Formal_Parameters;
      --  Meaning of "many formal parameters"

      Seldom : Positive renames
               Gch.Options.Lines_Between_Infrequently_Used_Calls;
      --  not used yet; A different meaning of "infrequently used"

   --  We need also some variables that collect information during calls
   --  of the rule checking routine for different elements.
   --  They should be out of the routine to serve its different calls.
   --  That is why they are placed below.

      type Calls is array (1 .. Infrequently) of Element;
      --  To collect calls before to recognize a violation

      --  List of subprograms that have many formal parameters,
      --  have some not named parameter association and could be
      --  "infrequently used"
      type Subpr;
      type Subpr_Access is access Subpr;
      type Subpr is record
         Sub : Element;  -- a subprogram
         Bad_Calls : Calls; -- calls of the subprogram
         Amount_Calls : Positive range Calls'Range; -- amount of calls
         Bad_Subpr : Boolean;
         Next : Subpr_Access;
      end record;
      Subprs : Subpr_Access;
      Last_Subpr : Subpr_Access;

      Current_Subpr : Subpr_Access;
      --  serves as a common variable of some local procedure
      --  Stores a reference to a current subprogram record

      Waiting : Boolean := False;
      --  Is some diagnostics to analyse while traversing an unit?
   ------------------------------
   -- end of QS_5_2_2  objects --
   ------------------------------
end Gch.Rules;