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

Contents of /branches/eth/eve/Src/framework/code_analysis/rules/ca_unneeded_helper_variable_rule.e

Parent Directory Parent Directory | Revision Log Revision Log


Revision 93943 - (show annotations)
Thu Jan 9 13:38:38 2014 UTC (6 years, 1 month ago) by zurfluhs
File size: 9464 byte(s)
Code Analysis: 'unneeded helper' rule
1 note
2 description: "Summary description for {CA_UNNEEDED_HELPER_VARIABLE_RULE}."
3 author: "Stefan Zurfluh"
4 date: "$Date$"
5 revision: "$Revision$"
6
7 class
8 CA_UNNEEDED_HELPER_VARIABLE_RULE
9
10 inherit
11 CA_RD_ANALYSIS_RULE
12 redefine
13 check_feature,
14 id,
15 process_instruction
16 end
17
18 AST_ITERATOR
19 redefine
20 process_assign_as,
21 process_access_id_as,
22 process_assigner_call_as,
23 process_bang_creation_as,
24 process_create_creation_as,
25 process_instr_call_as
26 end
27
28 create
29 make
30
31 feature {NONE} -- Initialization
32
33 make (a_pref_manager: PREFERENCE_MANAGER)
34 -- Initialization for `Current'.
35 do
36 is_enabled_by_default := True
37 create {CA_SUGGESTION} severity
38 create violations.make
39 initialize_preferences (a_pref_manager)
40 end
41
42 initialize_preferences (a_pref_manager: PREFERENCE_MANAGER)
43 local
44 l_factory: BASIC_PREFERENCE_FACTORY
45 do
46 create l_factory
47 max_line_length := l_factory.new_integer_preference_value (a_pref_manager,
48 preference_namespace + ca_names.max_line_length_option,
49 default_max_line_length)
50 max_line_length.set_default_value (default_max_line_length.out)
51 max_line_length.set_validation_agent (agent is_integer_string_within_bounds (?, 30, 1000))
52 end
53
54 feature {NONE} -- From {CA_CFG_RULE}
55
56 check_feature (a_class: CLASS_C; a_feature: E_FEATURE)
57 -- Checks `a_feature' from `a_class' for rule violations.
58 local
59 l_cfg_block: CA_CFG_INSTRUCTION
60 l_rds: HASH_TABLE [LINKED_SET [INTEGER], INTEGER]
61 l_id: ID_AS
62 l_n_usages, l_max: INTEGER
63 l_viol: CA_RULE_VIOLATION
64 do
65 -- Perform an iteration over the AST in order to gather
66 -- a list of variables that are "suspected" for rule
67 -- violations.
68 processing_cfg := False
69
70 -- Initializations
71 create assignments.make (0)
72 create assigned_expression_length.make (0)
73 create usages.make (0)
74 create usage_line_length.make (0)
75 create usage_location.make (0)
76 create usage_in_cfg.make (0)
77 create suspected_variables.make
78
79 process_feature_as (a_feature.ast)
80
81 processing_cfg := True
82 Precursor (a_class, a_feature)
83
84 across assignments as l_a loop
85 if l_a.item = 1 then
86 l_id := l_a.key
87 l_n_usages := usages [l_id]
88
89 if l_n_usages = 2 then
90 -- 2, since the assignment is included in the count.
91 l_max := max_line_length.value
92 -- Check if the possible new line is not too long:
93 if usage_line_length [l_id] - l_id.name_8.count + assigned_expression_length [l_id] <= l_max then
94 -- Now check the CFG for the fact that the variable must have been assigned
95 -- by the single assignment (and could not have kept the initial value, e. g.)
96 if usage_in_cfg.has_key (l_id) then
97 l_cfg_block := usage_in_cfg [l_id]
98 l_rds := rd_entry [l_cfg_block.label]
99 if l_rds.has_key (l_id.name_id) then
100 if l_rds [l_id.name_id].count = 1 then
101 -- Only one possible source of assignment.
102 create l_viol.make_with_rule (Current)
103 l_viol.set_location (l_cfg_block.instruction.start_location)
104 l_viol.long_description_info.extend (l_id.name_32)
105 violations.extend (l_viol)
106 end
107 end
108 end
109 end
110 end
111 end
112 end
113 end
114
115 feature {NONE} -- Rule checking
116
117 process_instruction (a_instr: CA_CFG_INSTRUCTION)
118 do
119 Precursor (a_instr)
120
121 -- Set it so that the AST visitors may set it.
122 current_cfg_block := a_instr
123
124 -- Find read variables.
125 a_instr.instruction.process (Current)
126 end
127
128 processing_cfg: BOOLEAN
129
130 current_cfg_block: detachable CA_CFG_INSTRUCTION
131
132 suspected_variables: LINKED_LIST [INTEGER]
133 -- List of IDs of all variables that are read only once.
134
135 assignments: HASH_TABLE [INTEGER, ID_AS]
136 -- Set of variable IDs of local variables that are assigned a value only
137 -- once in the feature.
138
139 assigned_expression_length: HASH_TABLE [INTEGER, ID_AS]
140 -- For each assignee the # of characters of the right-hand-side is stored.
141 -- It suffices to store the last assignment since variables that are
142 -- assigned more than once are not considered anyway.
143
144 usages: HASH_TABLE [INTEGER, ID_AS]
145 -- How many times is the local variable with a certain ID used in the feature?
146 -- Note that the assignment itself also counts.
147
148 current_line_length: INTEGER
149 -- # of character of the currently visited instruction.
150
151 usage_line_length: HASH_TABLE [INTEGER, ID_AS]
152 -- For each usage the # of characters of this line is stored.
153 -- It suffices to store the last usage since variables that are
154 -- used more than once are not considered anyway.
155
156 usage_location: HASH_TABLE [LOCATION_AS, ID_AS]
157 -- Location where variable with a certain ID has been used last.
158
159 usage_in_cfg: HASH_TABLE [CA_CFG_INSTRUCTION, ID_AS]
160
161 process_assigner_call_as (a_assigner_call: ASSIGNER_CALL_AS)
162 do
163 current_line_length := a_assigner_call.end_position - a_assigner_call.start_position + 1
164
165 Precursor (a_assigner_call)
166 end
167
168 process_bang_creation_as (a_bang_creation: BANG_CREATION_AS)
169 do
170 current_line_length := a_bang_creation.end_position - a_bang_creation.start_position + 1
171
172 Precursor (a_bang_creation)
173 end
174
175 process_create_creation_as (a_create_creation: CREATE_CREATION_AS)
176 do
177 current_line_length := a_create_creation.end_position - a_create_creation.start_position + 1
178
179 Precursor (a_create_creation)
180 end
181
182 process_instr_call_as (a_instr_call: INSTR_CALL_AS)
183 do
184 current_line_length := a_instr_call.end_position - a_instr_call.start_position + 1
185
186 Precursor (a_instr_call)
187 end
188
189 -- process_feature_as (a_feature: FEATURE_AS)
190 -- local
191 -- l_id: ID_AS
192 -- l_n_usages, l_max: INTEGER
193 -- do
194 -- create assignments.make (0)
195 -- create assigned_expression_length.make (0)
196 -- create usages.make (0)
197 -- create usage_line_length.make (0)
198 -- create usage_location.make (0)
199 -- create suspected_variables.make
200
201 -- Precursor (a_feature)
202
203 -- across assignments as l_a loop
204 -- if l_a.item = 1 then
205 -- l_id := l_a.key
206 -- l_n_usages := usages [l_id]
207
208 -- if l_n_usages = 2 then
209 -- -- 2, since the assignment is included in the count.
210 -- l_max := max_line_length.value
211 -- -- Check if the possible new line is not too long:
212 -- if usage_line_length [l_id] - l_id.name_8.count + assigned_expression_length [l_id] <= l_max then
213 -- suspected_variables.extend (l_id.name_id)
214 -- end
215 -- end
216 -- end
217 -- end
218 -- end
219
220 process_assign_as (a_assign: ASSIGN_AS)
221 local
222 l_id: ID_AS
223 l_old_count: INTEGER
224 do
225 if not processing_cfg then
226 -- In the right-hand-side of this assignment a critical variable might
227 -- be used. Thus here, too, we are storing the line length.
228 current_line_length := a_assign.end_position - a_assign.start_position + 1
229
230 if attached {ACCESS_FEAT_AS} a_assign.target as l_assignee and then l_assignee.is_local then
231 -- Only look at locals.
232 l_id := l_assignee.feature_name
233
234 if not assignments.has (l_id) then
235 assignments.put (1, l_id)
236 assigned_expression_length.force (a_assign.source.end_position - a_assign.source.start_position + 1, l_id)
237 else
238 l_old_count := assignments [l_id]
239 assignments.force (l_old_count + 1, l_id)
240 end
241 end
242 end
243
244 Precursor (a_assign)
245 end
246
247 process_access_id_as (a_access_id: ACCESS_ID_AS)
248 local
249 l_id: ID_AS
250 l_old_count: INTEGER
251 do
252 if a_access_id.is_local then
253 -- Only look at locals.
254
255 l_id := a_access_id.feature_name
256
257 if processing_cfg then
258 -- Map the usage to the current CFG block.
259 usage_in_cfg.force (current_cfg_block, l_id)
260 else
261
262 if not usages.has (l_id) then
263 usages.put (1, l_id)
264 else
265 l_old_count := usages [l_id]
266 usages.force (l_old_count + 1, l_id)
267 end
268
269 -- Store length of line where usage appears.
270 usage_line_length.force (current_line_length, l_id)
271 -- And store location for the use by a possible rule violation.
272 usage_location.force (a_access_id.start_location, l_id)
273 end
274 end
275
276 Precursor (a_access_id)
277 end
278
279 -- check_suspected_variables
280 -- local
281 -- l_viol: CA_RULE_VIOLATION
282 -- l_rd: HASH_TABLE [LINKED_SET [INTEGER], INTEGER]
283 -- do
284 -- across suspected_variables as l_suspects loop
285 -- across rd_entry as l_rds loop
286 -- from
287 -- l_rd := l_rds.item
288 -- l_rd.start
289 -- until
290 -- l_rd.after
291 -- loop
292 -- if l_rd.key_for_iteration = l_suspects.item then
293 -- -- The suspected variable
294 -- end
295 -- l_rd.forth
296 -- end
297 -- end
298 -- end
299 -- end
300
301 feature {NONE} -- Preferences
302
303 default_max_line_length: INTEGER = 80
304
305 max_line_length: INTEGER_PREFERENCE
306
307 feature -- Properties
308
309 title: STRING_32
310 -- Rule title.
311 do
312 Result := ca_names.unneeded_helper_variable_title
313 end
314
315 description: STRING_32
316 -- Rule description.
317 do
318 Result := ca_names.unneeded_helper_variable_description
319 end
320
321 id: STRING_32 = "CA085T"
322 -- "T" stands for 'under test'.
323
324 is_system_wide: BOOLEAN = False
325
326 format_violation_description (a_violation: CA_RULE_VIOLATION; a_formatter: TEXT_FORMATTER)
327 -- Generates a formatted rule violation description for `a_formatter' based on `a_violation'.
328 do
329 a_formatter.add (ca_messages.unneeded_helper_variable_violation_1)
330 if attached {STRING_32} a_violation.long_description_info.first as l_name then
331 a_formatter.add_local (l_name)
332 end
333 a_formatter.add (ca_messages.unneeded_helper_variable_violation_2)
334 end
335
336 end

Properties

Name Value
svn:eol-style native
svn:keywords Author Date ID Revision

  ViewVC Help
Powered by ViewVC 1.1.23