pretentious 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5f2d6ae04a184a2d01faa3d4b57870c670ed7a2d
4
- data.tar.gz: e901c224433743d694beae8e5824dd79dbda0e12
3
+ metadata.gz: 573e7785c064f86ac8001339041dbb8387cb6679
4
+ data.tar.gz: aae975ba4c83fba283e0758a456674b0c5f0b86d
5
5
  SHA512:
6
- metadata.gz: f03e00d1f288a00205e8aa7318bf8abf90262ecd534d6ccf292d54014706147eb679a4a4859d4a339c8a877b08012b691dbc104728229d0f1472126abc7b0b00
7
- data.tar.gz: 6be334899e32a59c1f5930ea885d40a7639c74623de6a19b63f017dc02838ae2130343288fcb3d372667fbf16c108fb367af5289a179095bca38f367653de7aa
6
+ metadata.gz: fb6534fe86d6865035b3f5e160275dbdd194094920afeba24157820a1a0fcd87c78cb78246fe8139440369b96b4120f201c27a9af58724c7a20b7876f7538e77
7
+ data.tar.gz: dd0b37c00a1375b4323dd3041c9f0ed866499a3b38a58c86b9b03cd9631fd254a76d7acd6c7c73a7def5ea6e303ce7e059bf303394e01968546b0fc6dc4de0d6
data/README.md CHANGED
@@ -210,6 +210,9 @@ RSpec.describe Digest::MD5 do
210
210
  end
211
211
  ```
212
212
 
213
+ Note: If your test subject is already part of a larger application and would like to capture behavior in the manner that
214
+ the application uses it, please look at [Declarative Generation](#declarative-generation-without-using-example-files).
215
+
213
216
  ## Minitest
214
217
 
215
218
  The minitest test framework is also supported, simply use Pretentious.minitest_for instead
@@ -256,14 +259,16 @@ modifying source codes. This is useful for testing code embedded inside framewor
256
259
  "example" is already embedded inside existing code.
257
260
 
258
261
  For example lets say you want to generate tests for UserAuthenticaion that is used inside the
259
- login method inside the UsersController inside a rails app. You'd simply define like below:
262
+ login method inside the UsersController inside a Rails app. You'd simply define like below:
260
263
 
261
264
 
262
265
  ```ruby
263
266
  # initializers/pretentious.rb
264
267
 
265
- Pretentious.on(UsersController).method_called(:login).spec_for(UserAuthentication) #RSPEC
266
- Pretentious.on(UsersController).method_called(:login, :logout, ...).minitest_for(UserAuthentication) #minitest
268
+ if Rails.env.test? #IMPORTANT don't run this when you don't need it!
269
+ Pretentious.on(UsersController).method_called(:login).spec_for(UserAuthentication) #RSPEC
270
+ Pretentious.on(UsersController).method_called(:login, :logout, ...).minitest_for(UserAuthentication) #minitest
271
+ end
267
272
 
268
273
  # spec files will be written to the project root
269
274
  ```
@@ -279,13 +284,17 @@ You can pass a block for manually handling the output, for example
279
284
  ```ruby
280
285
  # initializers/pretentious.rb
281
286
 
282
- Pretentious.on(UsersController).method_called(:login).spec_for(UserAuthentication) do |results|
283
- puts results[UserAuthentication][:output]
287
+ if Rails.env.test? #IMPORTANT don't run this when you don't need it!
288
+ Pretentious.on(UsersController).method_called(:login).spec_for(UserAuthentication) do |results|
289
+ puts results[UserAuthentication][:output]
290
+ end
284
291
  end
285
292
 
286
293
  # spec files will be written to the project root
287
294
  ```
288
295
 
296
+ IMPORTANT: If using rails or if it is part of a larger app, make sure to enable this only when you intend to generate specs!
297
+ delete the initializer or comment the code out when it is not needed.
289
298
 
290
299
  ## Handling complex parameters and object constructors
291
300
 
data/bin/ddtgen CHANGED
@@ -3,54 +3,48 @@
3
3
  require 'pretentious'
4
4
  require 'optparse'
5
5
  require 'ripper'
6
- require "readline"
6
+ require 'readline'
7
7
  require 'json'
8
8
  require 'fileutils'
9
9
 
10
10
  # ddtgen example.rb -t rspec -o rspec/
11
11
  options = OptionParser.new do |o|
12
12
  o.banner =
13
- "Usage: ddtgen FILENAME [options] # Generates tests using the specified example file\n"
14
- o.separator ""
13
+ "Usage: ddtgen FILENAME [options] # Generates tests using the specified example file\n"
14
+ o.separator ''
15
15
  o.separator "options:"
16
- o.on('-o','--output-dir','folder to place the files in') { |b| $output_folder = b}
16
+ o.on('-o', '--output-dir', 'folder to place the files in') { |b| $output_folder = b}
17
17
  o.parse!
18
18
  end
19
19
 
20
-
21
20
  filename = ARGV[0]
22
21
 
23
22
  if filename.nil?
24
- puts "an example file is required."
23
+ puts 'an example file is required.'
25
24
  puts options
26
25
  exit(1)
27
26
  end
28
27
 
29
- example_body = ""
28
+ example_body = ''
30
29
 
31
30
  index = 0
32
31
  File.open(filename, "r") do |f|
33
32
  f.each_line do |line|
34
- example_body << "#{line}\n"
33
+ example_body << "#{line}\n"
35
34
  end
36
35
  end
37
36
 
38
37
  eval(example_body, binding, filename, 1)
39
38
 
40
- #collect results
41
-
42
-
43
- Pretentious.last_results.each { |g, result_per_generator|
39
+ # collect results
40
+ Pretentious.last_results.each do |g, result_per_generator|
44
41
  puts "#{g}:"
45
- result_per_generator.each { |klass, result|
42
+ result_per_generator.each do |klass, result|
46
43
  output_folder = result[:generator].location(output_folder)
47
44
  FileUtils.mkdir_p output_folder
48
45
  result[:generator].helper(output_folder)
49
46
  filename = result[:generator].naming(output_folder, klass)
50
- File.open(filename, 'w') {
51
- |f| f.write(result[:output])
52
- }
47
+ File.open(filename, 'w') { |f| f.write(result[:output]) }
53
48
  puts "#{filename}"
54
- }
55
- }
56
-
49
+ end
50
+ end
data/lib/pretentious.rb CHANGED
@@ -1,15 +1,15 @@
1
- require "pretentious/version"
2
- require "pretentious/generator_base"
3
- require "pretentious/rspec_generator"
4
- require "pretentious/minitest_generator"
5
- require "pretentious/recorded_proc"
6
- require "pretentious/generator"
1
+ require 'pretentious/version'
2
+ require 'pretentious/context'
3
+ require 'pretentious/generator_base'
4
+ require 'pretentious/rspec_generator'
5
+ require 'pretentious/minitest_generator'
6
+ require 'pretentious/recorded_proc'
7
+ require 'pretentious/generator'
7
8
  require 'binding_of_caller'
8
9
  require 'pretentious/deconstructor'
9
10
  require 'pretentious/trigger'
10
11
 
11
12
  Class.class_eval do
12
-
13
13
  def _stub(*classes)
14
14
  @classes = classes
15
15
  self
@@ -18,11 +18,9 @@ Class.class_eval do
18
18
  def _get_mock_classes
19
19
  @classes
20
20
  end
21
-
22
21
  end
23
22
 
24
23
  Thread.class_eval do
25
-
26
24
  def _push_context(context)
27
25
  @_context ||= []
28
26
  @_context << context
@@ -42,25 +40,27 @@ Thread.class_eval do
42
40
  end
43
41
  end
44
42
 
43
+ # The main class to use for pretentious testing
45
44
  module Pretentious
46
-
45
+ # misc convenience tools
47
46
  module DdtUtils
48
47
  def self.to_underscore(str)
49
- str.gsub(/(.)([A-Z])/,'\1_\2').downcase
48
+ str.gsub(/(.)([A-Z])/, '\1_\2').downcase
50
49
  end
51
50
  end
52
51
 
53
-
54
52
  def self.spec_for(*klasses, &block)
55
53
  @spec_results ||= {}
56
54
  Pretentious::Generator.test_generator = Pretentious::RspecGenerator
57
- @spec_results.merge!(Pretentious::Generator.generate_for(*klasses, &block))
55
+ @spec_results.merge!(Pretentious::Generator
56
+ .generate_for(*klasses, &block))
58
57
  end
59
58
 
60
59
  def self.minitest_for(*klasses, &block)
61
60
  @minitest_results ||= {}
62
61
  Pretentious::Generator.test_generator = Pretentious::MinitestGenerator
63
- @minitest_results.merge!(Pretentious::Generator.generate_for(*klasses, &block))
62
+ @minitest_results.merge!(Pretentious::Generator
63
+ .generate_for(*klasses, &block))
64
64
  end
65
65
 
66
66
  def self.clear_results
@@ -69,7 +69,7 @@ module Pretentious
69
69
  end
70
70
 
71
71
  def self.last_results
72
- {spec: @spec_results, minitest: @minitest_results}
72
+ { spec: @spec_results, minitest: @minitest_results }
73
73
  end
74
74
 
75
75
  def self.install_watcher
@@ -80,23 +80,23 @@ module Pretentious
80
80
  Pretentious::Generator.unwatch_new_instances
81
81
  end
82
82
 
83
- def self.value_ize(value, let_variables, declared_names)
84
- if (value.kind_of? String)
85
- "#{value.dump}"
86
- elsif (value.is_a? Symbol)
87
- ":#{value.to_s}"
88
- elsif (value.is_a? Hash)
89
- Pretentious::Deconstructor.pick_name(let_variables, value.object_id, declared_names)
90
- elsif (value.is_a? Pretentious::RecordedProc)
91
- Pretentious::Deconstructor.pick_name(let_variables, value.target_proc.object_id, declared_names)
92
- elsif (value == nil)
93
- "nil"
94
- elsif Pretentious::Deconstructor.is_primitive?(value)
95
- "#{value.to_s}"
96
- elsif let_variables && let_variables[value.object_id]
97
- Pretentious::Deconstructor.pick_name(let_variables, value.object_id, declared_names)
83
+ def self.value_ize(context, value)
84
+ if value.is_a? String
85
+ "'#{value}'"
86
+ elsif value.is_a? Symbol
87
+ ":#{value}"
88
+ elsif value.is_a? Hash
89
+ context.pick_name(value.object_id)
90
+ elsif value.is_a? Pretentious::RecordedProc
91
+ context.pick_name(value.target_proc.object_id)
92
+ elsif value.nil?
93
+ 'nil'
94
+ elsif Pretentious::Deconstructor.primitive?(value)
95
+ "#{value}"
96
+ elsif context.variable_map && context.variable_map[value.object_id]
97
+ context.pick_name(value.object_id)
98
98
  else
99
- "#{value.to_s}"
99
+ "#{value}"
100
100
  end
101
101
  end
102
102
 
@@ -0,0 +1,86 @@
1
+ module Pretentious
2
+ # Contains references to scoped variables
3
+ class Context
4
+ attr_accessor :declared_names, :variable_map,
5
+ :previous_declarations
6
+
7
+ def initialize(variable_map = {}, declared_names = {}, previous_declarations = {})
8
+ @declared_names = declared_names
9
+ @variable_map = variable_map
10
+ @previous_declarations = previous_declarations
11
+ end
12
+
13
+ def subcontext(declarations)
14
+ previous_declarations = {}
15
+
16
+ declarations.select { |d| d[:used_by] != :inline }.each do |d|
17
+ previous_declarations[d[:id]] = pick_name(d[:id])
18
+ end
19
+
20
+ Pretentious::Context.new(@variable_map, {}, previous_declarations)
21
+ end
22
+
23
+ def was_declared_previously?(object_id)
24
+ @previous_declarations.key? object_id
25
+ end
26
+
27
+ def merge_variable_map(target_object)
28
+ @variable_map.merge!(target_object._variable_map) if target_object.methods.include?(:_variable_map) && !target_object._variable_map.nil?
29
+ end
30
+
31
+ def register_instance_variable(object_id)
32
+ @variable_map[object_id] = "@#{@previous_declarations[object_id]}" if @previous_declarations[object_id][0]!='@'
33
+ end
34
+
35
+ def register(object_id, name)
36
+ @variable_map[object_id] = name
37
+ end
38
+
39
+ def dump
40
+ puts "v-map #{@variable_map.inspect}"
41
+ puts "d-map #{@declared_names.inspect}"
42
+ puts "p-map #{@previous_declarations.inspect}"
43
+ end
44
+
45
+ def pick_name(object_id, value = :no_value_passed)
46
+ var_name = "var_#{object_id}"
47
+
48
+ object_id_to_declared_names = {}
49
+
50
+ if @declared_names
51
+ @declared_names.each { |k, v| object_id_to_declared_names[v[:object_id]] = k if v }
52
+ end
53
+ # return immediately if already mapped
54
+ return object_id_to_declared_names[object_id] if object_id_to_declared_names.include? object_id
55
+
56
+ if !@variable_map.nil? && @variable_map.include?(object_id)
57
+
58
+ candidate_name = @variable_map[object_id].to_s
59
+ if !@declared_names.include?(candidate_name)
60
+ var_name = candidate_name
61
+ @declared_names[candidate_name] = { count: 1, object_id: object_id }
62
+ else
63
+
64
+ if @declared_names[candidate_name][:object_id] == object_id
65
+ var_name = candidate_name
66
+ else
67
+ new_name = "#{candidate_name}_#{@declared_names[candidate_name][:count]}"
68
+ var_name = "#{new_name}"
69
+
70
+ @declared_names[candidate_name][:count] += 1
71
+ @declared_names[new_name] = { count: 1, object_id: object_id }
72
+ end
73
+
74
+ end
75
+ else
76
+ return value_of(value) if value != :no_value_passed
77
+ end
78
+
79
+ var_name
80
+ end
81
+
82
+ def value_of(value)
83
+ Pretentious.value_ize(self, value)
84
+ end
85
+ end
86
+ end
@@ -1,446 +1,383 @@
1
- class Pretentious::Deconstructor
2
-
3
- class UnResolved
4
-
5
- attr_accessor :target_object
6
-
7
- def initialize(object)
8
- @target_object = object
1
+ module Pretentious
2
+ # Deconstructor - decompose an object into its parts
3
+ class Deconstructor
4
+ # Represents an unresolved class
5
+ class UnResolved
6
+ attr_accessor :target_object
7
+
8
+ def initialize(object)
9
+ @target_object = object
10
+ end
9
11
  end
10
- end
11
-
12
- class Reference
13
- attr_accessor :tree
14
12
 
15
- def initialize(tree)
16
- @tree = tree
17
- end
18
- end
13
+ # Represents a reference
14
+ class Reference
15
+ attr_accessor :tree
19
16
 
20
- def dfs_array(arr, refs)
21
- value = []
22
- arr.each { |v|
23
- if Pretentious::Deconstructor.is_primitive?(v)
24
- value << v
25
- elsif v.is_a? Hash
26
- value << dfs_hash(v, refs)
27
- elsif v.is_a? Array
28
- value << dfs_array(v, refs)
29
- elsif v.is_a? Reference
30
- refs << v.tree[:id]
31
- value << Reference.new(dfs(v.tree))
32
- elsif value << v
17
+ def initialize(tree)
18
+ @tree = tree
33
19
  end
34
- }
35
- value
36
- end
20
+ end
37
21
 
38
- def dfs_hash(hash, refs)
39
- value = {}
40
- hash.each { |k, v|
41
- if Pretentious::Deconstructor.is_primitive?(v)
42
- value[k] = v
43
- elsif v.is_a? Hash
44
- value[k] = dfs_hash(v, refs)
45
- elsif v.is_a? Array
46
- value[k] = dfs_array(v, refs)
47
- elsif v.is_a? Reference
48
- refs << v.tree[:id]
49
- value[k] = Reference.new(dfs(v.tree))
50
- else
51
- value[k] = v
22
+ def dfs_array(arr, refs)
23
+ value = []
24
+ arr.each do |v|
25
+ if Pretentious::Deconstructor.primitive?(v)
26
+ value << v
27
+ elsif v.is_a? Hash
28
+ value << dfs_hash(v, refs)
29
+ elsif v.is_a? Array
30
+ value << dfs_array(v, refs)
31
+ elsif v.is_a? Reference
32
+ refs << v.tree[:id]
33
+ value << Reference.new(dfs(v.tree))
34
+ elsif value << v
35
+ end
52
36
  end
53
- }
54
- value
55
- end
37
+ value
38
+ end
56
39
 
57
- def dfs(tree)
58
- if !tree.is_a? Hash
59
- value = tree
60
- definition = {id: value.object_id, class: tree.class, value: value, used_by: []}
61
- unless (@dependencies.include? value.object_id)
62
- @dependencies[value.object_id] = definition
63
- @declaration_order << definition
40
+ def dfs_hash(hash, refs)
41
+ value = {}
42
+ hash.each do |k, v|
43
+ if Pretentious::Deconstructor.primitive?(v)
44
+ value[k] = v
45
+ elsif v.is_a? Hash
46
+ value[k] = dfs_hash(v, refs)
47
+ elsif v.is_a? Array
48
+ value[k] = dfs_array(v, refs)
49
+ elsif v.is_a? Reference
50
+ refs << v.tree[:id]
51
+ value[k] = Reference.new(dfs(v.tree))
52
+ else
53
+ value[k] = v
54
+ end
64
55
  end
65
- value.object_id
66
- else
67
- ref = []
68
-
69
- definition = {id: tree[:id], class: tree[:class], params_types: tree[:params_types], used_by: []}
56
+ value
57
+ end
70
58
 
71
- if tree[:class] == Hash
72
- definition[:value] = dfs_hash(tree[:composition], ref)
73
- elsif tree[:class] == Array
74
- definition[:value] = dfs_array(tree[:composition], ref)
75
- elsif tree[:class] == Pretentious::RecordedProc
76
- definition[:recorded_proc] = tree[:recorded_proc]
59
+ def dfs(tree)
60
+ if !tree.is_a? Hash
61
+ value = tree
62
+ definition = { id: value.object_id,
63
+ class: tree.class,
64
+ value: value,
65
+ used_by: [] }
66
+ unless @dependencies.include? value.object_id
67
+ @dependencies[value.object_id] = definition
68
+ @declaration_order << definition
69
+ end
70
+ value.object_id
71
+ else
72
+ ref = []
73
+
74
+ definition = { id: tree[:id],
75
+ class: tree[:class],
76
+ params_types: tree[:params_types],
77
+ used_by: [] }
78
+
79
+ if tree[:class] == Hash
80
+ definition[:value] = dfs_hash(tree[:composition], ref)
81
+ elsif tree[:class] == Array
82
+ definition[:value] = dfs_array(tree[:composition], ref)
83
+ elsif tree[:class] == Pretentious::RecordedProc
84
+ definition[:recorded_proc] = tree[:recorded_proc]
85
+
86
+ if !tree[:composition].nil?
87
+ ref << dfs(tree[:composition])
88
+ else
89
+ dfs(tree[:composition])
90
+ end
77
91
 
78
- if (!tree[:composition].nil?)
79
- ref << dfs(tree[:composition])
92
+ elsif tree[:composition].is_a? Array
93
+ tree[:composition].each { |t| ref << dfs(t) }
80
94
  else
81
- dfs(tree[:composition])
95
+ ref << dfs(tree[:composition])
82
96
  end
83
97
 
84
- elsif tree[:composition].is_a? Array
85
- tree[:composition].each { |t|
86
- ref << dfs(t)
87
- }
88
- else
89
- ref << dfs(tree[:composition])
90
- end
98
+ # evaluate given block composition
99
+ ref << dfs(tree[:block]) if tree[:block]
91
100
 
92
- #evaluate given block composition
93
- if (tree[:block])
94
- ref << dfs(tree[:block])
95
- end
101
+ definition[:ref] = ref
96
102
 
97
- definition[:ref] = ref
103
+ unless @dependencies.include? tree[:id]
104
+ @declaration_order << definition
105
+ @dependencies[tree[:id]] = definition
98
106
 
99
- unless (@dependencies.include? tree[:id])
100
- @declaration_order << definition
101
- @dependencies[tree[:id]] = definition
107
+ ref.each { |r| @dependencies[r][:used_by] << definition }
108
+ end
102
109
 
103
- ref.each { |r|
104
- @dependencies[r][:used_by] << definition
105
- }
110
+ tree[:id]
106
111
  end
107
-
108
- tree[:id]
109
112
  end
110
- end
111
113
 
112
- def update_ref_counts(params_arr, method_call)
113
- params_arr.each do |p|
114
- if (@dependencies.include? p.object_id)
115
- @dependencies[p.object_id][:used_by] << method_call
114
+ def update_ref_counts(params_arr, method_call)
115
+ params_arr.each do |p|
116
+ if @dependencies.include? p.object_id
117
+ @dependencies[p.object_id][:used_by] << method_call
118
+ end
116
119
  end
117
120
  end
118
- end
119
121
 
120
- def inline
121
- @dependencies.each { |id, definition|
122
- if (definition[:used_by].size == 1)
123
- if (definition.include?(:value) && self.class.is_primitive?(definition[:value]))
124
- ref = definition[:used_by][0]
125
- definition[:used_by] = :inline
126
- references = ref[:ref]
127
- if (references)
128
- new_ref = references.collect { |c| c == id ? definition : c}
129
- ref[:ref] = new_ref
130
- end
122
+ def inline
123
+ @dependencies.each do |id, definition|
124
+ next if definition[:used_by].size != 1
125
+ next if !definition.include?(:value) || !self.class.primitive?(definition[:value])
126
+ ref = definition[:used_by][0]
127
+ definition[:used_by] = :inline
128
+ references = ref[:ref]
129
+ if references
130
+ new_ref = references.collect { |c| c == id ? definition : c }
131
+ ref[:ref] = new_ref
131
132
  end
132
-
133
133
  end
134
- }
135
- end
136
-
137
- #creates a tree on how the object was created
138
- def build_tree(target_object)
139
- tree = {class: get_test_class(target_object), id: target_object.object_id, composition: []}
140
- if (target_object.is_a? Array)
141
- tree[:composition] = deconstruct_array(target_object)
142
- elsif target_object.is_a? Hash
143
- tree[:composition] = deconstruct_hash(target_object)
144
- elsif target_object.is_a? Pretentious::RecordedProc
145
- tree[:composition] = deconstruct_proc(target_object)
146
- tree[:given_block] = target_object.given_block?
147
- tree[:recorded_proc] = target_object
148
- tree[:id] = target_object.target_proc.object_id
149
- tree[:block_params] = self.class.block_param_names(target_object)
150
- elsif target_object.methods.include? :_get_init_arguments
151
- args = target_object._get_init_arguments
152
- unless args.nil?
153
- tree[:params_types] = args[:params_types]
154
- args[:params].each { |p|
155
- tree[:composition] << build_tree(p)
156
- }
157
-
158
- tree[:block] = build_tree(args[:block]) unless args[:block].nil?
159
- else
134
+ end
160
135
 
161
- if (self.class.is_primitive?(target_object))
162
- tree[:composition] = target_object
163
- elsif (target_object.class == File)
164
- tree[:composition] << build_tree(target_object.path)
136
+ # creates a tree on how the object was created
137
+ def build_tree(target_object)
138
+ tree = { class: get_test_class(target_object), id: target_object.object_id, composition: [] }
139
+ if target_object.is_a? Array
140
+ tree[:composition] = deconstruct_array(target_object)
141
+ elsif target_object.is_a? Hash
142
+ tree[:composition] = deconstruct_hash(target_object)
143
+ elsif target_object.is_a? Pretentious::RecordedProc
144
+ tree[:composition] = deconstruct_proc(target_object)
145
+ tree[:given_block] = target_object.given_block?
146
+ tree[:recorded_proc] = target_object
147
+ tree[:id] = target_object.target_proc.object_id
148
+ tree[:block_params] = self.class.block_param_names(target_object)
149
+ elsif target_object.methods.include? :_get_init_arguments
150
+ args = target_object._get_init_arguments
151
+ if args.nil?
152
+ if self.class.primitive?(target_object)
153
+ tree[:composition] = target_object
154
+ elsif target_object.class == File
155
+ tree[:composition] << build_tree(target_object.path)
156
+ else
157
+ tree[:composition] = UnResolved.new(target_object)
158
+ end
165
159
  else
166
- tree[:composition] = UnResolved.new(target_object)
160
+ tree[:params_types] = args[:params_types]
161
+ args[:params].each { |p| tree[:composition] << build_tree(p) }
162
+
163
+ tree[:block] = build_tree(args[:block]) unless args[:block].nil?
167
164
  end
168
- end
169
165
 
170
- else
171
- tree[:composition] = target_object
166
+ else
167
+ tree[:composition] = target_object
168
+ end
169
+ tree
172
170
  end
173
- tree
174
- end
175
171
 
172
+ def deconstruct(method_call_collection, *target_objects)
173
+ @declaration_order = []
174
+ @dependencies = {}
176
175
 
177
- def deconstruct(method_call_collection, *target_objects)
176
+ target_objects.each do |target_object|
177
+ tree = build_tree target_object
178
+ dfs(tree)
179
+ end
178
180
 
179
- @declaration_order = []
180
- @dependencies = {}
181
+ method_call_collection.each do |m|
182
+ update_ref_counts(m[:params], m)
183
+ end
181
184
 
182
- target_objects.each { |target_object|
183
- tree = build_tree target_object
184
- dfs(tree)
185
- }
185
+ inline
186
186
 
187
- method_call_collection.each do |m|
188
- update_ref_counts(m[:params], m)
187
+ { declaration: @declaration_order, dependency: @dependencies }
189
188
  end
190
189
 
191
- inline
192
-
193
- {declaration: @declaration_order, dependency: @dependencies}
194
- end
195
-
196
- def generate_declarations(variable_map = {}, previous_declarations = {}, method_call_collection = [], *target_objects)
197
- target_objects.each { |target_object|
198
- variable_map.merge!(target_object._variable_map) if target_object.methods.include?(:_variable_map) && !target_object._variable_map.nil?
199
- }
200
- deconstruct method_call_collection, *target_objects
201
- end
202
-
203
- def build_output(indentation_level, variable_map, declarations, declared_names, previous_declarations)
204
- output_buffer = ""
205
- indentation = ""
206
-
207
- indentation_level.times {
208
- indentation << ' '
209
- }
210
-
211
- declarations[:declaration].each do |d|
212
- if (d[:used_by] != :inline) && !previous_declarations.has_key?(d[:id])
213
- var_name = Pretentious::Deconstructor.pick_name(variable_map, d[:id], declared_names)
214
- output_buffer << "#{indentation}#{var_name} = #{construct(d, variable_map, declared_names, indentation)}\n"
215
- elsif (d[:used_by]!=:inline) && previous_declarations[d[:id]]
216
- variable_map[d[:id]] = "@#{previous_declarations[d[:id]]}" if previous_declarations[d[:id]][0]!='@'
190
+ def generate_declarations(context, method_call_collection, *target_objects)
191
+ target_objects.each do |target_object|
192
+ context.merge_variable_map(target_object)
217
193
  end
194
+ deconstruct method_call_collection, *target_objects
218
195
  end
219
- output_buffer
220
- end
221
196
 
222
- def deconstruct_to_ruby(indentation_level = 0, variable_map = {}, declared_names = {}, previous_declarations = {}, method_call_collection = [], *target_objects)
223
- declarations, dependencies = generate_declarations variable_map, previous_declarations, method_call_collection, *target_objects
224
- build_output(indentation_level, variable_map, declarations, declared_names, previous_declarations)
225
- end
226
-
227
- def self.is_primitive?(value)
228
- value.is_a?(String) || value.is_a?(Fixnum) || value.is_a?(TrueClass) || value.is_a?(FalseClass) ||
229
- value.is_a?(NilClass) || value.is_a?(Symbol) || value.is_a?(Class)
230
- end
197
+ def build_output(context, indentation_level, declarations)
198
+ output_buffer = ''
199
+ indentation = ''
200
+ indentation_level.times { indentation << ' ' }
201
+ declarations[:declaration].select { |d| d[:used_by] != :inline }.each do |d|
202
+ if !context.was_declared_previously?(d[:id])
203
+ var_name = context.pick_name(d[:id])
204
+ output_buffer << "#{indentation}#{var_name} = #{construct(context, d, indentation)}\n"
205
+ elsif context.was_declared_previously?(d[:id])
206
+ context.register_instance_variable(d[:id])
207
+ end
208
+ end
209
+ output_buffer
210
+ end
231
211
 
232
- def self.block_param_names(proc)
233
- parameters_to_join = []
212
+ def deconstruct_to_ruby(context, indentation_level = 0, *target_objects)
213
+ declarations, _dependencies = generate_declarations context, [], *target_objects
214
+ build_output(context, indentation_level, declarations)
215
+ end
234
216
 
235
- parameters = proc.target_proc.parameters
217
+ def self.primitive?(value)
218
+ value.is_a?(String) || value.is_a?(Fixnum) || value.is_a?(TrueClass) || value.is_a?(FalseClass) ||
219
+ value.is_a?(NilClass) || value.is_a?(Symbol) || value.is_a?(Class)
220
+ end
236
221
 
237
- parameters.each { |p|
238
- parameters_to_join << p[1].to_s
239
- }
240
- parameters_to_join
241
- end
222
+ def self.block_param_names(proc)
223
+ parameters_to_join = []
242
224
 
243
- def self.block_params_generator(proc, separator = '|')
225
+ parameters = proc.target_proc.parameters
244
226
 
245
- if (proc.target_proc.parameters.size > 0)
246
- return "#{separator}#{block_param_names(proc).join(', ')}#{separator}"
227
+ parameters.each { |p| parameters_to_join << p[1].to_s }
228
+ parameters_to_join
247
229
  end
248
230
 
249
- return ''
250
- end
231
+ def self.block_params_generator(proc, separator = '|')
232
+ if proc.target_proc.parameters.size > 0
233
+ return "#{separator}#{block_param_names(proc).join(', ')}#{separator}"
234
+ end
251
235
 
252
- def proc_to_ruby(proc, let_variables, declared, indentation = '')
253
- output_buffer = ""
254
- output_buffer << "Proc.new { #{self.class.block_params_generator(proc)}\n"
255
- output_buffer << self.class.proc_body(proc, let_variables, declared, indentation)
256
- output_buffer << "#{indentation}}\n"
257
- output_buffer
258
- end
236
+ ''
237
+ end
259
238
 
260
- def self.proc_body(proc, let_variables, declared,indentation = '')
261
- if (proc.return_value.size == 1)
262
- "#{indentation * 2}#{Pretentious::value_ize(proc.return_value[0], let_variables, declared)}\n"
263
- else
264
- "#{indentation * 2}\# Variable return values ... can't figure out what goes in here...\n"
239
+ def proc_to_ruby(context, proc, indentation = '')
240
+ output_buffer = ''
241
+ output_buffer << "proc { #{self.class.block_params_generator(proc)}\n"
242
+ output_buffer << self.class.proc_body(context, proc, indentation)
243
+ output_buffer << "#{indentation}}\n"
244
+ output_buffer
265
245
  end
266
- end
267
246
 
268
- def deconstruct_array(array)
269
- composition = []
270
- array.each { |v|
271
- if (Pretentious::Deconstructor.is_primitive?(v))
272
- composition << v
273
- elsif v.is_a? Hash
274
- composition << deconstruct_hash(v)
275
- elsif v.is_a? Array
276
- composition << deconstruct_array(v)
247
+ def self.proc_body(context, proc, indentation = '')
248
+ if proc.return_value.size == 1
249
+ "#{indentation} #{context.value_of(proc.return_value[0])}\n"
277
250
  else
278
- composition << Reference.new(build_tree(v))
251
+ "#{indentation} \# Variable return values ... can't figure out what goes in here...\n"
279
252
  end
280
- }
281
- composition
282
- end
253
+ end
283
254
 
284
- def deconstruct_hash(hash)
285
- composition = {}
286
- hash.each { |k, v|
287
- if (Pretentious::Deconstructor.is_primitive?(v))
288
- composition[k] = v
289
- elsif v.is_a? Hash
290
- composition[k] = deconstruct_hash(v)
291
- elsif v.is_a? Array
292
- composition[k] = deconstruct_array(v)
293
- else
294
- composition[k] = Reference.new(build_tree(v))
255
+ def deconstruct_array(array)
256
+ composition = []
257
+ array.each do |v|
258
+ if Pretentious::Deconstructor.primitive?(v)
259
+ composition << v
260
+ elsif v.is_a? Hash
261
+ composition << deconstruct_hash(v)
262
+ elsif v.is_a? Array
263
+ composition << deconstruct_array(v)
264
+ else
265
+ composition << Reference.new(build_tree(v))
266
+ end
295
267
  end
296
- }
297
- composition
298
- end
299
-
300
- def deconstruct_proc(proc)
301
- if (proc.return_value.size == 1)
302
- return build_tree(proc.return_value[0]) unless proc.return_value[0].nil?
303
- return nil
304
- else
305
- nil
268
+ composition
306
269
  end
307
- end
308
-
309
- def get_test_class(target_object)
310
- target_object.respond_to?(:test_class) ? target_object.test_class : target_object.class
311
- end
312
-
313
-
314
- def self.pick_name(variable_map, object_id, declared_names = {}, value = :no_value_passed)
315
- var_name = "var_#{object_id}"
316
270
 
317
- object_id_to_declared_names = {}
318
-
319
- declared_names.each { |k,v|
320
- object_id_to_declared_names[v[:object_id]] = k if v
321
- } if declared_names
322
-
323
- #return immediately if already mapped
324
- return object_id_to_declared_names[object_id] if (object_id_to_declared_names.include? object_id)
325
-
326
- if (!variable_map.nil? && variable_map.include?(object_id))
327
-
328
- candidate_name = variable_map[object_id].to_s
329
- if !declared_names.include?(candidate_name)
330
- var_name = candidate_name
331
- declared_names[candidate_name] = {count: 1, object_id: object_id}
332
- else
333
-
334
- if (declared_names[candidate_name][:object_id] == object_id)
335
- var_name = candidate_name
271
+ def deconstruct_hash(hash)
272
+ composition = {}
273
+ hash.each do |k, v|
274
+ if Pretentious::Deconstructor.primitive?(v)
275
+ composition[k] = v
276
+ elsif v.is_a? Hash
277
+ composition[k] = deconstruct_hash(v)
278
+ elsif v.is_a? Array
279
+ composition[k] = deconstruct_array(v)
336
280
  else
337
- new_name = "#{candidate_name}_#{declared_names[candidate_name][:count]}"
338
- var_name = "#{new_name}"
339
-
340
- declared_names[candidate_name][:count]+=1
341
- declared_names[new_name] = {count: 1, object_id: object_id}
281
+ composition[k] = Reference.new(build_tree(v))
342
282
  end
343
-
344
- end
345
- else
346
- if value != :no_value_passed
347
- return Pretentious::value_ize(value, let_variables, declared_names)
348
283
  end
284
+ composition
349
285
  end
350
286
 
351
- var_name
352
- end
353
-
354
- private
287
+ def deconstruct_proc(proc)
288
+ return nil if proc.return_value.size != 1
289
+ return build_tree(proc.return_value[0]) unless proc.return_value[0].nil?
290
+ end
355
291
 
292
+ def get_test_class(target_object)
293
+ target_object.respond_to?(:test_class) ? target_object.test_class : target_object.class
294
+ end
356
295
 
357
- def output_array(arr, variable_map, declared_names)
358
- output_buffer = '['
359
- array_elements = []
360
- arr.each { |v|
361
- value = Pretentious::value_ize(v, variable_map, declared_names)
362
- if (v.is_a? Hash)
363
- value = output_hash(v, variable_map, declared_names)
364
- elsif (v.is_a? Array)
365
- value = output_array(v, variable_map, declared_names)
366
- elsif (v.is_a? Reference)
367
- value = Pretentious::Deconstructor.pick_name(variable_map, v.tree, declared_names)
296
+ private
297
+
298
+ def output_array(context, arr)
299
+ output_buffer = '['
300
+ array_elements = []
301
+ arr.each do |v|
302
+ value = Pretentious.value_ize(context, v)
303
+ if v.is_a? Hash
304
+ value = output_hash(context, v)
305
+ elsif v.is_a? Array
306
+ value = output_array(context, v)
307
+ elsif v.is_a? Reference
308
+ value = context.pick_name(v.tree)
309
+ end
310
+ array_elements << value
368
311
  end
369
- array_elements << value
370
- }
371
- output_buffer << array_elements.join(', ')
372
- output_buffer << ']'
373
- output_buffer
374
- end
312
+ output_buffer << array_elements.join(', ')
313
+ output_buffer << ']'
314
+ output_buffer
315
+ end
375
316
 
376
- def output_hash(hash, variable_map, declared_names)
377
- output_buffer = '{'
378
- hash_elements = []
379
- hash.each { |k, v|
380
- value = Pretentious::value_ize(v, variable_map, declared_names)
381
- if (v.is_a? Hash)
382
- value = output_hash(v, variable_map, declared_names)
383
- elsif (v.is_a? Array)
384
- value = output_array(v, variable_map, declared_names)
385
- elsif (v.is_a? Reference)
386
- value = Pretentious::Deconstructor.pick_name(variable_map, v.tree, declared_names)
387
- end
317
+ def output_hash(context, hash)
318
+ output_buffer = '{ '
319
+ hash_elements = []
320
+ hash.each do |k, v|
321
+ value = context.value_of(v)
322
+ if v.is_a? Hash
323
+ value = output_hash(context, v)
324
+ elsif v.is_a? Array
325
+ value = output_array(context, v)
326
+ elsif v.is_a? Reference
327
+ value = context.pick_name(v.tree)
328
+ end
388
329
 
389
- if (k.is_a? Symbol)
390
- hash_elements << "#{k}: #{value}"
391
- else
392
- hash_elements << "#{Pretentious::value_ize(k, variable_map, declared_names)} => #{value}"
330
+ if k.is_a? Symbol
331
+ hash_elements << "#{k}: #{value}"
332
+ else
333
+ hash_elements << "#{context.value_of(k)} => #{value}"
334
+ end
393
335
  end
394
- }
395
- output_buffer << hash_elements.join(', ')
396
- output_buffer << '}'
397
- output_buffer
398
- end
336
+ output_buffer << hash_elements.join(', ')
337
+ output_buffer << ' }'
338
+ output_buffer
339
+ end
399
340
 
400
- def construct(definition, variable_map, declared_names, indentation = '')
401
- if (definition.include? :value)
402
- if (definition[:value].is_a? Hash)
403
- output_hash(definition[:value], variable_map, declared_names)
404
- elsif (definition[:value].is_a? Array)
405
- output_array(definition[:value], variable_map, declared_names)
406
- elsif (definition[:value].is_a? UnResolved)
407
- 'nil #parameters unresolvable. cannot decompose'
341
+ def construct(context, definition, indentation = '')
342
+ if definition.include? :value
343
+ if definition[:value].is_a? Hash
344
+ output_hash(context, definition[:value])
345
+ elsif definition[:value].is_a? Array
346
+ output_array(context, definition[:value])
347
+ elsif definition[:value].is_a? UnResolved
348
+ 'nil #parameters unresolvable. cannot decompose'
349
+ else
350
+ context.value_of(definition[:value])
351
+ end
352
+ elsif definition[:class] == Pretentious::RecordedProc
353
+ proc_to_ruby(context, definition[:recorded_proc], indentation)
408
354
  else
409
- Pretentious::value_ize(definition[:value], variable_map, declared_names)
410
- end
411
- elsif (definition[:class] == Pretentious::RecordedProc)
412
- proc_to_ruby(definition[:recorded_proc], variable_map, declared_names, indentation)
413
- else
414
- params = []
415
- if (definition[:ref] && definition[:ref].size > 0)
416
-
417
- i = 0
418
- params_types = definition[:params_types]
419
- definition[:ref].each_with_index do |v, index|
420
-
421
- type = :param
422
- if (params_types)
423
- type = params_types[index][0]
424
- i+=1
425
- end
355
+ params = []
356
+ if definition[:ref] && definition[:ref].size > 0
357
+
358
+ i = 0
359
+ params_types = definition[:params_types]
360
+ definition[:ref].each_with_index do |v, index|
361
+ type = :param
362
+ if params_types
363
+ type = params_types[index][0]
364
+ i += 1
365
+ end
426
366
 
427
- #to inline?
428
- if (v.is_a? Hash)
429
- params << Pretentious::value_ize(v[:value], variable_map, declared_names)
430
- else
431
- if (type == :block)
432
- params << "&#{Pretentious::Deconstructor.pick_name(variable_map, v, declared_names)}"
367
+ # to inline?
368
+ if v.is_a? Hash
369
+ params << context.value_of(v[:value])
433
370
  else
434
- params << Pretentious::Deconstructor.pick_name(variable_map, v, declared_names)
371
+ params << (type == :block ? "&#{context.pick_name(v)}" : context.pick_name(v))
435
372
  end
436
373
  end
374
+ "#{definition[:class]}.new(#{params.join(', ')})"
375
+ else
376
+ "#{definition[:class]}.new"
437
377
  end
438
- "#{definition[:class]}.new(#{params.join(', ')})"
439
- else
440
- "#{definition[:class]}.new"
441
- end
442
378
 
379
+ end
443
380
  end
444
- end
445
381
 
446
- end
382
+ end
383
+ end