zapata 0.0.1

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 (132) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +3 -0
  4. data/CONTRIBUTING.md +5 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +22 -0
  7. data/README.md +152 -0
  8. data/Rakefile +2 -0
  9. data/bin/zapata +20 -0
  10. data/lib/zapata.rb +91 -0
  11. data/lib/zapata/analyst.rb +34 -0
  12. data/lib/zapata/core/collector.rb +9 -0
  13. data/lib/zapata/core/loader.rb +38 -0
  14. data/lib/zapata/core/reader.rb +10 -0
  15. data/lib/zapata/core/writer.rb +33 -0
  16. data/lib/zapata/db.rb +32 -0
  17. data/lib/zapata/diver.rb +81 -0
  18. data/lib/zapata/predictor/args.rb +94 -0
  19. data/lib/zapata/predictor/chooser.rb +27 -0
  20. data/lib/zapata/primitive/arg.rb +24 -0
  21. data/lib/zapata/primitive/array.rb +39 -0
  22. data/lib/zapata/primitive/base.rb +28 -0
  23. data/lib/zapata/primitive/basic.rb +22 -0
  24. data/lib/zapata/primitive/casgn.rb +15 -0
  25. data/lib/zapata/primitive/const.rb +15 -0
  26. data/lib/zapata/primitive/def.rb +33 -0
  27. data/lib/zapata/primitive/defs.rb +32 -0
  28. data/lib/zapata/primitive/hash.rb +31 -0
  29. data/lib/zapata/primitive/ivar.rb +6 -0
  30. data/lib/zapata/primitive/klass.rb +34 -0
  31. data/lib/zapata/primitive/lvar.rb +24 -0
  32. data/lib/zapata/primitive/missing.rb +17 -0
  33. data/lib/zapata/primitive/modul.rb +20 -0
  34. data/lib/zapata/primitive/nil.rb +16 -0
  35. data/lib/zapata/primitive/optarg.rb +18 -0
  36. data/lib/zapata/primitive/raw.rb +16 -0
  37. data/lib/zapata/primitive/send.rb +48 -0
  38. data/lib/zapata/primitive/sklass.rb +20 -0
  39. data/lib/zapata/primitive/var.rb +25 -0
  40. data/lib/zapata/printer.rb +93 -0
  41. data/lib/zapata/rzpec/runner.rb +67 -0
  42. data/lib/zapata/rzpec/writer.rb +115 -0
  43. data/lib/zapata/version.rb +3 -0
  44. data/spec/array_spec.rb +37 -0
  45. data/spec/definition_spec.rb +43 -0
  46. data/spec/hash_spec.rb +43 -0
  47. data/spec/klass_types_spec.rb +55 -0
  48. data/spec/send_spec.rb +31 -0
  49. data/spec/simple_types_spec.rb +90 -0
  50. data/spec/spec_helper.rb +124 -0
  51. data/spec/support/rails_test_app/.gitignore +16 -0
  52. data/spec/support/rails_test_app/.rspec +3 -0
  53. data/spec/support/rails_test_app/Gemfile +45 -0
  54. data/spec/support/rails_test_app/Gemfile.lock +200 -0
  55. data/spec/support/rails_test_app/README.md +3 -0
  56. data/spec/support/rails_test_app/Rakefile +6 -0
  57. data/spec/support/rails_test_app/app/assets/images/.keep +0 -0
  58. data/spec/support/rails_test_app/app/assets/javascripts/application.js +16 -0
  59. data/spec/support/rails_test_app/app/assets/stylesheets/application.css +15 -0
  60. data/spec/support/rails_test_app/app/controllers/application_controller.rb +5 -0
  61. data/spec/support/rails_test_app/app/controllers/concerns/.keep +0 -0
  62. data/spec/support/rails_test_app/app/helpers/application_helper.rb +2 -0
  63. data/spec/support/rails_test_app/app/mailers/.keep +0 -0
  64. data/spec/support/rails_test_app/app/models/.keep +0 -0
  65. data/spec/support/rails_test_app/app/models/concerns/.keep +0 -0
  66. data/spec/support/rails_test_app/app/models/robot_to_test.rb +49 -0
  67. data/spec/support/rails_test_app/app/models/test_array.rb +34 -0
  68. data/spec/support/rails_test_app/app/models/test_const.rb +14 -0
  69. data/spec/support/rails_test_app/app/models/test_definition.rb +38 -0
  70. data/spec/support/rails_test_app/app/models/test_float.rb +14 -0
  71. data/spec/support/rails_test_app/app/models/test_hash.rb +39 -0
  72. data/spec/support/rails_test_app/app/models/test_int.rb +14 -0
  73. data/spec/support/rails_test_app/app/models/test_send.rb +75 -0
  74. data/spec/support/rails_test_app/app/models/test_str.rb +14 -0
  75. data/spec/support/rails_test_app/app/models/test_sym.rb +14 -0
  76. data/spec/support/rails_test_app/app/models/testing_module/bare.rb +6 -0
  77. data/spec/support/rails_test_app/app/models/testing_module/klass_methods.rb +47 -0
  78. data/spec/support/rails_test_app/app/models/testing_module/nested/inside.rb +8 -0
  79. data/spec/support/rails_test_app/app/views/layouts/application.html.erb +14 -0
  80. data/spec/support/rails_test_app/config.ru +4 -0
  81. data/spec/support/rails_test_app/config/application.rb +23 -0
  82. data/spec/support/rails_test_app/config/boot.rb +4 -0
  83. data/spec/support/rails_test_app/config/database.yml +25 -0
  84. data/spec/support/rails_test_app/config/environment.rb +5 -0
  85. data/spec/support/rails_test_app/config/environments/development.rb +37 -0
  86. data/spec/support/rails_test_app/config/environments/production.rb +83 -0
  87. data/spec/support/rails_test_app/config/environments/test.rb +39 -0
  88. data/spec/support/rails_test_app/config/initializers/backtrace_silencers.rb +7 -0
  89. data/spec/support/rails_test_app/config/initializers/cookies_serializer.rb +3 -0
  90. data/spec/support/rails_test_app/config/initializers/filter_parameter_logging.rb +4 -0
  91. data/spec/support/rails_test_app/config/initializers/inflections.rb +16 -0
  92. data/spec/support/rails_test_app/config/initializers/mime_types.rb +4 -0
  93. data/spec/support/rails_test_app/config/initializers/session_store.rb +3 -0
  94. data/spec/support/rails_test_app/config/initializers/wrap_parameters.rb +14 -0
  95. data/spec/support/rails_test_app/config/locales/en.yml +23 -0
  96. data/spec/support/rails_test_app/config/routes.rb +56 -0
  97. data/spec/support/rails_test_app/config/secrets.yml +22 -0
  98. data/spec/support/rails_test_app/db/seeds.rb +7 -0
  99. data/spec/support/rails_test_app/lib/assets/.keep +0 -0
  100. data/spec/support/rails_test_app/lib/tasks/.keep +0 -0
  101. data/spec/support/rails_test_app/log/.keep +0 -0
  102. data/spec/support/rails_test_app/public/404.html +67 -0
  103. data/spec/support/rails_test_app/public/422.html +67 -0
  104. data/spec/support/rails_test_app/public/500.html +66 -0
  105. data/spec/support/rails_test_app/public/favicon.ico +0 -0
  106. data/spec/support/rails_test_app/public/robots.txt +5 -0
  107. data/spec/support/rails_test_app/spec/models/robot_to_test_spec.rb +33 -0
  108. data/spec/support/rails_test_app/spec/models/test_array_spec.rb +27 -0
  109. data/spec/support/rails_test_app/spec/models/test_const_spec.rb +11 -0
  110. data/spec/support/rails_test_app/spec/models/test_definition_spec.rb +31 -0
  111. data/spec/support/rails_test_app/spec/models/test_float_spec.rb +11 -0
  112. data/spec/support/rails_test_app/spec/models/test_hash_spec.rb +31 -0
  113. data/spec/support/rails_test_app/spec/models/test_int_spec.rb +11 -0
  114. data/spec/support/rails_test_app/spec/models/test_send_spec.rb +53 -0
  115. data/spec/support/rails_test_app/spec/models/test_str_spec.rb +11 -0
  116. data/spec/support/rails_test_app/spec/models/test_sym_spec.rb +11 -0
  117. data/spec/support/rails_test_app/spec/models/testing_module/bare_spec.rb +7 -0
  118. data/spec/support/rails_test_app/spec/models/testing_module/klass_methods_spec.rb +19 -0
  119. data/spec/support/rails_test_app/spec/models/testing_module/nested/inside_spec.rb +7 -0
  120. data/spec/support/rails_test_app/spec/rails_helper.rb +43 -0
  121. data/spec/support/rails_test_app/spec/spec_helper.rb +78 -0
  122. data/spec/support/rails_test_app/test/controllers/.keep +0 -0
  123. data/spec/support/rails_test_app/test/fixtures/.keep +0 -0
  124. data/spec/support/rails_test_app/test/helpers/.keep +0 -0
  125. data/spec/support/rails_test_app/test/integration/.keep +0 -0
  126. data/spec/support/rails_test_app/test/mailers/.keep +0 -0
  127. data/spec/support/rails_test_app/test/models/.keep +0 -0
  128. data/spec/support/rails_test_app/test/test_helper.rb +13 -0
  129. data/spec/support/rails_test_app/vendor/assets/javascripts/.keep +0 -0
  130. data/spec/support/rails_test_app/vendor/assets/stylesheets/.keep +0 -0
  131. data/zapata.gemspec +34 -0
  132. metadata +446 -0
@@ -0,0 +1,31 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Hash < Base
4
+ def node
5
+ body = @code
6
+ type = @code.type
7
+ OpenStruct.new(type: type, body: body)
8
+ end
9
+
10
+ def to_a
11
+ value.to_a.flatten
12
+ end
13
+
14
+ def dive_deeper
15
+ end
16
+
17
+ def to_raw
18
+ result = {}
19
+
20
+ node.body.to_a.each do |pair|
21
+ key_node, value_node = pair.to_a
22
+ key = Diver.dive(key_node).to_raw
23
+ value = Diver.dive(value_node).to_raw
24
+ result[key] = value
25
+ end
26
+
27
+ Raw.new(:hash, result)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,6 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Ivar < Basic
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,34 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Klass < Base
4
+ def initialize(code)
5
+ @code = code
6
+ @moduls = Diver.current_moduls.dup
7
+ Diver.access_level = :public
8
+ Diver.current_klass = self
9
+ dive_deeper
10
+ Diver.current_klass = nil
11
+ end
12
+
13
+ def parent_modul_names
14
+ @moduls.map { |mod| mod and mod.name }.compact
15
+ end
16
+
17
+ def node
18
+ const, inherited_from_klass, body = @code.to_a
19
+ immediate_modul, klass = const.to_a
20
+ chain = parent_modul_names + [immediate_modul, klass]
21
+ name = chain.compact.join('::')
22
+ type = @code.type
23
+
24
+ OpenStruct.new(
25
+ type: type,
26
+ immediate_modul: immediate_modul,
27
+ klass: klass,
28
+ name: name,
29
+ body: body
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Lvar < Base
4
+ def node
5
+ name = @code.to_a.first
6
+ type = @code.type
7
+ OpenStruct.new(type: type, name: name, body: @code)
8
+ end
9
+
10
+ def dive_deeper
11
+ end
12
+
13
+ def to_raw
14
+ chosen_value = Predictor::Args.choose_value(node.name, self)
15
+
16
+ if chosen_value.node.body == node.body
17
+ Raw.new(:missing, node.body.to_a.last)
18
+ else
19
+ chosen_value.to_raw
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,17 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Missing
4
+ def initialize(name)
5
+ @name = name
6
+ end
7
+
8
+ def node
9
+ OpenStruct.new(type: :missing)
10
+ end
11
+
12
+ def to_raw
13
+ Raw.new(:missing, @name)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Modul < Base
4
+ def initialize(code)
5
+ @code = code
6
+ Diver.current_moduls << self
7
+ dive_deeper
8
+ Diver.current_moduls.pop
9
+ end
10
+
11
+ def node
12
+ const, body = @code.to_a
13
+ modul, name = const.to_a
14
+ type = @code.type
15
+
16
+ OpenStruct.new(type: type, modul: modul, name: name, body: body)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Nil < Basic
4
+ def initialize
5
+ end
6
+
7
+ def node
8
+ OpenStruct.new(type: :nil)
9
+ end
10
+
11
+ def to_raw
12
+ Raw.new(:nil, nil)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Optarg < Base
4
+ def node
5
+ name, body = @code.to_a
6
+ type = @code.type
7
+ OpenStruct.new(type: type, name: name, body: body)
8
+ end
9
+
10
+ def dive_deeper
11
+ end
12
+
13
+ def to_raw
14
+ Diver.dive(node.body).to_raw
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Raw
4
+ attr_accessor :type, :value
5
+
6
+ def initialize(type, value)
7
+ @type = type
8
+ @value = value
9
+ end
10
+
11
+ def to_raw
12
+ self
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Send < Base
4
+ def initialize(code)
5
+ super
6
+
7
+ if node.name == :private
8
+ Diver.access_level = :private
9
+ elsif node.name == :protected
10
+ Diver.access_level = :protected
11
+ elsif node.name == :public
12
+ Diver.access_level = :public
13
+ end
14
+ end
15
+
16
+ def to_a
17
+ [value]
18
+ end
19
+
20
+ def node
21
+ receiver, name, args = @code.to_a
22
+ type = @code.type
23
+ OpenStruct.new(type: type, name: name, args: args, receiver: receiver)
24
+ end
25
+
26
+ def raw_receiver
27
+ return unless node.receiver
28
+ Diver.dive(node.receiver).to_raw
29
+ end
30
+
31
+ def to_raw
32
+ if raw_receiver and raw_receiver.type == :const
33
+ Raw.new(:const_send, "#{Printer.print(raw_receiver)}.#{node.name}#{Predictor::Args.literal(node.args)}")
34
+ elsif %i(+ - * /).include?(node.name)
35
+ Raw.new(:super, node.name)
36
+ else
37
+ predicted = Predictor::Args.choose_value(node.name, self).to_raw
38
+
39
+ if predicted.type == :missing
40
+ Raw.new(:super, node.name)
41
+ else
42
+ predicted
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Sklass < Base
4
+ def initialize(code)
5
+ @code = code
6
+
7
+ Diver.current_sklass = self
8
+ dive_deeper
9
+ Diver.current_sklass = nil
10
+ end
11
+
12
+ def node
13
+ receiver_self, body = @code.to_a
14
+ type = @code.type
15
+
16
+ OpenStruct.new(type: type, body: body)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ module Zapata
2
+ module Primitive
3
+ class Var < Base
4
+ def node
5
+ name, body = @code.to_a
6
+ type = @code.type
7
+ OpenStruct.new(type: type, name: name, body: body)
8
+ end
9
+
10
+ def literal
11
+ Diver.dive(node.body).literal
12
+ end
13
+
14
+ def to_raw
15
+ raw = Diver.dive(node.body).to_raw
16
+
17
+ if raw.type == :super
18
+ Missing.new(node.name).to_raw
19
+ else
20
+ raw
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,93 @@
1
+ module Zapata
2
+ class Printer
3
+ class << self
4
+ def print(raw)
5
+ case raw.type
6
+ when :const, :send, :int, :const_send, :literal, :float
7
+ raw.value
8
+ when :str
9
+ # decide which one to use
10
+ # "\"#{raw.value}\""
11
+ "'#{raw.value}'"
12
+ when :sym
13
+ ":#{raw.value}"
14
+ when :true
15
+ true
16
+ when :false
17
+ false
18
+ when :array
19
+ array(raw.value)
20
+ when :hash
21
+ hash(raw.value)
22
+ when :nil
23
+ 'nil'
24
+ when :missing
25
+ print(Primitive::Raw.new(:str, "Missing \"#{raw.value}\""))
26
+ when :ivar
27
+ RZpec::Writer.ivars << raw
28
+ to_var_name(raw.value)
29
+ else
30
+ raise "Not yet implemented #{raw}"
31
+ end
32
+ end
33
+
34
+ def array(given_array)
35
+ unnested_array = given_array.map { |el| unnest(el) }
36
+ "[#{unnested_array.join(', ')}]"
37
+ end
38
+
39
+ def args(given_args, klass)
40
+ return unless given_args.present?
41
+
42
+ if klass == Array
43
+ array_without_closers = given_args[1...-1]
44
+ return unless array_without_closers.present?
45
+
46
+ "(#{array_without_closers})"
47
+ elsif [Fixnum, Symbol].include?(klass)
48
+ "(#{given_args})"
49
+ elsif klass == Hash
50
+ "(#{given_args})"
51
+ else
52
+ raise "Not yet implemented"
53
+ end
54
+ end
55
+
56
+ def hash(obj)
57
+ unnested_hash = obj.each_with_object({}) do |(key, val), obj|
58
+ unnested_key = unnest(key)
59
+ unnested_val = unnest(val)
60
+ obj[unnested_key] = unnested_val
61
+ end
62
+
63
+ all_keys_symbols = unnested_hash.keys.all? do |key|
64
+ Parser::CurrentRuby.parse(key.to_s).type == :sym
65
+ end
66
+
67
+ values = unnested_hash.map do |key, val|
68
+ if all_keys_symbols
69
+ "#{key[1..-1]}: #{val}"
70
+ else
71
+ "#{key} => #{val}"
72
+ end
73
+ end
74
+
75
+ "{ #{values.join(', ')} }"
76
+ end
77
+
78
+ def unnest(raw)
79
+ return raw unless raw.respond_to?(:value)
80
+
81
+ if raw.value.is_a?(Primitive::Raw)
82
+ print(unnest(raw.value))
83
+ else
84
+ print(raw)
85
+ end
86
+ end
87
+
88
+ def to_var_name(name)
89
+ name.to_s.split('::').last.underscore.delete('@')
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,67 @@
1
+ module Zapata
2
+ module RZpec
3
+ class Runner
4
+ attr_reader :ran
5
+
6
+ def initialize(spec_filename)
7
+ @spec_filename = spec_filename
8
+ run
9
+ # silence { run }
10
+ end
11
+
12
+ def silence
13
+ original_stderr = $stderr.dup
14
+ original_stdout = $stdout.dup
15
+
16
+ $stdout.reopen('/dev/null', 'w')
17
+ $stdout.reopen('/dev/null', 'w')
18
+
19
+ yield
20
+
21
+ $stderr = original_stderr
22
+ $stdout = original_stdout
23
+ end
24
+
25
+ def methodz
26
+ examples.index_by { |ex| ex['description'].delete('#').to_sym }
27
+ end
28
+
29
+ def result_message(method_name)
30
+ methodz[method_name]['exception']['message']
31
+ end
32
+
33
+ def expected(method_name)
34
+ report_lines = result_message(method_name).to_s.split(/\n/)
35
+ expected_line = report_lines.detect { |line| line.match('got:') }
36
+
37
+ if expected_line
38
+ clean_expected_line = expected_line[10..-1]
39
+
40
+ if (matches = clean_expected_line.match(/\#\<(.+):(.+)\>/))
41
+ "'Returned instance object #{matches[1]}'"
42
+ else
43
+ Printer.print(Diver.dive(Parser::CurrentRuby.parse(clean_expected_line)).to_raw)
44
+ end
45
+ else
46
+ "'Exception in RSpec'"
47
+ end
48
+ end
49
+
50
+ def run
51
+ @ran = true
52
+
53
+ @stdin, @stdout, @stderr = Bundler.with_clean_env do
54
+ Open3.popen3("bundle exec rspec #{@spec_filename} --format j")
55
+ end
56
+ end
57
+
58
+ def examples
59
+ parsed_json_result['examples']
60
+ end
61
+
62
+ def parsed_json_result
63
+ @json ||= JSON.parse(@stdout.readlines.last)
64
+ end
65
+ end
66
+ end
67
+ end