/[eiffelstudio]/branches/eth/eve/Src/framework/code_analysis/ca_code_analyzer.e
ViewVC logotype

Diff of /branches/eth/eve/Src/framework/code_analysis/ca_code_analyzer.e

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 94740 by jasonw, Fri Mar 28 09:42:08 2014 UTC revision 94861 by apaolo, Wed Apr 16 16:15:49 2014 UTC
# Line 1  Line 1 
1  note  note
2          description: "THE Code Analyzer."          description: "THE Code Analyzer."
3          author: "Stefan Zurfluh"          author: "Stefan Zurfluh"
4          date: "$Date$"          date: "$Date$"
5          revision: "$Revision$"          revision: "$Revision$"
6    
7  class  class
8          CA_CODE_ANALYZER          CA_CODE_ANALYZER
9    
10  inherit  inherit
11          SHARED_EIFFEL_PROJECT          SHARED_EIFFEL_PROJECT
12    
13          CA_SHARED_NAMES          CA_SHARED_NAMES
14    
15  create  create
16          make          make
17    
18  feature {NONE} -- Initialization  feature {NONE} -- Initialization
19    
20          make          make
21                          -- Initialization for `Current'.                          -- Initialization for `Current'.
22                  do                  do
23                          create settings.make                          create settings.make
24                          create rules.make                          create rules.make
25                                  -- Adding the rules.                                  -- Adding the rules.
26                          rules.extend (create {CA_SELF_ASSIGNMENT_RULE}.make)                          rules.extend (create {CA_SELF_ASSIGNMENT_RULE}.make)
27                          rules.extend (create {CA_UNUSED_ARGUMENT_RULE}.make)                          rules.extend (create {CA_UNUSED_ARGUMENT_RULE}.make)
28                          rules.extend (create {CA_NPATH_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_NPATH_RULE}.make (settings.preference_manager))
29                          rules.extend (create {CA_EMPTY_IF_RULE}.make)                          rules.extend (create {CA_EMPTY_IF_RULE}.make)
30                          rules.extend (create {CA_FEATURE_NEVER_CALLED_RULE}.make)                          rules.extend (create {CA_FEATURE_NEVER_CALLED_RULE}.make)
31                          rules.extend (create {CA_CQ_SEPARATION_RULE}.make)                          rules.extend (create {CA_CQ_SEPARATION_RULE}.make)
32                          rules.extend (create {CA_UNNEEDED_OT_LOCAL_RULE}.make)                          rules.extend (create {CA_UNNEEDED_OT_LOCAL_RULE}.make)
33                          rules.extend (create {CA_UNNEEDED_OBJECT_TEST_RULE}.make) -- Needs type info.                          rules.extend (create {CA_UNNEEDED_OBJECT_TEST_RULE}.make) -- Needs type info.
34                          rules.extend (create {CA_NESTED_COMPLEXITY_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_NESTED_COMPLEXITY_RULE}.make (settings.preference_manager))
35                          rules.extend (create {CA_MANY_ARGUMENTS_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_MANY_ARGUMENTS_RULE}.make (settings.preference_manager))
36                          rules.extend (create {CA_CREATION_PROC_EXPORTED_RULE}.make)                          rules.extend (create {CA_CREATION_PROC_EXPORTED_RULE}.make)
37                          rules.extend (create {CA_VARIABLE_NOT_READ_RULE}.make)                          rules.extend (create {CA_VARIABLE_NOT_READ_RULE}.make)
38                          rules.extend (create {CA_SEMICOLON_ARGUMENTS_RULE}.make)                          rules.extend (create {CA_SEMICOLON_ARGUMENTS_RULE}.make)
39                          rules.extend (create {CA_VERY_LONG_ROUTINE_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_VERY_LONG_ROUTINE_RULE}.make (settings.preference_manager))
40                          rules.extend (create {CA_VERY_BIG_CLASS_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_VERY_BIG_CLASS_RULE}.make (settings.preference_manager))
41                          rules.extend (create {CA_FEATURE_SECTION_COMMENT_RULE}.make)                          rules.extend (create {CA_FEATURE_SECTION_COMMENT_RULE}.make)
42                          rules.extend (create {CA_FEATURE_NOT_COMMENTED_RULE}.make)                          rules.extend (create {CA_FEATURE_NOT_COMMENTED_RULE}.make)
43                          rules.extend (create {CA_BOOLEAN_RESULT_RULE}.make)                          rules.extend (create {CA_BOOLEAN_RESULT_RULE}.make)
44                          rules.extend (create {CA_BOOLEAN_COMPARISON_RULE}.make)                          rules.extend (create {CA_BOOLEAN_COMPARISON_RULE}.make)
45                          rules.extend (create {CA_VERY_SHORT_IDENTIFIER_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_VERY_SHORT_IDENTIFIER_RULE}.make (settings.preference_manager))
46                          rules.extend (create {CA_VERY_LONG_IDENTIFIER_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_VERY_LONG_IDENTIFIER_RULE}.make (settings.preference_manager))
47                          rules.extend (create {CA_MISSING_IS_EQUAL_RULE}.make)                          rules.extend (create {CA_MISSING_IS_EQUAL_RULE}.make)
48                          rules.extend (create {CA_SIMPLIFIABLE_BOOLEAN_RULE}.make)                          rules.extend (create {CA_SIMPLIFIABLE_BOOLEAN_RULE}.make)
49                          rules.extend (create {CA_SELF_COMPARISON_RULE}.make)                          rules.extend (create {CA_SELF_COMPARISON_RULE}.make)
50                          rules.extend (create {CA_TODO_RULE}.make)                          rules.extend (create {CA_TODO_RULE}.make)
51                          rules.extend (create {CA_WRONG_LOOP_ITERATION_RULE}.make)                          rules.extend (create {CA_WRONG_LOOP_ITERATION_RULE}.make)
52                          rules.extend (create {CA_INSPECT_INSTRUCTIONS_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_INSPECT_INSTRUCTIONS_RULE}.make (settings.preference_manager))
53                          rules.extend (create {CA_ATTRIBUTE_TO_LOCAL_RULE}.make)                          rules.extend (create {CA_ATTRIBUTE_TO_LOCAL_RULE}.make)
54                          rules.extend (create {CA_EMPTY_EFFECTIVE_ROUTINE_RULE}.make)                          rules.extend (create {CA_EMPTY_EFFECTIVE_ROUTINE_RULE}.make)
55                          rules.extend (create {CA_IF_ELSE_NOT_EQUAL_RULE}.make)                          rules.extend (create {CA_IF_ELSE_NOT_EQUAL_RULE}.make)
56                          rules.extend (create {CA_SHORT_CIRCUIT_IF_RULE}.make)                          rules.extend (create {CA_SHORT_CIRCUIT_IF_RULE}.make)
57                          rules.extend (create {CA_ITERABLE_LOOP_RULE}.make) -- Needs type info.                          rules.extend (create {CA_ITERABLE_LOOP_RULE}.make) -- Needs type info.
58                          rules.extend (create {CA_COUNT_EQUALS_ZERO_RULE}.make) -- Needs type info.                          rules.extend (create {CA_COUNT_EQUALS_ZERO_RULE}.make) -- Needs type info.
59                          rules.extend (create {CA_DEEPLY_NESTED_IF_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_DEEPLY_NESTED_IF_RULE}.make (settings.preference_manager))
60                          rules.extend (create {CA_UNNEEDED_HELPER_VARIABLE_RULE}.make (settings.preference_manager))                          rules.extend (create {CA_UNNEEDED_HELPER_VARIABLE_RULE}.make (settings.preference_manager))
61                          rules.extend (create {CA_UNNEEDED_PARENTHESES_RULE}.make)                          rules.extend (create {CA_UNNEEDED_PARENTHESES_RULE}.make)
62                            rules.extend (create {CA_CLASS_NAMING_CONVENTION_RULE}.make)
63                          settings.initialize_rule_settings (rules)                          rules.extend (create {CA_FEATURE_NAMING_CONVENTION_RULE}.make)
64                            rules.extend (create {CA_VARIABLE_NAMING_CONVENTION_RULE}.make)
65                          create classes_to_analyze.make                          rules.extend (create {CA_ARGUMENT_NAMING_CONVENTION_RULE}.make)
66                          create rule_violations.make (100)                          rules.extend (create {CA_UNNECESSARY_SIGN_OPERAND}.make)
67                          create completed_actions  
68                          create output_actions                          settings.initialize_rule_settings (rules)
69    
70                          create ignoredby.make (25)                          create classes_to_analyze.make
71                          create library_class.make (25)                          create rule_violations.make (100)
72                          create nonlibrary_class.make (25)                          create completed_actions
73                  end                          create output_actions
74    
75  feature -- Analysis interface                          create ignoredby.make (25)
76                            create library_class.make (25)
77          add_completed_action (a_action: attached PROCEDURE [ANY, TUPLE [ITERABLE [TUPLE [detachable EXCEPTION, CLASS_C]]]])                          create nonlibrary_class.make (25)
78                          -- Adds `a_action' to the list of procedures that will be                  end
79                          -- called when analysis has completed.  
80                  do  feature -- Analysis interface
81                          completed_actions.extend (a_action)  
82                  end          add_completed_action (a_action: attached PROCEDURE [ANY, TUPLE [ITERABLE [TUPLE [detachable EXCEPTION, CLASS_C]]]])
83                            -- Adds `a_action' to the list of procedures that will be
84          add_output_action (a_action: attached PROCEDURE [ANY, TUPLE [READABLE_STRING_GENERAL]])                          -- called when analysis has completed.
85                          -- Adds `a_action' to the procedures that are called for outputting status. The final results                  do
86                          -- (rule violations) are not given to these procedures.                          completed_actions.extend (a_action)
87                  do                  end
88                          output_actions.extend (a_action)  
89                  end          add_output_action (a_action: attached PROCEDURE [ANY, TUPLE [READABLE_STRING_GENERAL]])
90                            -- Adds `a_action' to the procedures that are called for outputting status. The final results
91          analyze                          -- (rule violations) are not given to these procedures.
92                          -- Analyze all the classes that have been added.                  do
93                  require                          output_actions.extend (a_action)
94                          not is_running                  end
95                  local  
96                          l_rules_checker: CA_ALL_RULES_CHECKER          analyze
97                          l_task: CA_RULE_CHECKING_TASK                          -- Analyze all the classes that have been added.
98                          l_rules_to_check: LINKED_LIST [CA_RULE]                  require
99                  do                          not is_running
100                          is_running := True                  local
101                            l_rules_checker: CA_ALL_RULES_CHECKER
102                          create l_rules_checker.make                          l_task: CA_RULE_CHECKING_TASK
103                          create l_rules_to_check.make                          l_rules_to_check: LINKED_LIST [CA_RULE]
104                          across rules as l_rules loop                  do
105                                  l_rules.item.clear_violations                          is_running := True
106                                  if is_rule_checkable (l_rules.item) then  
107                                          l_rules_to_check.extend (l_rules.item)                          create l_rules_checker.make
108                                                  -- Here we only prepare standard rules. The rule checking task will iterate again                          create l_rules_to_check.make
109                                                  -- through the rules and run the analysis on the enabled rules.                          across rules as l_rules loop
110                                          if attached {CA_STANDARD_RULE} l_rules.item as l_std_rule then                                  l_rules.item.clear_violations
111                                                  l_std_rule.prepare_checking (l_rules_checker)                                  if is_rule_checkable (l_rules.item) then
112                                          end                                          l_rules_to_check.extend (l_rules.item)
113                                  end                                                  -- Here we only prepare standard rules. The rule checking task will iterate again
114                          end                                                  -- through the rules and run the analysis on the enabled rules.
115                                            if attached {CA_STANDARD_RULE} l_rules.item as l_std_rule then
116                          create l_task.make (l_rules_checker, l_rules_to_check, classes_to_analyze, agent analysis_completed)                                                  l_std_rule.prepare_checking (l_rules_checker)
117                          l_task.set_output_actions (output_actions)                                          end
118                          rota.run_task (l_task)                                  end
119                  end                          end
120    
121          is_rule_checkable (a_rule: attached CA_RULE): BOOLEAN                          create l_task.make (l_rules_checker, l_rules_to_check, classes_to_analyze, agent analysis_completed)
122                          -- Will `a_rule' be checked based on the current preferences and based on the current                          l_task.set_output_actions (output_actions)
123                          -- checking scope?                          rota.run_task (l_task)
124                  do                  end
125                          Result := a_rule.is_enabled.value  
126                                                  and then (system_wide_check or else (not a_rule.is_system_wide))          is_rule_checkable (a_rule: attached CA_RULE): BOOLEAN
127                                                  and then is_severity_enabled (a_rule.severity)                          -- Will `a_rule' be checked based on the current preferences and based on the current
128                  end                          -- checking scope?
129                    do
130          clear_classes_to_analyze                          Result := a_rule.is_enabled.value
131                          -- Removes all classes that have been added to the list of classes                                                  and then (system_wide_check or else (not a_rule.is_system_wide))
132                          -- to analyze.                                                  and then is_severity_enabled (a_rule.severity)
133                  do                  end
134                          classes_to_analyze.wipe_out  
135                  end          clear_classes_to_analyze
136                            -- Removes all classes that have been added to the list of classes
137          add_whole_system                          -- to analyze.
138                          -- Adds all the classes that are part of the current system. Classes of referenced libraries                  do
139                          -- will not be added.                          classes_to_analyze.wipe_out
140                  local                  end
141                          l_cluster: CLUSTER_I  
142                  do          add_whole_system
143                          across                          -- Adds all the classes that are part of the current system. Classes of referenced libraries
144                                  eiffel_universe.groups as l_groups                          -- will not be added.
145                          loop                  local
146                                  l_cluster ?= l_groups.item                          l_cluster: CLUSTER_I
147                                          -- Only load top-level clusters, as the others will be loaded recursively afterwards.                  do
148                                  if l_cluster /= Void and then l_cluster.parent_cluster = Void then                          across
149                                          add_cluster (l_cluster)                                  eiffel_universe.groups as l_groups
150                                  end                          loop
151                          end                                  l_cluster ?= l_groups.item
152                                            -- Only load top-level clusters, as the others will be loaded recursively afterwards.
153                          system_wide_check := True                                  if l_cluster /= Void and then l_cluster.parent_cluster = Void then
154                  end                                          add_cluster (l_cluster)
155                                    end
156          add_cluster (a_cluster: attached CLUSTER_I)                          end
157                          -- Add all classes of cluster `a_cluster'.  
158                  do                          system_wide_check := True
159                          system_wide_check := False                  end
160    
161                          if a_cluster.classes /= Void then          add_cluster (a_cluster: attached CLUSTER_I)
162                                  across a_cluster.classes as ic loop                          -- Add all classes of cluster `a_cluster'.
163                                          add_class (ic.item)                  do
164                                  end                          system_wide_check := False
165                          end  
166                            if a_cluster.classes /= Void then
167                          if a_cluster.sub_clusters /= Void then                                  across a_cluster.classes as ic loop
168                                  across a_cluster.sub_clusters as ic loop                                          add_class (ic.item)
169                                          add_cluster (ic.item)                                  end
170                                  end                          end
171                          end  
172                  end                          if a_cluster.sub_clusters /= Void then
173                                    across a_cluster.sub_clusters as ic loop
174          add_group (a_group: attached CONF_GROUP)                                          add_cluster (ic.item)
175                          -- Add all classes of the configuration group `a_group'.                                  end
176                  require                          end
177                          a_group_not_void: a_group /= Void                  end
178                  do  
179                          if a_group.classes /= Void then          add_group (a_group: attached CONF_GROUP)
180                                  across a_group.classes as ic loop                          -- Add all classes of the configuration group `a_group'.
181                                          add_class (ic.item)                  require
182                                  end                          a_group_not_void: a_group /= Void
183                          end                  do
184                  end                          if a_group.classes /= Void then
185                                    across a_group.classes as ic loop
186          add_classes (a_classes: attached ITERABLE [attached CONF_CLASS])                                          add_class (ic.item)
187                          -- Add the classes `a_classes'.                                  end
188                  do                          end
189                          system_wide_check := False                  end
190    
191                          across a_classes as l_classes loop          add_classes (a_classes: attached ITERABLE [attached CONF_CLASS])
192                                  add_class (l_classes.item)                          -- Add the classes `a_classes'.
193                          end                  do
194                  end                          system_wide_check := False
195    
196          add_class (a_class: attached CONF_CLASS)                          across a_classes as l_classes loop
197                          -- Adds class `a_class'.                                  add_class (l_classes.item)
198                  local                          end
199                          l_class_c: CLASS_C                  end
200                  do  
201                          system_wide_check := False          add_class (a_class: attached CONF_CLASS)
202                            -- Adds class `a_class'.
203                          if attached {EIFFEL_CLASS_I} a_class as l_eiffel_class                  local
204                                  and then attached l_eiffel_class.compiled_class as l_compiled                          l_class_c: CLASS_C
205                          then                  do
206                                  classes_to_analyze.extend (l_compiled)                          system_wide_check := False
207    
208                                  extract_indexes (l_compiled)                          if attached {EIFFEL_CLASS_I} a_class as l_eiffel_class
209                          else                                  and then attached l_eiffel_class.compiled_class as l_compiled
210                                  output_actions.call ([ca_messages.class_skipped (a_class.name)])                          then
211                          end                                  classes_to_analyze.extend (l_compiled)
212                  end  
213                                    extract_indexes (l_compiled)
214  feature -- Properties                          else
215                                    output_actions.call ([ca_messages.class_skipped (a_class.name)])
216          is_running: BOOLEAN                          end
217                          -- Is code analysis running?                  end
218    
219          rules: LINKED_LIST [CA_RULE]  feature -- Properties
220                          -- List of rules that will be used for analysis.  
221            is_running: BOOLEAN
222          rule_violations: detachable HASH_TABLE [SORTED_TWO_WAY_LIST [CA_RULE_VIOLATION], CLASS_C]                          -- Is code analysis running?
223                          -- All found violations from the last analysis.  
224            rules: LINKED_LIST [CA_RULE]
225          settings: CA_SETTINGS                          -- List of rules that will be used for analysis.
226                          -- The settings manager for Code Analysis.  
227            rule_violations: detachable HASH_TABLE [SORTED_TWO_WAY_LIST [CA_RULE_VIOLATION], CLASS_C]
228          preferences: PREFERENCES                          -- All found violations from the last analysis.
229                          -- Code Analysis preferences.  
230                  do Result := settings.preferences end          settings: CA_SETTINGS
231                            -- The settings manager for Code Analysis.
232          class_list: ITERABLE [CLASS_C]  
233                          -- List of classes that have been added.          preferences: PREFERENCES
234                  do Result := classes_to_analyze end                          -- Code Analysis preferences.
235                    do Result := settings.preferences end
236  feature {NONE} -- Implementation  
237            class_list: ITERABLE [CLASS_C]
238          csv_file_name: STRING = "last_analysis_result.csv"                          -- List of classes that have been added.
239                    do Result := classes_to_analyze end
240          csv_header: STRING = "Severity;Class;Location;Title;Description;Rule ID;Severity Score"  
241    feature {NONE} -- Implementation
242          analysis_completed (a_exceptions: detachable ITERABLE [TUPLE [detachable EXCEPTION, CLASS_C]])  
243                          -- Will be called when the analysis task has finished. `a_exceptions'          csv_file_name: STRING = "last_analysis_result.csv"
244                          -- contains a list of exception that occurred during analysis.  
245                  local          csv_header: STRING = "Severity;Class;Location;Title;Description;Rule ID;Severity Score"
246                          l_csv_writer: CA_CSV_WRITER  
247                  do          analysis_completed (a_exceptions: detachable ITERABLE [TUPLE [detachable EXCEPTION, CLASS_C]])
248                          create l_csv_writer.make (csv_file_name, csv_header)                          -- Will be called when the analysis task has finished. `a_exceptions'
249                            -- contains a list of exception that occurred during analysis.
250                          across rules as l_rules loop                  local
251                                  across l_rules.item.violations as l_v loop                          l_csv_writer: CA_CSV_WRITER
252                                                  -- Check the ignore list.                  do
253                                          if is_violation_valid (l_v.item) then                          create l_csv_writer.make (csv_file_name, csv_header)
254                                                          -- Make sure a list for this class exists in the hash table:  
255                                                  rule_violations.put (create {SORTED_TWO_WAY_LIST [CA_RULE_VIOLATION]}.make, l_v.item.affected_class)                          across rules as l_rules loop
256                                                          -- Add the violation.                                  across l_rules.item.violations as l_v loop
257                                                  rule_violations.at (l_v.item.affected_class).extend (l_v.item)                                                  -- Check the ignore list.
258                                                          -- Log it.                                          if is_violation_valid (l_v.item) then
259                                                  l_csv_writer.add_line (l_v.item.csv_line)                                                          -- Make sure a list for this class exists in the hash table:
260                                          end                                                  rule_violations.put (create {SORTED_TWO_WAY_LIST [CA_RULE_VIOLATION]}.make, l_v.item.affected_class)
261                                  end                                                          -- Add the violation.
262                          end                                                  rule_violations.at (l_v.item.affected_class).extend (l_v.item)
263                                                            -- Log it.
264                          l_csv_writer.close_file                                                  l_csv_writer.add_line (l_v.item.csv_line)
265                                            end
266                          clear_classes_to_analyze                                  end
267                            end
268                          is_running := False  
269                          completed_actions.call ([a_exceptions])                          l_csv_writer.close_file
270                          completed_actions.wipe_out  
271                  end                          clear_classes_to_analyze
272    
273          is_violation_valid (a_viol: attached CA_RULE_VIOLATION): BOOLEAN                          is_running := False
274                          -- Is the violation `a_viol' valid under the current settings                          completed_actions.call ([a_exceptions])
275                          -- such as the rule ignore list of a class, or the library or                          completed_actions.wipe_out
276                          -- non-library status of a class?                  end
277                  local  
278                          l_affected_class: CLASS_C          is_violation_valid (a_viol: attached CA_RULE_VIOLATION): BOOLEAN
279                          l_rule: CA_RULE                          -- Is the violation `a_viol' valid under the current settings
280                  do                          -- such as the rule ignore list of a class, or the library or
281                          l_affected_class := a_viol.affected_class                          -- non-library status of a class?
282                          l_rule := a_viol.rule                  local
283                            l_affected_class: CLASS_C
284                          Result := True                          l_rule: CA_RULE
285                    do
286                          if ignoredby.has (l_affected_class)                          l_affected_class := a_viol.affected_class
287                                                          and then (ignoredby.at (l_affected_class)).has (l_rule.id) then                          l_rule := a_viol.rule
288                                  Result := False  
289                          end                          Result := True
290    
291                          if (not l_rule.checks_library_classes) and then library_class.at (l_affected_class) then                          if ignoredby.has (l_affected_class)
292                                  Result := False                                                          and then (ignoredby.at (l_affected_class)).has (l_rule.id) then
293                          end                                  Result := False
294                            end
295                          if (not l_rule.checks_nonlibrary_classes) and then nonlibrary_class.at (l_affected_class) then  
296                                  Result := False                          if (not l_rule.checks_library_classes) and then library_class.at (l_affected_class) then
297                          end                                  Result := False
298                  end                          end
299    
300          classes_to_analyze: LINKED_SET [CLASS_C]                          if (not l_rule.checks_nonlibrary_classes) and then nonlibrary_class.at (l_affected_class) then
301                          -- List of classes that shall be analyzed.                                  Result := False
302                            end
303          system_wide_check: BOOLEAN                  end
304                          -- Shall the whole system be analyzed?  
305            classes_to_analyze: LINKED_SET [CLASS_C]
306          completed_actions: ACTION_SEQUENCE [TUPLE [ITERABLE [TUPLE [detachable EXCEPTION, CLASS_C]]]]                          -- List of classes that shall be analyzed.
307                          -- List of procedures to call when analysis has completed.  
308            system_wide_check: BOOLEAN
309          frozen rota: detachable ROTA_S                          -- Shall the whole system be analyzed?
310                          -- Accesses the rota service.  
311                  local          completed_actions: ACTION_SEQUENCE [TUPLE [ITERABLE [TUPLE [detachable EXCEPTION, CLASS_C]]]]
312                          l_service_consumer: SERVICE_CONSUMER [ROTA_S]                          -- List of procedures to call when analysis has completed.
313                  do  
314                          create l_service_consumer          frozen rota: detachable ROTA_S
315                          if attached l_service_consumer.service as l_service and then l_service.is_interface_usable then                          -- Accesses the rota service.
316                                  Result := l_service                  local
317                          end                          l_service_consumer: SERVICE_CONSUMER [ROTA_S]
318                  end                  do
319                            create l_service_consumer
320          is_severity_enabled (a_severity: attached CA_RULE_SEVERITY): BOOLEAN                          if attached l_service_consumer.service as l_service and then l_service.is_interface_usable then
321                  do                                  Result := l_service
322                          Result := (attached {CA_HINT} a_severity and settings.are_hints_enabled.value)                          end
323                                  or else (attached {CA_SUGGESTION} a_severity and settings.are_suggestions_enabled.value)                  end
324                                  or else (attached {CA_WARNING} a_severity and settings.are_warnings_enabled.value)  
325                                  or else (attached {CA_ERROR} a_severity and settings.are_errors_enabled.value)          is_severity_enabled (a_severity: attached CA_RULE_SEVERITY): BOOLEAN
326                  end                  do
327                            Result := (attached {CA_HINT} a_severity and settings.are_hints_enabled.value)
328          output_actions: ACTION_SEQUENCE [TUPLE [READABLE_STRING_GENERAL]]                                  or else (attached {CA_SUGGESTION} a_severity and settings.are_suggestions_enabled.value)
329                          -- Will be called whenever there is a message to output.                                  or else (attached {CA_WARNING} a_severity and settings.are_warnings_enabled.value)
330                                    or else (attached {CA_ERROR} a_severity and settings.are_errors_enabled.value)
331  feature {NONE} -- Class-wide Options (From Indexing Clauses)                  end
332    
333          extract_indexes (a_class: attached CLASS_C)          output_actions: ACTION_SEQUENCE [TUPLE [READABLE_STRING_GENERAL]]
334                          -- Extracts options from the indexing clause of class `a_class'.                          -- Will be called whenever there is a message to output.
335                  local  
336                          l_ast: CLASS_AS  feature {NONE} -- Class-wide Options (From Indexing Clauses)
337                          l_ignoredby: LINKED_LIST [STRING_32]  
338                  do          extract_indexes (a_class: attached CLASS_C)
339                          create l_ignoredby.make                          -- Extracts options from the indexing clause of class `a_class'.
340                          l_ignoredby.compare_objects -- We want to compare the actual strings.                  local
341                                  -- Reset the class flags.                          l_ast: CLASS_AS
342                          library_class.force (False, a_class)                          l_ignoredby: LINKED_LIST [STRING_32]
343                          nonlibrary_class.force (False, a_class)                  do
344                          l_ast := a_class.ast                          create l_ignoredby.make
345                            l_ignoredby.compare_objects -- We want to compare the actual strings.
346                          if attached l_ast.internal_top_indexes as l_top then                                  -- Reset the class flags.
347                                  search_indexing_tags (l_top, a_class, l_ignoredby)                          library_class.force (False, a_class)
348                          end                          nonlibrary_class.force (False, a_class)
349                          if attached l_ast.internal_bottom_indexes as l_bottom then                          l_ast := a_class.ast
350                                  search_indexing_tags (l_bottom, a_class, l_ignoredby)  
351                          end                          if attached l_ast.internal_top_indexes as l_top then
352                                    search_indexing_tags (l_top, a_class, l_ignoredby)
353                          ignoredby.force (l_ignoredby, a_class)                          end
354                  end                          if attached l_ast.internal_bottom_indexes as l_bottom then
355                                    search_indexing_tags (l_bottom, a_class, l_ignoredby)
356          search_indexing_tags (a_clause: attached INDEXING_CLAUSE_AS; a_class: attached CLASS_C; a_ignoredby: attached LINKED_LIST [STRING_32])                          end
357                          -- Searches `a_clause' for settings relevant to code analysis.  
358                  local                          ignoredby.force (l_ignoredby, a_class)
359                          l_item: STRING_32                  end
360                  do  
361                          across a_clause as ic loop          search_indexing_tags (a_clause: attached INDEXING_CLAUSE_AS; a_class: attached CLASS_C; a_ignoredby: attached LINKED_LIST [STRING_32])
362                                  if ic.item.tag.name_32.is_equal ("ca_ignoredby") then                          -- Searches `a_clause' for settings relevant to code analysis.
363                                                  -- Class wants to ignore certain rules.                  local
364                                          across ic.item.index_list as l_list loop                          l_item: STRING_32
365                                                  l_item := l_list.item.string_value_32                  do
366                                                  l_item.prune_all ('%"')                          across a_clause as ic loop
367                                                  a_ignoredby.extend (l_item)                                  if ic.item.tag.name_32.is_equal ("ca_ignoredby") then
368                                          end                                                  -- Class wants to ignore certain rules.
369                                  elseif ic.item.tag.name_32.is_equal ("ca_library") then                                          across ic.item.index_list as l_list loop
370                                                  -- Class has information on whether it is a library class.                                                  l_item := l_list.item.string_value_32
371                                          if not ic.item.index_list.is_empty then                                                  l_item.prune_all ('%"')
372                                                  l_item := ic.item.index_list.first.string_value_32                                                  a_ignoredby.extend (l_item)
373                                                  l_item.to_lower                                          end
374                                                  l_item.prune_all ('%"')                                  elseif ic.item.tag.name_32.is_equal ("ca_library") then
375                                                  if l_item.is_equal ("true") then                                                  -- Class has information on whether it is a library class.
376                                                          library_class.force (True, a_class)                                          if not ic.item.index_list.is_empty then
377                                                  elseif l_item.is_equal ("false") then                                                  l_item := ic.item.index_list.first.string_value_32
378                                                          nonlibrary_class.force (True, a_class)                                                  l_item.to_lower
379                                                  end                                                  l_item.prune_all ('%"')
380                                          end                                                  if l_item.is_equal ("true") then
381                                  end                                                          library_class.force (True, a_class)
382                          end                                                  elseif l_item.is_equal ("false") then
383                  end                                                          nonlibrary_class.force (True, a_class)
384                                                    end
385          ignoredby: HASH_TABLE [LINKED_LIST [STRING_32], CLASS_C]                                          end
386                          -- Maps classes to lists of rules (rule IDs) the class wants to be ignored by.                                  end
387                            end
388          library_class, nonlibrary_class: HASH_TABLE [BOOLEAN, CLASS_C]                  end
389                          -- Stores classes that are marked as library or non-library classes.  
390            ignoredby: HASH_TABLE [LINKED_LIST [STRING_32], CLASS_C]
391  invariant                          -- Maps classes to lists of rules (rule IDs) the class wants to be ignored by.
392          --      law_of_non_contradiction: one class must not be both a library_class and a nonlibrary_class  
393            library_class, nonlibrary_class: HASH_TABLE [BOOLEAN, CLASS_C]
394  end                          -- Stores classes that are marked as library or non-library classes.
395    
396    invariant
397            --      law_of_non_contradiction: one class must not be both a library_class and a nonlibrary_class
398    
399    end

Legend:
Removed from v.94740  
changed lines
  Added in v.94861

  ViewVC Help
Powered by ViewVC 1.1.23