archruby 0.1.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 (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