archruby 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,155 @@
1
+ module Archruby
2
+ module Ruby
3
+ module TypeInference
4
+ module Ruby
5
+
6
+ class ProcessMethodArguments < SexpInterpreter
7
+ def initialize(ast)
8
+ super()
9
+ @ast = ast
10
+ @params = {}
11
+ @current_dependency_class = []
12
+ @current_dependency_class_name = nil
13
+ end
14
+
15
+ def parse
16
+ process(@ast)
17
+ @params
18
+ end
19
+
20
+ def process_args(exp)
21
+ _, *args = exp
22
+ if !args.empty?
23
+ if args.first.class == Symbol
24
+ @params[args.first] ||= Set.new
25
+ else
26
+ args.map! {|sub_tree| process(sub_tree) if sub_tree.class == Sexp}
27
+ end
28
+ end
29
+ end
30
+
31
+ def process_lasgn(exp)
32
+ _, variable_name, *args = exp
33
+ @params[variable_name] ||= Set.new
34
+ args.map! {|sub_tree| process(sub_tree)}
35
+ @params[variable_name].add(@current_dependency_class_name)
36
+ @current_dependency_class_name = nil
37
+ end
38
+
39
+ def process_lit(exp)
40
+ _, value = exp
41
+ end
42
+
43
+ def process_call(exp)
44
+ _, receiver, method_name, *args = exp
45
+ process(receiver)
46
+ args.map! { |subtree| process(subtree) }
47
+ end
48
+
49
+ def process_const(exp)
50
+ _, const_name = exp
51
+ if !@current_dependency_class.empty?
52
+ @current_dependency_class_name = build_full_name(const_name)
53
+ else
54
+ @current_dependency_class_name = const_name.to_s
55
+ end
56
+ end
57
+
58
+ def process_colon2(exp)
59
+ _, first_part, last_part = exp
60
+ @current_dependency_class.unshift(last_part)
61
+ process(first_part)
62
+ end
63
+
64
+ def process_colon3(exp)
65
+ _, constant_name = exp
66
+ @current_dependency_class_name = build_full_name("::#{constant_name}")
67
+ end
68
+
69
+ def build_full_name(const_name)
70
+ @current_dependency_class.unshift(const_name)
71
+ full_class_path = @current_dependency_class.join('::')
72
+ @current_dependency_class = []
73
+ full_class_path
74
+ end
75
+
76
+ def process_hash(exp)
77
+ _, key, value = exp
78
+ process(key)
79
+ process(value)
80
+ end
81
+
82
+ def process_if(exp)
83
+ _, *args = exp
84
+ args.map! {|sub_tree| process(sub_tree) if sub_tree.class == Sexp }
85
+ end
86
+
87
+ def process_kwarg(exp)
88
+ _, *args = exp
89
+ args.map! { |subtree| process(subtree) if subtree.class == Sexp}
90
+ end
91
+
92
+ def process_array(exp)
93
+ _, *args = exp
94
+ args.map! {|sub_tree| process(sub_tree)}
95
+ end
96
+
97
+ def process_ivar(exp)
98
+ _, var_name, *args = exp
99
+ args.map! {|sub_tree| process(sub_tree)}
100
+ end
101
+
102
+ def process_iter(exp)
103
+ _, first_part, second_part, *body = exp
104
+ process(first_part)
105
+ body.map! {|sub_tree| process(sub_tree)}
106
+ end
107
+
108
+ def process_cvasgn(exp)
109
+ _, class_var_name, *value = exp
110
+ value.map! {|sub_tree| process(sub_tree)}
111
+ end
112
+
113
+ def process_masgn(exp)
114
+ _, *args = exp
115
+ args.map! {|sub_tree| process(sub_tree) if sub_tree.class == Sexp}
116
+ end
117
+
118
+ def process_or(exp)
119
+ _, left_side, right_side = exp
120
+ process(left_side)
121
+ process(right_side)
122
+ end
123
+
124
+ def process_lvar(exp)
125
+ end
126
+
127
+ def process_cvar(exp)
128
+ # class variable
129
+ end
130
+
131
+ def process_true(exp)
132
+ end
133
+
134
+ def process_nil(exp)
135
+ end
136
+
137
+ def process_str(exp)
138
+ end
139
+
140
+ def process_false(exp)
141
+ end
142
+
143
+ def process_self(exp)
144
+ end
145
+
146
+ def process_gvar(exp)
147
+ #global variables
148
+ end
149
+
150
+ end
151
+
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,427 @@
1
+ module Archruby
2
+ module Ruby
3
+ module TypeInference
4
+ module Ruby
5
+
6
+ class ProcessMethodBody < SexpInterpreter
7
+ def initialize(ast, local_scope)
8
+ super()
9
+ @ast = ast
10
+ @params = {}
11
+ @current_dependency_class = []
12
+ @current_dependency_class_name = nil
13
+ @method_calls = []
14
+ @local_scope = local_scope
15
+ end
16
+
17
+ def parse
18
+ #binding.pry
19
+ @ast.map! {|sub_tree| process(sub_tree)}
20
+ @method_calls
21
+ end
22
+
23
+ def process_call(exp)
24
+ _, receiver, method_name, *params = exp
25
+ if receiver && receiver[0] == :lvar && receiver[1].class == Symbol
26
+ type = @local_scope.var_type(receiver[1])
27
+ parsed_params = ProcessMethodParams.new(params, @local_scope).parse
28
+ add_method_call(type, method_name, parsed_params)
29
+ elsif !receiver.nil?
30
+ process(receiver)
31
+ parsed_params = nil
32
+ if check_if_has_params(params)
33
+ parsed_params = ProcessMethodParams.new(params, @local_scope).parse
34
+ end
35
+ add_method_call(@current_dependency_class_name, method_name, parsed_params)
36
+ #@current_dependency_class_name = nil
37
+ end
38
+ end
39
+
40
+ def process_defs(exp)
41
+ #estudar esse caso -> acontece no rails em activemodel
42
+ end
43
+
44
+ def check_if_has_params(params)
45
+ has_local_params = false
46
+ params.each do |param|
47
+ if param[0] == :lvar
48
+ has_local_params = @local_scope.has_formal_parameter(param[1]) || @local_scope.has_local_params(param[1])
49
+ end
50
+ end
51
+ has_local_params
52
+ end
53
+
54
+ def add_method_call(class_name, method_name, params=nil)
55
+ @method_calls << InternalMethodInvocation.new(class_name, method_name, params)
56
+ end
57
+
58
+ def process_lasgn(exp)
59
+ _, variable_name, *args = exp
60
+ args.map! { |subtree| process(subtree) }
61
+ if @current_dependency_class_name
62
+ @local_scope.add_variable(variable_name, @current_dependency_class_name)
63
+ end
64
+ @current_dependency_class_name = nil
65
+ end
66
+
67
+ def process_const(exp)
68
+ _, const_name = exp
69
+ if !@current_dependency_class.empty?
70
+ @current_dependency_class_name = build_full_name(const_name)
71
+ else
72
+ @current_dependency_class_name = const_name.to_s
73
+ end
74
+ end
75
+
76
+ def process_colon3(exp)
77
+ _, constant_name = exp
78
+ @current_dependency_class_name = build_full_name("::#{constant_name}")
79
+ end
80
+
81
+ def process_colon2(exp)
82
+ _, first_part, last_part = exp
83
+ @current_dependency_class.unshift(last_part)
84
+ process(first_part)
85
+ end
86
+
87
+ def build_full_name(const_name)
88
+ @current_dependency_class.unshift(const_name)
89
+ full_class_path = @current_dependency_class.join('::')
90
+ @current_dependency_class = []
91
+ full_class_path
92
+ end
93
+
94
+ def process_attrasgn(exp)
95
+ _, receiver, method_name, value = exp
96
+ process(receiver)
97
+ process(value)
98
+ end
99
+
100
+ def process_iasgn(exp)
101
+ _, instance_varialbe_name, *value = exp
102
+ value.map! { |subtree| process(subtree) }
103
+ end
104
+
105
+ def process_op_asgn1(exp)
106
+ process(exp.last)
107
+ end
108
+
109
+ def process_match3(exp)
110
+ _, left_side, right_side = exp
111
+ process(left_side)
112
+ process(right_side)
113
+ end
114
+
115
+ def process_op_asgn2(exp)
116
+ _, receiver, method, met, last = exp
117
+ process(receiver)
118
+ process(last)
119
+ end
120
+
121
+ def process_iter(exp)
122
+ _, first_part, second_part, *body = exp
123
+ process(first_part)
124
+ body.map! {|sub_tree| process(sub_tree)}
125
+ end
126
+
127
+ def process_if(exp)
128
+ _, condition, true_body, else_body = exp
129
+ process(condition)
130
+ process(true_body)
131
+ process(else_body)
132
+ end
133
+
134
+ def process_dsym(exp)
135
+ _, str, *args = exp
136
+ args.map! {|sub_tree| process(sub_tree)}
137
+ end
138
+
139
+ def process_block(exp)
140
+ _, *args = exp
141
+ args.map! { |subtree| process(subtree) }
142
+ end
143
+
144
+ def process_hash(exp)
145
+ _, key, value = exp
146
+ process(key)
147
+ process(value)
148
+ end
149
+
150
+ def process_super(exp)
151
+ _, *args = exp
152
+ args.map! {|sub_tree| process(sub_tree)}
153
+ end
154
+
155
+ def process_rescue(exp)
156
+ _, normal, *rescue_body = exp
157
+ process(normal)
158
+ rescue_body.map! {|sub_tree| process(sub_tree)}
159
+ end
160
+
161
+ def process_return(exp)
162
+ _, *value = exp
163
+ value.map! {|sub_tree| process(sub_tree)}
164
+ end
165
+
166
+ def process_resbody(exp)
167
+ _, class_to_rescue, *body = exp
168
+ process(class_to_rescue)
169
+ body.map! {|sub_tree| process(sub_tree)}
170
+ end
171
+
172
+ def process_array(exp)
173
+ _, *args = exp
174
+ args.map! {|sub_tree| process(sub_tree)}
175
+ end
176
+
177
+ def process_and(exp)
178
+ _, left_side, right_side = exp
179
+ process(left_side)
180
+ process(right_side)
181
+ end
182
+
183
+ def process_or(exp)
184
+ _, left_side, right_side = exp
185
+ process(left_side)
186
+ process(right_side)
187
+ end
188
+
189
+ def process_dstr(exp)
190
+ _, start, *args = exp
191
+ args.map! {|sub_tree| process(sub_tree)}
192
+ end
193
+
194
+ def process_dregx_once(exp)
195
+ _, start, *args = exp
196
+ args.map! {|sub_tree| process(sub_tree)}
197
+ end
198
+
199
+ def process_evstr(exp)
200
+ _, *args = exp
201
+ args.map! {|sub_tree| process(sub_tree)}
202
+ end
203
+
204
+ def process_dstr(exp)
205
+ _, init, *args = exp
206
+ args.map! {|sub_tree| process(sub_tree)}
207
+ end
208
+
209
+ def process_dxstr(exp)
210
+ _, str, *args = exp
211
+ args.map! {|sub_tree| process(sub_tree)}
212
+ end
213
+
214
+ def process_ivar(exp)
215
+ _, var_name, *args = exp
216
+ args.map! {|sub_tree| process(sub_tree)}
217
+ end
218
+
219
+ def process_match2(exp)
220
+ _, rec, *args = exp
221
+ args.map! {|sub_tree| process(sub_tree)}
222
+ end
223
+
224
+ def process_match3(exp)
225
+ _, first, second = exp
226
+ process(first)
227
+ process(second)
228
+ end
229
+
230
+ def process_svalue(exp)
231
+ _, *args = exp
232
+ args.map! {|sub_tree| process(sub_tree)}
233
+ end
234
+
235
+ def process_op_asgn_or(exp)
236
+ _, *args = exp
237
+ args.map! {|sub_tree| process(sub_tree)}
238
+ end
239
+
240
+ def process_op_asgn_and(exp)
241
+ _, *args = exp
242
+ args.map! {|sub_tree| process(sub_tree)}
243
+ end
244
+
245
+ def process_ensure(exp)
246
+ _, *args = exp
247
+ args.map! {|sub_tree| process(sub_tree)}
248
+ end
249
+
250
+ def process_while(exp)
251
+ _, condition, body = exp
252
+ process(condition)
253
+ process(body)
254
+ end
255
+
256
+ def process_until(exp)
257
+ _, condition, body, *args = exp
258
+ process(condition)
259
+ process(body)
260
+ end
261
+
262
+ def process_yield(exp)
263
+ _, *args = exp
264
+ args.map! {|sub_tree| process(sub_tree)}
265
+ end
266
+
267
+ def process_splat(exp)
268
+ _, *args = exp
269
+ args.map! {|sub_tree| process(sub_tree)}
270
+ end
271
+
272
+ def process_case(exp)
273
+ _, condition, when_part, ensure_part = exp
274
+ process(condition)
275
+ process(when_part)
276
+ process(ensure_part)
277
+ end
278
+
279
+ def process_for(exp)
280
+ _, x, y, body = exp
281
+ process(x)
282
+ process(y)
283
+ process(body)
284
+ end
285
+
286
+ def process_when(exp)
287
+ _, condition, body = exp
288
+ process(condition)
289
+ process(body)
290
+ end
291
+
292
+ def process_rescue(exp)
293
+ _, body, rescbody = exp
294
+ process(body)
295
+ process(rescbody)
296
+ end
297
+
298
+ def process_cvasgn(exp)
299
+ _, class_var_name, *value = exp
300
+ value.map! {|sub_tree| process(sub_tree)}
301
+ end
302
+
303
+ def process_dot3(exp)
304
+ _, left, right = exp
305
+ process(left)
306
+ process(right)
307
+ end
308
+
309
+ def process_dot2(exp)
310
+ _, left, right = exp
311
+ process(left)
312
+ process(right)
313
+ end
314
+
315
+ def process_block_pass(exp)
316
+ _, *args = exp
317
+ args.map! {|sub_tree| process(sub_tree)}
318
+ end
319
+
320
+ def process_retry(exp)
321
+ end
322
+
323
+ def process_dregx(exp)
324
+ _, str, *args = exp
325
+ args.map! {|sub_tree| process(sub_tree) if sub_tree.class == Sexp}
326
+ end
327
+
328
+ def process_defn(exp)
329
+ #estudar esse caso para ver se vamos quer pegar isso
330
+ end
331
+
332
+ def process_masgn(exp)
333
+ _, *args = exp
334
+ args.map! {|sub_tree| process(sub_tree)}
335
+ end
336
+
337
+ def process_redo(exp)
338
+ end
339
+
340
+ def process_to_ary(exp)
341
+ _, *args = exp
342
+ args.map! {|sub_tree| process(sub_tree)}
343
+ end
344
+
345
+ def process_gasgn(exp)
346
+ _, global_var_name, *value = exp
347
+ value.map! {|sub_tree| process(sub_tree)}
348
+ end
349
+
350
+ def process_sclass(exp)
351
+ _, singleton_class, *body = exp
352
+ body.map! {|sub_tree| process(sub_tree)}
353
+ end
354
+
355
+ def process_not(exp)
356
+ _, *args = exp
357
+ args.map! {|sub_tree| process(sub_tree)}
358
+ end
359
+
360
+ def process_defined(exp)
361
+ _, *args = exp
362
+ args.map! {|sub_tree| process(sub_tree)}
363
+ end
364
+
365
+ def process_cvdecl(exp)
366
+ _, instance_classvar_name, *value = exp
367
+ value.map! {|sub_tree| process(sub_tree)}
368
+ end
369
+
370
+ def process_back_ref(exp)
371
+ end
372
+
373
+ def process_cvar(exp)
374
+ # class variable
375
+ end
376
+
377
+ def process_alias(exp)
378
+ end
379
+
380
+ def process_begin(exp)
381
+ end
382
+
383
+ def process_self(exp)
384
+ end
385
+
386
+ def process_xstr(exp)
387
+ end
388
+
389
+ def process_nth_ref(exp)
390
+ end
391
+
392
+ def process_break(exp)
393
+ end
394
+
395
+ def process_next(exp)
396
+ end
397
+
398
+ def process_str(exp)
399
+ end
400
+
401
+ def process_gvar(exp)
402
+ end
403
+
404
+ def process_nil(exp)
405
+ end
406
+
407
+ def process_zsuper(exp)
408
+ end
409
+
410
+ def process_lit(exp)
411
+ end
412
+
413
+ def process_lvar(exp)
414
+ end
415
+
416
+ def process_true(exp)
417
+ end
418
+
419
+ def process_false(exp)
420
+ end
421
+
422
+ end
423
+
424
+ end
425
+ end
426
+ end
427
+ end