archruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +32 -0
  6. data/Rakefile +1 -0
  7. data/archruby.gemspec +28 -0
  8. data/bin/archruby +20 -0
  9. data/bin/constraints_breaks.yml +29 -0
  10. data/constraints_breaks.yml +22 -0
  11. data/lib/archruby.rb +47 -0
  12. data/lib/archruby/architecture/architecture.rb +83 -0
  13. data/lib/archruby/architecture/config_definition.rb +66 -0
  14. data/lib/archruby/architecture/constraint_break.rb +22 -0
  15. data/lib/archruby/architecture/dependency.rb +11 -0
  16. data/lib/archruby/architecture/file_content.rb +24 -0
  17. data/lib/archruby/architecture/module_definition.rb +218 -0
  18. data/lib/archruby/architecture/parser.rb +58 -0
  19. data/lib/archruby/presenters/graph.rb +132 -0
  20. data/lib/archruby/presenters/text.rb +14 -0
  21. data/lib/archruby/presenters/yaml.rb +28 -0
  22. data/lib/archruby/ruby/core_library.rb +26 -0
  23. data/lib/archruby/ruby/parser.rb +409 -0
  24. data/lib/archruby/ruby/std_library.rb +22 -0
  25. data/lib/archruby/ruby/var_propagation.rb +46 -0
  26. data/lib/archruby/version.rb +3 -0
  27. data/spec/architecture/architecture_spec.rb +48 -0
  28. data/spec/architecture/config_definition_spec.rb +20 -0
  29. data/spec/architecture/constraint_break_spec.rb +22 -0
  30. data/spec/architecture/file_content_spec.rb +12 -0
  31. data/spec/architecture/module_definition_spec.rb +70 -0
  32. data/spec/architecture/parser_spec.rb +11 -0
  33. data/spec/archruby_spec.rb +10 -0
  34. data/spec/dummy_app/.gitignore +16 -0
  35. data/spec/dummy_app/Gemfile +45 -0
  36. data/spec/dummy_app/README.rdoc +28 -0
  37. data/spec/dummy_app/Rakefile +6 -0
  38. data/spec/dummy_app/app/assets/images/.keep +0 -0
  39. data/spec/dummy_app/app/assets/javascripts/application.js +16 -0
  40. data/spec/dummy_app/app/assets/stylesheets/application.css +13 -0
  41. data/spec/dummy_app/app/controllers/application_controller.rb +17 -0
  42. data/spec/dummy_app/app/controllers/concerns/.keep +0 -0
  43. data/spec/dummy_app/app/helpers/application_helper.rb +2 -0
  44. data/spec/dummy_app/app/mailers/.keep +0 -0
  45. data/spec/dummy_app/app/models/.keep +0 -0
  46. data/spec/dummy_app/app/models/concerns/.keep +0 -0
  47. data/spec/dummy_app/app/models/module_test.rb +5 -0
  48. data/spec/dummy_app/app/models/teste.rb +11 -0
  49. data/spec/dummy_app/app/models/user.rb +9 -0
  50. data/spec/dummy_app/app/views/layouts/application.html.erb +14 -0
  51. data/spec/dummy_app/app/views/view_test.rb +5 -0
  52. data/spec/dummy_app/bin/bundle +3 -0
  53. data/spec/dummy_app/bin/rails +4 -0
  54. data/spec/dummy_app/bin/rake +4 -0
  55. data/spec/dummy_app/config.ru +4 -0
  56. data/spec/dummy_app/config/application.rb +23 -0
  57. data/spec/dummy_app/config/boot.rb +4 -0
  58. data/spec/dummy_app/config/database.yml +25 -0
  59. data/spec/dummy_app/config/environment.rb +5 -0
  60. data/spec/dummy_app/config/environments/development.rb +29 -0
  61. data/spec/dummy_app/config/environments/production.rb +80 -0
  62. data/spec/dummy_app/config/environments/test.rb +36 -0
  63. data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy_app/config/initializers/filter_parameter_logging.rb +4 -0
  65. data/spec/dummy_app/config/initializers/inflections.rb +16 -0
  66. data/spec/dummy_app/config/initializers/mime_types.rb +5 -0
  67. data/spec/dummy_app/config/initializers/secret_token.rb +12 -0
  68. data/spec/dummy_app/config/initializers/session_store.rb +3 -0
  69. data/spec/dummy_app/config/initializers/wrap_parameters.rb +14 -0
  70. data/spec/dummy_app/config/locales/en.yml +23 -0
  71. data/spec/dummy_app/config/routes.rb +56 -0
  72. data/spec/dummy_app/db/seeds.rb +7 -0
  73. data/spec/dummy_app/lib/assets/.keep +0 -0
  74. data/spec/dummy_app/lib/fetch_facebook_info.rb +7 -0
  75. data/spec/dummy_app/lib/integracao_twitter.rb +5 -0
  76. data/spec/dummy_app/lib/tasks/.keep +0 -0
  77. data/spec/dummy_app/log/.keep +0 -0
  78. data/spec/dummy_app/public/404.html +58 -0
  79. data/spec/dummy_app/public/422.html +58 -0
  80. data/spec/dummy_app/public/500.html +57 -0
  81. data/spec/dummy_app/public/favicon.ico +0 -0
  82. data/spec/dummy_app/public/robots.txt +5 -0
  83. data/spec/dummy_app/test/controllers/.keep +0 -0
  84. data/spec/dummy_app/test/fixtures/.keep +0 -0
  85. data/spec/dummy_app/test/helpers/.keep +0 -0
  86. data/spec/dummy_app/test/integration/.keep +0 -0
  87. data/spec/dummy_app/test/mailers/.keep +0 -0
  88. data/spec/dummy_app/test/models/.keep +0 -0
  89. data/spec/dummy_app/test/test_helper.rb +15 -0
  90. data/spec/dummy_app/vendor/assets/javascripts/.keep +0 -0
  91. data/spec/dummy_app/vendor/assets/stylesheets/.keep +0 -0
  92. data/spec/fixtures/new_arch_definition.yml +32 -0
  93. data/spec/fixtures/ruby_example.rb +74 -0
  94. data/spec/ruby/parser_spec.rb +45 -0
  95. data/spec/ruby/var_propagation_spec.rb +22 -0
  96. data/spec/spec_helper.rb +1 -0
  97. metadata +295 -0
@@ -0,0 +1,26 @@
1
+ module Archruby
2
+ module Ruby
3
+ CORE_LIB_NAME = 'ruby_core_lib'
4
+ CORE_LIBRARY_CLASSES = [
5
+ 'Array', 'Bignum', 'BasicObject', 'Object', 'Module', 'Class', 'Complex', 'Complex::compatible',
6
+ 'NilClass', 'Numeric', 'String', 'Float', 'Fiber', 'FiberError', 'Continuation', 'Dir', 'File',
7
+ 'Encoding', 'Enumerator', 'StopIteration', 'Enumerator::Lazy', 'Enumerator::Generator',
8
+ 'Enumerator::Yielder', 'Exception', 'SystemExit', 'fatal', 'SignalException', 'Interrupt',
9
+ 'StandardError', 'TypeError', 'ArgumentError', 'IndexError', 'KeyError', 'RangeError',
10
+ 'ScriptError', 'SyntaxError', 'LoadError', 'NotImplementedError', 'NameError', 'NoMethodError',
11
+ 'RuntimeError', 'SecurityError', 'NoMemoryError', 'EncodingError', 'SystemCallError',
12
+ 'Encoding::CompatibilityError', 'File::Stat', 'IO', 'ObjectSpace::WeakMap', 'Hash', 'ENV',
13
+ 'IOError', 'EOFError', 'ARGF', 'RubyVM', 'RubyVM::InstructionSequence', 'Math::DomainError',
14
+ 'ZeroDivisionError', 'FloatDomainError', 'Integer', 'Fixnum', 'Data', 'TrueClass', 'FalseClass',
15
+ 'Thread', 'Proc', 'LocalJumpError', 'SystemStackError', 'Method', 'UnboundMethod', 'Binding',
16
+ 'Process::Status', 'Random', 'Range', 'Rational', 'Rational::compatible', 'RegexpError',
17
+ 'Regexp', 'MatchData', 'Symbol', 'Struct', 'ThreadGroup', 'Mutex', 'ThreadError', 'Time',
18
+ 'Encoding::UndefinedConversionError', 'Encoding::InvalidByteSequenceError',
19
+ 'Encoding::ConverterNotFoundError', 'Encoding::Converter', 'RubyVM::Env', 'Thread::Backtrace',
20
+ 'Thread::Backtrace::Location', 'TracePoint', 'Comparable', 'Kernel', 'File::Constants',
21
+ 'Enumerable', 'Errno', 'FileTest', 'GC', 'ObjectSpace', 'GC::Profiler', 'IO::WaitReadable',
22
+ 'IO::WaitWritable', 'Marshal', 'Math', 'Process', 'Process::UID', 'Process::GID', 'Process::Sys',
23
+ 'Signal'
24
+ ]
25
+ end
26
+ end
@@ -0,0 +1,409 @@
1
+ require 'ruby_parser'
2
+ require 'sexp_processor'
3
+
4
+ module Archruby
5
+ module Ruby
6
+
7
+ class Parser < SexpInterpreter
8
+ attr_reader :dependencies, :classes, :classes_and_dependencies
9
+
10
+ def initialize content
11
+ super()
12
+ @content = content
13
+ @dependencies = []
14
+ @classes = []
15
+ @full_class_path = []
16
+ @classes_and_dependencies = {}
17
+ @module_names = []
18
+ @complete_class_name = []
19
+ @var_propagation = Archruby::Ruby::VarPropagation.new
20
+ parse
21
+ end
22
+
23
+ def parse
24
+ process ruby_parser.parse @content
25
+ end
26
+
27
+ def process_block exp
28
+ _, *args = exp
29
+ args.map! {|sub_tree| process sub_tree}
30
+ end
31
+
32
+ def process_class exp
33
+ _, class_name, *args = exp
34
+ if class_name.class == Symbol
35
+ if !@module_names.empty?
36
+ @classes << "#{@module_names.join("::")}::#{class_name}"
37
+ else
38
+ @classes << class_name.to_s
39
+ end
40
+ else
41
+ # cai aqui quando a definicao é algo do tipo: class Teste::De end
42
+ get_complete_class_name class_name
43
+ @classes << @complete_class_name.join("::")
44
+ @complete_class_name = []
45
+ end
46
+ args.map! {|sub_tree| process sub_tree}
47
+ end
48
+
49
+ def get_complete_class_name exp
50
+ if exp[0] == :const
51
+ _, const_name = exp
52
+ @complete_class_name.unshift const_name
53
+ return
54
+ else
55
+ _, first_part, last_constant_part = exp
56
+ @complete_class_name.unshift(last_constant_part)
57
+ get_complete_class_name first_part
58
+ end
59
+ end
60
+
61
+ def process_const exp
62
+ _, const_name = exp
63
+ if !@full_class_path.empty?
64
+ const_name = build_full_name(const_name)
65
+ end
66
+ add_dependency const_name
67
+ build_class_dependency const_name, exp.line
68
+ end
69
+
70
+ def build_full_name const_name
71
+ @full_class_path.unshift const_name
72
+ full_class_path = @full_class_path.join('::')
73
+ @full_class_path = []
74
+ full_class_path
75
+ end
76
+
77
+ def build_class_dependency const_name, line_number
78
+ return if @classes.empty?
79
+ class_name = @classes.last
80
+ @classes_and_dependencies[class_name] = [] if @classes_and_dependencies[class_name].nil?
81
+ @classes_and_dependencies[class_name] << Archruby::Architecture::Dependency.new(const_name, line_number)
82
+ end
83
+
84
+ def add_dependency const_name
85
+ @dependencies << const_name.to_s if !@dependencies.include?(const_name.to_s)
86
+ end
87
+
88
+ def process_colon3 exp
89
+ _, constant_name = exp
90
+ const_name = build_full_name("::#{constant_name}")
91
+ add_dependency const_name
92
+ build_class_dependency const_name, exp.line
93
+ end
94
+
95
+ def process_call exp
96
+ _, receiver, method_name, *args = exp
97
+ process receiver
98
+
99
+ if receiver && (receiver[0] == :const || receiver[0] == :colon2)
100
+ if @variables
101
+ @var_propagation.push @variables.last, exp.line, @dependencies.last
102
+ end
103
+ end
104
+ args.map! {|sub_tree| process sub_tree}
105
+ end
106
+
107
+ def process_defn exp
108
+ @variables = []
109
+ _, method_name, method_arguments, *args = exp
110
+ process method_arguments
111
+ args.map! {|sub_tree| process sub_tree}
112
+ @var_propagation.vars.each do |var|
113
+ var = var[var.keys.first]
114
+ if var[:type]
115
+ var[:lines].shift
116
+ var[:lines].each do |line_number|
117
+
118
+ build_class_dependency var[:type], line_number
119
+ end
120
+ end
121
+ end
122
+ @var_propagation = Archruby::Ruby::VarPropagation.new
123
+ @variables = []
124
+ end
125
+
126
+ def process_lasgn exp
127
+ _, variable_name, *args = exp
128
+ @variables.push(variable_name) if @variables
129
+ args.map! {|sub_tree| process sub_tree}
130
+ end
131
+
132
+ def process_lit exp
133
+ _, value = exp
134
+ end
135
+
136
+ def process_lvar exp
137
+ _, variable_name = exp
138
+ @var_propagation.push variable_name, exp.line
139
+ end
140
+
141
+ def process_iter exp
142
+ _, *args = exp
143
+ args.map! {|sub_tree| process sub_tree}
144
+ end
145
+
146
+ def process_args exp
147
+ _, *args = exp
148
+ args.map! do |sub_tree|
149
+ process sub_tree if sub_tree.class != Symbol
150
+ end
151
+ end
152
+
153
+ def process_nil exp
154
+ _ = exp
155
+ end
156
+
157
+ def process_str exp
158
+ _, string = exp
159
+ end
160
+
161
+ def process_return exp
162
+ _, *args = exp
163
+ args.map! {|sub_tree| process sub_tree}
164
+ end
165
+
166
+ def process_colon2 exp
167
+ _, first_part, last_part = exp
168
+ @full_class_path.unshift(last_part)
169
+ process first_part
170
+ end
171
+
172
+ def process_hash exp
173
+ _, *args = exp
174
+ args.map! {|sub_tree| process sub_tree}
175
+ end
176
+
177
+ def process_iasgn exp
178
+ _, variable_name, *args = exp
179
+ args.map! {|sub_tree| process sub_tree}
180
+ end
181
+
182
+ def process_defs exp
183
+ _, receiver, method_name, arguments, *args = exp
184
+ process arguments
185
+ args.map! {|sub_tree| process sub_tree}
186
+ end
187
+
188
+ def process_attrasgn exp
189
+ _, object, method_call, *args = exp
190
+ process object
191
+ args.map! {|sub_tree| process sub_tree}
192
+ end
193
+
194
+ def process_ivar exp
195
+ _, instance_variable_name = exp
196
+ end
197
+
198
+ def process_dstr exp
199
+ _, string, *args = exp
200
+ args.map! {|sub_tree| process sub_tree}
201
+ end
202
+
203
+ def process_evstr exp
204
+ _, *args = exp
205
+ args.map! {|sub_tree| process sub_tree}
206
+ end
207
+
208
+ def process_self exp
209
+ _ = exp
210
+ end
211
+
212
+ def process_masgn exp
213
+ _, *args = exp
214
+ args.map! {|sub_tree| process sub_tree}
215
+ end
216
+
217
+ def process_array exp
218
+ _, *args = exp
219
+ args.map! {|sub_tree| process sub_tree}
220
+ end
221
+
222
+ def process_cdecl exp
223
+ _, constant_name = exp
224
+ end
225
+
226
+ def process_and exp
227
+ _, *args = exp
228
+ args.map! {|sub_tree| process sub_tree}
229
+ end
230
+
231
+ def process_rescue exp
232
+ _, *args = exp
233
+ args.map! {|sub_tree| process sub_tree}
234
+ end
235
+
236
+ def process_resbody exp
237
+ _, *args = exp
238
+ args.map! {|sub_tree| process sub_tree}
239
+ end
240
+
241
+ def process_gvar exp
242
+ _, ruby_global_var_name = exp
243
+ end
244
+
245
+ def process_if exp
246
+ _, *args = exp
247
+ args.map! {|sub_tree| process sub_tree}
248
+ end
249
+
250
+ def process_true exp
251
+ _ = exp
252
+ end
253
+
254
+ def process_false exp
255
+ _ = exp
256
+ end
257
+
258
+ def process_case exp
259
+ _, *args = exp
260
+ args.map! {|sub_tree| process sub_tree}
261
+ end
262
+
263
+ def process_when exp
264
+ _, *args = exp
265
+ args.map! {|sub_tree| process sub_tree}
266
+ end
267
+
268
+ def process_op_asgn1 exp
269
+ _, variabe_rec, position_to_access, operator, *args = exp
270
+ args.map! {|sub_tree| process sub_tree}
271
+ end
272
+
273
+ def process_arglist exp
274
+ _, *args = exp
275
+ args.map! {|sub_tree| process sub_tree}
276
+ end
277
+
278
+ def process_block_pass exp
279
+ _, *args = exp
280
+ args.map! {|sub_tree| process sub_tree}
281
+ end
282
+
283
+ def process_or exp
284
+ _, *args = exp
285
+ args.map! {|sub_tree| process sub_tree}
286
+ end
287
+
288
+ def process_sclass exp
289
+ _, *args = exp
290
+ args.map! {|sub_tree| process sub_tree}
291
+ end
292
+
293
+ def process_next exp
294
+ _ = exp
295
+ end
296
+
297
+ def process_module exp
298
+ _, module_name, *args = exp
299
+ if module_name.class == Symbol
300
+ @module_names.push module_name.to_s
301
+ @classes << @module_names.join('::')
302
+ else
303
+ get_complete_class_name(module_name)
304
+ @classes << @complete_class_name.join('::')
305
+ @module_names.push @complete_class_name.join('::')
306
+ @complete_class_name = []
307
+ end
308
+ args.map! {|sub_tree| process sub_tree}
309
+ @module_names.pop
310
+ end
311
+
312
+ def process_to_ary exp
313
+ _, *args = exp
314
+ args.map! {|sub_tree| process sub_tree}
315
+ end
316
+
317
+ def process_while exp
318
+ _, condition, *args = exp
319
+ true_clause = args.pop
320
+ args.map! {|sub_tree| process sub_tree}
321
+ end
322
+
323
+ def process_cvdecl exp
324
+ _, variable_name, *args = exp
325
+ args.map! {|sub_tree| process sub_tree}
326
+ end
327
+
328
+ def process_cvar exp
329
+ _, variable_name = exp
330
+ end
331
+
332
+ def process_until exp
333
+ _, condition, *args = exp
334
+ true_clause = args.pop
335
+ args.map! {|sub_tree| process sub_tree}
336
+ end
337
+
338
+ def process_yield exp
339
+ _, *body = exp
340
+ if !body.empty?
341
+ body.map! {|sub_tree| process sub_tree}
342
+ end
343
+ end
344
+
345
+ def process_dot2 exp
346
+ _, first, second = exp
347
+ end
348
+
349
+ def process_zsuper exp
350
+ _ = exp
351
+ end
352
+
353
+ def process_op_asgn_or exp
354
+ _, first, second = exp
355
+ process first
356
+ process second
357
+ end
358
+
359
+ def process_match3 exp
360
+ _, regular_expression, *args = exp
361
+ args.map! {|sub_tree| process sub_tree}
362
+ end
363
+
364
+ def process_break exp
365
+ _ = exp
366
+ end
367
+
368
+ def process_dregx exp
369
+ _, regex = exp
370
+ end
371
+
372
+ def process_super exp
373
+ _, args = exp
374
+ process args
375
+ end
376
+
377
+ def process_ensure exp
378
+ _, rescue_clause, *ensure_clause = exp
379
+ process rescue_clause
380
+ ensure_clause.map! {|sub_tree| process sub_tree}
381
+ end
382
+
383
+ def process_op_asgn2 exp
384
+ _, left_assign, variable, method, args = exp
385
+ process left_assign
386
+ process args
387
+ end
388
+
389
+ def process_splat exp
390
+ _, left_assign = exp
391
+ process left_assign
392
+ end
393
+
394
+ def process_dxstr exp
395
+ # shelling out
396
+ _ = exp
397
+ end
398
+
399
+ def process_dot3 exp
400
+ _ = exp
401
+ end
402
+
403
+ def ruby_parser
404
+ RubyParser.new
405
+ end
406
+ end
407
+
408
+ end
409
+ end
@@ -0,0 +1,22 @@
1
+ module Archruby
2
+ module Ruby
3
+ STD_LIB_NAME = 'ruby_str_lib'
4
+ STD_LIBRARY_CLASSES = [
5
+ 'MAbbrev', 'Base64', 'Benchmark', 'BigDecimal', 'BigMath', 'Jacobian',
6
+ 'LUSolve', 'Newton', 'CGI', 'Coverage','CSV', 'Curses', 'FileViewer', 'Date',
7
+ 'DateTime', 'DBM', 'DBMError', 'SimpleDelegator', 'Delegator', 'Digest',
8
+ 'DL', 'ACL', 'DRb', 'E2MM', 'English', 'ERB', 'Etc', 'RbConfig', 'FileUtils',
9
+ 'Fcntl', 'Fiddle', 'FileUtils', 'Find', 'Forwardable', 'SingleForwardable',
10
+ 'GDBM', 'GDBMError', 'GDBMFatalError', 'GetoptLong', 'GServer', 'IPAddr', 'IRB', 'JSON',
11
+ 'Logger', 'Matrix', 'Vector', 'MiniTest', 'MakeMakefile', 'Monitor', 'MonitorMixin', 'Mutex_m',
12
+ 'Net', 'NKF', 'Kconv', 'Observable', 'OpenURI', 'URI', 'Open3', 'OpenSSL', 'OptionParser', 'OpenStruct',
13
+ 'Pathname', 'PP', 'PrettyPrint', 'Prime', 'PStore', 'Psych', 'PTY', 'Racc', 'Rake', 'RDoc',
14
+ 'Readline', 'Resolv', 'IPSocket', 'TCPSocket', 'UDPSocket', 'SOCKSSocket', 'REXML', 'Rinda',
15
+ 'Ripper', 'RSS', 'Gem', 'Scanf', 'SDBM', 'SDBMError', 'SecureRandom', 'Set', 'SortedSet', 'Shell',
16
+ 'Shellwords', 'Singleton', 'UNIXServer', 'UNIXSocket', 'TCPServer', 'BasicSocket', 'Socket',
17
+ 'StringIO', 'StringScanner', 'Sync', 'Syslog', 'Tempfile', 'ConditionVariable', 'Queue',
18
+ 'SizedQueue', 'ThWait', 'Timeout', 'TSort', 'WeakRef', 'WEBrick', 'XMLRPC', 'YAML',
19
+ 'Zlib', 'Iconv'
20
+ ]
21
+ end
22
+ end