archruby 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -0
  3. data/README.md +1 -1
  4. data/Rakefile +46 -0
  5. data/TODO.rtf +20 -0
  6. data/architecture.yml +51 -0
  7. data/archruby.gemspec +3 -0
  8. data/bin/archruby +1 -0
  9. data/lib/archruby.rb +14 -2
  10. data/lib/archruby/architecture/architecture.rb +6 -6
  11. data/lib/archruby/architecture/config_definition.rb +13 -13
  12. data/lib/archruby/architecture/constraint_break.rb +1 -1
  13. data/lib/archruby/architecture/dependency.rb +3 -1
  14. data/lib/archruby/architecture/file_content.rb +2 -2
  15. data/lib/archruby/architecture/module_definition.rb +33 -20
  16. data/lib/archruby/architecture/parser.rb +25 -11
  17. data/lib/archruby/architecture/type_inference_checker.rb +29 -13
  18. data/lib/archruby/presenters/dsm.rb +163 -0
  19. data/lib/archruby/presenters/dsm/cell_dsm.rb +17 -0
  20. data/lib/archruby/presenters/dsm/dsm_css.css +77 -0
  21. data/lib/archruby/presenters/graph.rb +12 -9
  22. data/lib/archruby/ruby/parser.rb +131 -125
  23. data/lib/archruby/ruby/type_inference/dependency_organizer.rb +53 -0
  24. data/lib/archruby/ruby/type_inference/ruby/class_dependency.rb +22 -0
  25. data/lib/archruby/ruby/type_inference/ruby/internal_method_invocation.rb +20 -0
  26. data/lib/archruby/ruby/type_inference/ruby/method_definition.rb +20 -0
  27. data/lib/archruby/ruby/type_inference/ruby/parser_for_typeinference.rb +537 -0
  28. data/lib/archruby/ruby/type_inference/ruby/process_method_arguments.rb +155 -0
  29. data/lib/archruby/ruby/type_inference/ruby/process_method_body.rb +427 -0
  30. data/lib/archruby/ruby/type_inference/ruby/process_method_params.rb +276 -0
  31. data/lib/archruby/ruby/type_inference/type_inference_checker.rb +126 -0
  32. data/lib/archruby/version.rb +1 -1
  33. data/spec/architecture/file_content_spec.rb +2 -1
  34. data/spec/architecture/module_definition_spec.rb +9 -9
  35. data/spec/dummy_app/lib/teste_class.rb +6 -0
  36. data/spec/ruby/type_inference/dependency_organizer_spec.rb +20 -0
  37. data/spec/ruby/type_inference/fixtures/homebrew_bottles_class.rb +139 -0
  38. data/spec/ruby/type_inference/fixtures/homebrew_brew_teste.rb +1323 -0
  39. data/spec/ruby/type_inference/fixtures/rails_action_view_class_teste.rb +89 -0
  40. data/spec/ruby/type_inference/fixtures/rails_active_record_class.rb +99 -0
  41. data/spec/ruby/type_inference/fixtures/rails_teste_active_record.rb +55 -0
  42. data/spec/ruby/type_inference/fixtures/teste2.rb +16 -0
  43. data/spec/ruby/type_inference/fixtures/teste_class_and_args.rb +49 -0
  44. data/spec/ruby/type_inference/fixtures/teste_class_and_args2.rb +11 -0
  45. data/spec/ruby/type_inference/parser_for_typeinference_spec.rb +69 -0
  46. data/spec/ruby/type_inference/type_inference_checker_spec.rb +47 -0
  47. metadata +84 -3
@@ -6,10 +6,11 @@ module Archruby
6
6
 
7
7
  class Parser < SexpInterpreter
8
8
  attr_reader :dependencies, :classes, :classes_and_dependencies,
9
- :type_inference, :method_calls
9
+ :type_inference, :method_calls, :type_propagation_parser
10
10
 
11
- def initialize content
11
+ def initialize(content)
12
12
  super()
13
+ #a = Archruby::Presenters::Graph.new
13
14
  @content = content
14
15
  @dependencies = []
15
16
  @classes = []
@@ -18,21 +19,23 @@ module Archruby
18
19
  @module_names = []
19
20
  @complete_class_name = []
20
21
  @var_propagation = Archruby::Ruby::VarPropagation.new
22
+ @type_propagation_parser = Archruby::Ruby::TypeInference::Ruby::ParserForTypeinference.new
21
23
  @type_inference = []
22
24
  @method_calls = []
23
25
  parse
24
26
  end
25
27
 
26
28
  def parse
27
- process ruby_parser.parse @content
29
+ process ruby_parser.parse(@content)
30
+ @type_propagation_parser.parse(@content)
28
31
  end
29
32
 
30
- def process_block exp
33
+ def process_block(exp)
31
34
  _, *args = exp
32
- args.map! {|sub_tree| process sub_tree}
35
+ args.map! {|sub_tree| process(sub_tree)}
33
36
  end
34
37
 
35
- def process_class exp
38
+ def process_class(exp)
36
39
  _, class_name, *args = exp
37
40
  if class_name.class == Symbol
38
41
  if !@module_names.empty?
@@ -42,17 +45,17 @@ module Archruby
42
45
  end
43
46
  else
44
47
  # cai aqui quando a definicao é algo do tipo: class Teste::De end
45
- get_complete_class_name class_name
48
+ get_complete_class_name(class_name)
46
49
  @classes << @complete_class_name.join("::")
47
50
  @complete_class_name = []
48
51
  end
49
- args.map! {|sub_tree| process sub_tree}
52
+ args.map! {|sub_tree| process(sub_tree)}
50
53
  end
51
54
 
52
- def get_complete_class_name exp
55
+ def get_complete_class_name(exp)
53
56
  if exp[0] == :const
54
57
  _, const_name = exp
55
- @complete_class_name.unshift const_name
58
+ @complete_class_name.unshift(const_name)
56
59
  return
57
60
  else
58
61
  _, first_part, last_constant_part = exp
@@ -61,53 +64,57 @@ module Archruby
61
64
  end
62
65
  end
63
66
 
64
- def process_const exp
67
+ def process_const(exp)
65
68
  _, const_name = exp
66
69
  if !@full_class_path.empty?
67
70
  const_name = build_full_name(const_name)
68
71
  end
69
- add_dependency const_name
70
- build_class_dependency const_name, exp.line
72
+ add_dependency(const_name)
73
+ build_class_dependency(const_name, exp.line)
71
74
  end
72
75
 
73
- def build_full_name const_name
74
- @full_class_path.unshift const_name
76
+ def build_full_name(const_name)
77
+ @full_class_path.unshift(const_name)
75
78
  full_class_path = @full_class_path.join('::')
76
79
  @full_class_path = []
77
80
  full_class_path
78
81
  end
79
82
 
80
- def build_class_dependency const_name, line_number
83
+ def build_class_dependency(const_name, line_number)
81
84
  return if @classes.empty?
82
85
  class_name = @classes.last
83
86
  @classes_and_dependencies[class_name] = [] if @classes_and_dependencies[class_name].nil?
84
87
  @classes_and_dependencies[class_name] << Archruby::Architecture::Dependency.new(const_name, line_number)
85
88
  end
86
89
 
87
- def add_dependency const_name
90
+ def process_for(exp)
91
+
92
+ end
93
+
94
+ def add_dependency(const_name)
88
95
  @dependencies << const_name.to_s if !@dependencies.include?(const_name.to_s)
89
96
  end
90
97
 
91
- def process_colon3 exp
98
+ def process_colon3(exp)
92
99
  _, constant_name = exp
93
100
  const_name = build_full_name("::#{constant_name}")
94
- add_dependency const_name
95
- build_class_dependency const_name, exp.line
101
+ add_dependency(const_name)
102
+ build_class_dependency(const_name, exp.line)
96
103
  end
97
104
 
98
- def process_call exp
105
+ def process_call(exp)
99
106
  _, receiver, method_name, *args = exp
100
- process receiver
107
+ process(receiver)
101
108
  if receiver && (receiver[0] == :const || receiver[0] == :colon2)
102
109
  if @variables
103
- @var_propagation.push @variables.last, exp.line, @dependencies.last
110
+ @var_propagation.push(@variables.last, exp.line, @dependencies.last)
104
111
  end
105
112
  end
106
113
  build_type_inference(receiver, method_name, args, exp.line)
107
114
  args.map! {|sub_tree| process sub_tree}
108
115
  end
109
116
 
110
- def build_call_history receiver, method_name, params_name
117
+ def build_call_history(receiver, method_name, params_name)
111
118
  @method_calls << {
112
119
  :class => @classes.last,
113
120
  :method => @current_method_name,
@@ -115,10 +122,10 @@ module Archruby
115
122
  :class_call => receiver,
116
123
  :method_call => method_name,
117
124
  :method_call_params => params_name
118
- }
125
+ }
119
126
  end
120
127
 
121
- def build_type_inference receiver, method_name, params, line_num
128
+ def build_type_inference(receiver, method_name, params, line_num)
122
129
  if !@local_types.nil? && receiver && receiver[0] == :lvar
123
130
  receiver = @local_types[receiver[1]]
124
131
  params_name = []
@@ -151,28 +158,27 @@ module Archruby
151
158
  end
152
159
  end
153
160
 
154
- def extract_arguments arguments
161
+ def extract_arguments(arguments)
155
162
  _, *arg_vars = arguments
156
163
  if arg_vars[0].class == Symbol
157
164
  @current_arguments = arg_vars
158
165
  end
159
166
  end
160
167
 
161
- def process_defn exp
168
+ def process_defn(exp)
162
169
  @variables = []
163
170
  @local_types = {}
164
171
  _, method_name, method_arguments, *args = exp
165
172
  @current_method_name = method_name
166
173
  extract_arguments(method_arguments)
167
- process method_arguments
174
+ process(method_arguments)
168
175
  args.map! {|sub_tree| process sub_tree}
169
176
  @var_propagation.vars.each do |var|
170
177
  var = var[var.keys.first]
171
178
  if var[:type]
172
179
  var[:lines].shift
173
180
  var[:lines].each do |line_number|
174
-
175
- build_class_dependency var[:type], line_number
181
+ build_class_dependency(var[:type], line_number)
176
182
  end
177
183
  end
178
184
  end
@@ -182,185 +188,185 @@ module Archruby
182
188
  @current_arguments = nil
183
189
  end
184
190
 
185
- def process_lasgn exp
191
+ def process_lasgn(exp)
186
192
  _, variable_name, *args = exp
187
193
  const_access = args[0][0] == :call unless args[0].nil?
188
194
  @variables.push(variable_name) if @variables
189
- args.map! {|sub_tree| process sub_tree}
195
+ args.map!{ |sub_tree| process(sub_tree) }
190
196
  if @local_types.class == Hash && const_access
191
197
  @local_types[variable_name] = @dependencies.last
192
198
  end
193
199
  end
194
200
 
195
- def process_lit exp
201
+ def process_lit(exp)
196
202
  _, value = exp
197
203
  end
198
204
 
199
- def process_lvar exp
205
+ def process_lvar(exp)
200
206
  _, variable_name = exp
201
- @var_propagation.push variable_name, exp.line
207
+ @var_propagation.push(variable_name, exp.line)
202
208
  end
203
209
 
204
- def process_iter exp
210
+ def process_iter(exp)
205
211
  _, *args = exp
206
- args.map! {|sub_tree| process sub_tree}
212
+ args.map! {|sub_tree| next if sub_tree.class == Fixnum; process(sub_tree)}
207
213
  end
208
214
 
209
- def process_args exp
215
+ def process_args(exp)
210
216
  _, *args = exp
211
217
  args.map! do |sub_tree|
212
218
  process sub_tree if sub_tree.class != Symbol
213
219
  end
214
220
  end
215
221
 
216
- def process_nil exp
222
+ def process_nil(exp)
217
223
  _ = exp
218
224
  end
219
225
 
220
- def process_str exp
226
+ def process_str(exp)
221
227
  _, string = exp
222
228
  end
223
229
 
224
- def process_return exp
230
+ def process_return(exp)
225
231
  _, *args = exp
226
- args.map! {|sub_tree| process sub_tree}
232
+ args.map! {|sub_tree| process(sub_tree) }
227
233
  end
228
234
 
229
- def process_colon2 exp
235
+ def process_colon2(exp)
230
236
  _, first_part, last_part = exp
231
237
  @full_class_path.unshift(last_part)
232
- process first_part
238
+ process(first_part)
233
239
  end
234
240
 
235
- def process_hash exp
241
+ def process_hash(exp)
236
242
  _, *args = exp
237
- args.map! {|sub_tree| process sub_tree}
243
+ args.map! {|sub_tree| process(sub_tree)}
238
244
  end
239
245
 
240
246
  def process_iasgn exp
241
247
  _, variable_name, *args = exp
242
- args.map! {|sub_tree| process sub_tree}
248
+ args.map! {|sub_tree| process(sub_tree)}
243
249
  end
244
250
 
245
- def process_defs exp
251
+ def process_defs(exp)
246
252
  _, receiver, method_name, arguments, *args = exp
247
- process arguments
248
- args.map! {|sub_tree| process sub_tree}
253
+ process(arguments)
254
+ args.map! {|sub_tree| process(sub_tree)}
249
255
  end
250
256
 
251
- def process_attrasgn exp
257
+ def process_attrasgn(exp)
252
258
  _, object, method_call, *args = exp
253
- process object
254
- args.map! {|sub_tree| process sub_tree}
259
+ process(object)
260
+ args.map! {|sub_tree| process(sub_tree)}
255
261
  end
256
262
 
257
- def process_ivar exp
263
+ def process_ivar(exp)
258
264
  _, instance_variable_name = exp
259
265
  end
260
266
 
261
- def process_dstr exp
267
+ def process_dstr(exp)
262
268
  _, string, *args = exp
263
- args.map! {|sub_tree| process sub_tree}
269
+ args.map! {|sub_tree| process(sub_tree)}
264
270
  end
265
271
 
266
- def process_evstr exp
272
+ def process_evstr(exp)
267
273
  _, *args = exp
268
- args.map! {|sub_tree| process sub_tree}
274
+ args.map! {|sub_tree| process(sub_tree)}
269
275
  end
270
276
 
271
- def process_self exp
277
+ def process_self(exp)
272
278
  _ = exp
273
279
  end
274
280
 
275
- def process_masgn exp
281
+ def process_masgn(exp)
276
282
  _, *args = exp
277
- args.map! {|sub_tree| process sub_tree}
283
+ args.map! {|sub_tree| process(sub_tree)}
278
284
  end
279
285
 
280
- def process_array exp
286
+ def process_array(exp)
281
287
  _, *args = exp
282
- args.map! {|sub_tree| process sub_tree}
288
+ args.map! {|sub_tree| process(sub_tree)}
283
289
  end
284
290
 
285
- def process_cdecl exp
291
+ def process_cdecl(exp)
286
292
  _, constant_name = exp
287
293
  end
288
294
 
289
- def process_and exp
295
+ def process_and(exp)
290
296
  _, *args = exp
291
- args.map! {|sub_tree| process sub_tree}
297
+ args.map! {|sub_tree| process(sub_tree)}
292
298
  end
293
299
 
294
- def process_rescue exp
300
+ def process_rescue(exp)
295
301
  _, *args = exp
296
- args.map! {|sub_tree| process sub_tree}
302
+ args.map! {|sub_tree| process(sub_tree)}
297
303
  end
298
304
 
299
- def process_resbody exp
305
+ def process_resbody(exp)
300
306
  _, *args = exp
301
- args.map! {|sub_tree| process sub_tree}
307
+ args.map! {|sub_tree| process(sub_tree)}
302
308
  end
303
309
 
304
- def process_gvar exp
310
+ def process_gvar(exp)
305
311
  _, ruby_global_var_name = exp
306
312
  end
307
313
 
308
- def process_if exp
314
+ def process_if(exp)
309
315
  _, *args = exp
310
- args.map! {|sub_tree| process sub_tree}
316
+ args.map! {|sub_tree| process(sub_tree)}
311
317
  end
312
318
 
313
- def process_true exp
319
+ def process_true(exp)
314
320
  _ = exp
315
321
  end
316
322
 
317
- def process_false exp
323
+ def process_false(exp)
318
324
  _ = exp
319
325
  end
320
326
 
321
- def process_case exp
327
+ def process_case(exp)
322
328
  _, *args = exp
323
- args.map! {|sub_tree| process sub_tree}
329
+ args.map! {|sub_tree| process(sub_tree)}
324
330
  end
325
331
 
326
- def process_when exp
332
+ def process_when(exp)
327
333
  _, *args = exp
328
- args.map! {|sub_tree| process sub_tree}
334
+ args.map! {|sub_tree| process(sub_tree)}
329
335
  end
330
336
 
331
- def process_op_asgn1 exp
337
+ def process_op_asgn1(exp)
332
338
  _, variabe_rec, position_to_access, operator, *args = exp
333
- args.map! {|sub_tree| process sub_tree}
339
+ args.map! {|sub_tree| process(sub_tree)}
334
340
  end
335
341
 
336
- def process_arglist exp
342
+ def process_arglist(exp)
337
343
  _, *args = exp
338
- args.map! {|sub_tree| process sub_tree}
344
+ args.map! {|sub_tree| process(sub_tree)}
339
345
  end
340
346
 
341
- def process_block_pass exp
347
+ def process_block_pass(exp)
342
348
  _, *args = exp
343
- args.map! {|sub_tree| process sub_tree}
349
+ args.map! {|sub_tree| process(sub_tree)}
344
350
  end
345
351
 
346
- def process_or exp
352
+ def process_or(exp)
347
353
  _, *args = exp
348
- args.map! {|sub_tree| process sub_tree}
354
+ args.map! {|sub_tree| process(sub_tree)}
349
355
  end
350
356
 
351
- def process_sclass exp
357
+ def process_sclass(exp)
352
358
  _, *args = exp
353
359
  args.map! {|sub_tree| process sub_tree}
354
360
  end
355
361
 
356
- def process_next exp
362
+ def process_next(exp)
357
363
  _ = exp
358
364
  end
359
365
 
360
- def process_module exp
366
+ def process_module(exp)
361
367
  _, module_name, *args = exp
362
368
  if module_name.class == Symbol
363
- @module_names.push module_name.to_s
369
+ @module_names.push(module_name.to_s)
364
370
  @classes << @module_names.join('::')
365
371
  else
366
372
  get_complete_class_name(module_name)
@@ -368,98 +374,98 @@ module Archruby
368
374
  @module_names.push @complete_class_name.join('::')
369
375
  @complete_class_name = []
370
376
  end
371
- args.map! {|sub_tree| process sub_tree}
377
+ args.map! {|sub_tree| process(sub_tree)}
372
378
  @module_names.pop
373
379
  end
374
380
 
375
- def process_to_ary exp
381
+ def process_to_ary(exp)
376
382
  _, *args = exp
377
- args.map! {|sub_tree| process sub_tree}
383
+ args.map! {|sub_tree| process(sub_tree)}
378
384
  end
379
385
 
380
- def process_while exp
386
+ def process_while(exp)
381
387
  _, condition, *args = exp
382
388
  true_clause = args.pop
383
- args.map! {|sub_tree| process sub_tree}
389
+ args.map! {|sub_tree| process(sub_tree)}
384
390
  end
385
391
 
386
- def process_cvdecl exp
392
+ def process_cvdecl(exp)
387
393
  _, variable_name, *args = exp
388
- args.map! {|sub_tree| process sub_tree}
394
+ args.map! {|sub_tree| process(sub_tree)}
389
395
  end
390
396
 
391
- def process_cvar exp
397
+ def process_cvar(exp)
392
398
  _, variable_name = exp
393
399
  end
394
400
 
395
- def process_until exp
401
+ def process_until(exp)
396
402
  _, condition, *args = exp
397
403
  true_clause = args.pop
398
- args.map! {|sub_tree| process sub_tree}
404
+ args.map! {|sub_tree| process(sub_tree)}
399
405
  end
400
406
 
401
- def process_yield exp
407
+ def process_yield(exp)
402
408
  _, *body = exp
403
409
  if !body.empty?
404
- body.map! {|sub_tree| process sub_tree}
410
+ body.map! {|sub_tree| process(sub_tree)}
405
411
  end
406
412
  end
407
413
 
408
- def process_dot2 exp
414
+ def process_dot2(exp)
409
415
  _, first, second = exp
410
416
  end
411
417
 
412
- def process_zsuper exp
418
+ def process_zsuper(exp)
413
419
  _ = exp
414
420
  end
415
421
 
416
- def process_op_asgn_or exp
422
+ def process_op_asgn_or(exp)
417
423
  _, first, second = exp
418
- process first
419
- process second
424
+ process(first)
425
+ process(second)
420
426
  end
421
427
 
422
- def process_match3 exp
428
+ def process_match3(exp)
423
429
  _, regular_expression, *args = exp
424
- args.map! {|sub_tree| process sub_tree}
430
+ args.map! {|sub_tree| process(sub_tree)}
425
431
  end
426
432
 
427
- def process_break exp
433
+ def process_break(exp)
428
434
  _ = exp
429
435
  end
430
436
 
431
- def process_dregx exp
437
+ def process_dregx(exp)
432
438
  _, regex = exp
433
439
  end
434
440
 
435
- def process_super exp
441
+ def process_super(exp)
436
442
  _, args = exp
437
- process args
443
+ process(args)
438
444
  end
439
445
 
440
- def process_ensure exp
446
+ def process_ensure(exp)
441
447
  _, rescue_clause, *ensure_clause = exp
442
- process rescue_clause
443
- ensure_clause.map! {|sub_tree| process sub_tree}
448
+ process(rescue_clause)
449
+ ensure_clause.map! {|sub_tree| process(sub_tree)}
444
450
  end
445
451
 
446
- def process_op_asgn2 exp
452
+ def process_op_asgn2(exp)
447
453
  _, left_assign, variable, method, args = exp
448
- process left_assign
449
- process args
454
+ process(left_assign)
455
+ process(args)
450
456
  end
451
457
 
452
- def process_splat exp
458
+ def process_splat(exp)
453
459
  _, left_assign = exp
454
- process left_assign
460
+ process(left_assign)
455
461
  end
456
462
 
457
- def process_dxstr exp
463
+ def process_dxstr(exp)
458
464
  # shelling out
459
465
  _ = exp
460
466
  end
461
467
 
462
- def process_dot3 exp
468
+ def process_dot3(exp)
463
469
  _ = exp
464
470
  end
465
471