transpec 1.8.0 → 1.9.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +1 -1
- data/CHANGELOG.md +6 -0
- data/README.md +106 -79
- data/README.md.erb +91 -73
- data/lib/transpec/cli.rb +1 -1
- data/lib/transpec/converter.rb +16 -5
- data/lib/transpec/syntax/allow.rb +4 -0
- data/lib/transpec/syntax/expect.rb +4 -0
- data/lib/transpec/syntax/have.rb +24 -13
- data/lib/transpec/syntax/method_stub.rb +42 -6
- data/lib/transpec/syntax/mixin/any_instance_block.rb +14 -5
- data/lib/transpec/syntax/mixin/expect_base.rb +6 -5
- data/lib/transpec/syntax/mixin/messaging_host.rb +17 -0
- data/lib/transpec/syntax/mixin/{allow_no_message.rb → no_message_allowance.rb} +5 -4
- data/lib/transpec/syntax/mixin/send.rb +0 -13
- data/lib/transpec/syntax/mixin/should_base.rb +7 -1
- data/lib/transpec/syntax/mixin/useless_and_return.rb +79 -0
- data/lib/transpec/syntax/operator_matcher.rb +20 -4
- data/lib/transpec/syntax/receive.rb +21 -6
- data/lib/transpec/syntax/should_receive.rb +14 -11
- data/lib/transpec/util.rb +46 -0
- data/lib/transpec/version.rb +1 -1
- data/spec/transpec/converter_spec.rb +60 -18
- data/spec/transpec/syntax/expect_spec.rb +41 -9
- data/spec/transpec/syntax/method_stub_spec.rb +99 -2
- data/spec/transpec/syntax/operator_matcher_spec.rb +19 -84
- data/spec/transpec/syntax/receive_spec.rb +231 -2
- data/spec/transpec/syntax/should_receive_spec.rb +38 -0
- data/spec/transpec/syntax/should_spec.rb +28 -39
- data/tasks/readme.rake +16 -2
- metadata +5 -3
data/lib/transpec/cli.rb
CHANGED
@@ -49,7 +49,7 @@ module Transpec
|
|
49
49
|
unless @configuration.skip_dynamic_analysis?
|
50
50
|
puts 'Copying the project for dynamic analysis...'
|
51
51
|
DynamicAnalyzer.new(rspec_command: @configuration.rspec_command) do |analyzer|
|
52
|
-
puts "Running dynamic analysis with command
|
52
|
+
puts "Running dynamic analysis with command #{analyzer.rspec_command.inspect}..."
|
53
53
|
runtime_data = analyzer.analyze(paths)
|
54
54
|
end
|
55
55
|
puts
|
data/lib/transpec/converter.rb
CHANGED
@@ -80,11 +80,11 @@ module Transpec
|
|
80
80
|
|
81
81
|
def process_expect(expect)
|
82
82
|
process_have(expect.have_matcher)
|
83
|
-
|
83
|
+
process_messaging_host(expect.receive_matcher)
|
84
84
|
end
|
85
85
|
|
86
86
|
def process_allow(allow)
|
87
|
-
|
87
|
+
process_messaging_host(allow.receive_matcher)
|
88
88
|
end
|
89
89
|
|
90
90
|
def process_should_receive(should_receive)
|
@@ -102,7 +102,7 @@ module Transpec
|
|
102
102
|
should_receive.expectize!(@configuration.negative_form_of_to)
|
103
103
|
end
|
104
104
|
|
105
|
-
|
105
|
+
process_messaging_host(should_receive)
|
106
106
|
end
|
107
107
|
|
108
108
|
def process_double(double)
|
@@ -122,9 +122,9 @@ module Transpec
|
|
122
122
|
method_stub.convert_deprecated_method!
|
123
123
|
end
|
124
124
|
|
125
|
-
method_stub.
|
125
|
+
method_stub.remove_no_message_allowance! if @configuration.convert_deprecated_method?
|
126
126
|
|
127
|
-
|
127
|
+
process_messaging_host(method_stub)
|
128
128
|
end
|
129
129
|
|
130
130
|
def process_be_boolean(be_boolean)
|
@@ -184,6 +184,17 @@ module Transpec
|
|
184
184
|
have.convert_to_standard_expectation!(@configuration.parenthesize_matcher_arg)
|
185
185
|
end
|
186
186
|
|
187
|
+
def process_messaging_host(messaging_host)
|
188
|
+
process_useless_and_return(messaging_host)
|
189
|
+
process_any_instance_block(messaging_host)
|
190
|
+
end
|
191
|
+
|
192
|
+
def process_useless_and_return(messaging_host)
|
193
|
+
return unless messaging_host
|
194
|
+
return unless configuration.convert_deprecated_method?
|
195
|
+
messaging_host.remove_useless_and_return!
|
196
|
+
end
|
197
|
+
|
187
198
|
def process_any_instance_block(messaging_host)
|
188
199
|
return unless messaging_host
|
189
200
|
return unless rspec_version.migration_term_of_any_instance_implementation_block?
|
data/lib/transpec/syntax/have.rb
CHANGED
@@ -20,11 +20,9 @@ module Transpec
|
|
20
20
|
|
21
21
|
attr_reader :expectation
|
22
22
|
|
23
|
-
def self.target_method?(
|
24
|
-
|
25
|
-
|
26
|
-
return false if have_receiver_node
|
27
|
-
[:have, :have_exactly, :have_at_least, :have_at_most].include?(have_method_name)
|
23
|
+
def self.target_method?(receiver_node, method_name)
|
24
|
+
receiver_node.nil? &&
|
25
|
+
[:have, :have_exactly, :have_at_least, :have_at_most].include?(method_name)
|
28
26
|
end
|
29
27
|
|
30
28
|
add_dynamic_analysis_request do |rewriter|
|
@@ -34,7 +32,7 @@ module Transpec
|
|
34
32
|
def convert_to_standard_expectation!(parenthesize_matcher_arg = true)
|
35
33
|
return if project_requires_collection_matcher?
|
36
34
|
replace(@expectation.subject_range, replacement_subject_source) if explicit_subject?
|
37
|
-
replace(
|
35
|
+
replace(matcher_range, replacement_matcher_source(parenthesize_matcher_arg))
|
38
36
|
register_record if explicit_subject?
|
39
37
|
end
|
40
38
|
|
@@ -42,16 +40,13 @@ module Transpec
|
|
42
40
|
@expectation.respond_to?(:subject_node)
|
43
41
|
end
|
44
42
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
43
|
+
alias_method :have_node, :node
|
44
|
+
alias_method :items_node, :parent_node
|
48
45
|
|
49
46
|
def size_node
|
50
47
|
have_node.children[2]
|
51
48
|
end
|
52
49
|
|
53
|
-
alias_method :items_node, :node
|
54
|
-
|
55
50
|
def items_method_has_arguments?
|
56
51
|
items_node.children.size > 2
|
57
52
|
end
|
@@ -107,10 +102,10 @@ module Transpec
|
|
107
102
|
if subject_is_owner_of_collection?
|
108
103
|
if collection_accessor_is_private?
|
109
104
|
source << ".send(#{collection_accessor.inspect}"
|
110
|
-
source << ", #{
|
105
|
+
source << ", #{collection_accessor_args_body_source}" if items_method_has_arguments?
|
111
106
|
source << ')'
|
112
107
|
else
|
113
|
-
source << ".#{collection_accessor}#{
|
108
|
+
source << ".#{collection_accessor}#{collection_accessor_args_parentheses_source}"
|
114
109
|
end
|
115
110
|
end
|
116
111
|
source << ".#{query_method}"
|
@@ -164,6 +159,22 @@ module Transpec
|
|
164
159
|
end
|
165
160
|
end
|
166
161
|
|
162
|
+
def matcher_range
|
163
|
+
expression_range.join(items_node.loc.expression)
|
164
|
+
end
|
165
|
+
|
166
|
+
def collection_accessor_args_parentheses_source
|
167
|
+
map = items_node.loc
|
168
|
+
range = map.selector.end.join(map.expression.end)
|
169
|
+
range.source
|
170
|
+
end
|
171
|
+
|
172
|
+
def collection_accessor_args_body_source
|
173
|
+
arg_nodes = items_node.children[2..-1]
|
174
|
+
range = arg_nodes.first.loc.expression.begin.join(arg_nodes.last.loc.expression.end)
|
175
|
+
range.source
|
176
|
+
end
|
177
|
+
|
167
178
|
def register_record
|
168
179
|
@report.records << HaveRecord.new(self)
|
169
180
|
end
|
@@ -2,15 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
4
|
require 'transpec/syntax/mixin/monkey_patch_any_instance'
|
5
|
-
require 'transpec/syntax/mixin/
|
6
|
-
require 'transpec/syntax/mixin/allow_no_message'
|
5
|
+
require 'transpec/syntax/mixin/messaging_host'
|
7
6
|
require 'transpec/util'
|
8
7
|
require 'English'
|
9
8
|
|
10
9
|
module Transpec
|
11
10
|
class Syntax
|
12
11
|
class MethodStub < Syntax
|
13
|
-
include Mixin::MonkeyPatchAnyInstance, Mixin::
|
12
|
+
include Mixin::MonkeyPatchAnyInstance, Mixin::MessagingHost, Util
|
14
13
|
|
15
14
|
# rubocop:disable LineLength
|
16
15
|
CLASSES_DEFINING_OWN_STUB_METHOD = [
|
@@ -84,6 +83,16 @@ module Transpec
|
|
84
83
|
register_record(:deprecated)
|
85
84
|
end
|
86
85
|
|
86
|
+
def remove_no_message_allowance!
|
87
|
+
return unless allow_no_message?
|
88
|
+
super
|
89
|
+
register_record(:no_message_allowance)
|
90
|
+
end
|
91
|
+
|
92
|
+
def remove_useless_and_return!
|
93
|
+
super && register_record(:useless_and_return)
|
94
|
+
end
|
95
|
+
|
87
96
|
def add_receiver_arg_to_any_instance_implementation_block!
|
88
97
|
super && register_record(:any_instance_block)
|
89
98
|
end
|
@@ -163,9 +172,13 @@ module Transpec
|
|
163
172
|
def register_record(conversion_type)
|
164
173
|
record_class = case conversion_type
|
165
174
|
when :deprecated
|
166
|
-
|
175
|
+
DeprecatedMethodRecord
|
176
|
+
when :no_message_allowance
|
177
|
+
NoMessageAllowanceRecord
|
178
|
+
when :useless_and_return
|
179
|
+
MonkeyPatchUselessAndReturnRecord
|
167
180
|
when :any_instance_block
|
168
|
-
|
181
|
+
MonkeyPatchAnyInstanceBlockRecord
|
169
182
|
else
|
170
183
|
AllowRecord
|
171
184
|
end
|
@@ -207,7 +220,7 @@ module Transpec
|
|
207
220
|
end
|
208
221
|
end
|
209
222
|
|
210
|
-
class
|
223
|
+
class DeprecatedMethodRecord < Record
|
211
224
|
def initialize(method_stub, *)
|
212
225
|
@method_stub = method_stub
|
213
226
|
end
|
@@ -223,6 +236,29 @@ module Transpec
|
|
223
236
|
syntax << '(:message)'
|
224
237
|
end
|
225
238
|
end
|
239
|
+
|
240
|
+
class NoMessageAllowanceRecord < Record
|
241
|
+
def initialize(method_stub, *)
|
242
|
+
@method_stub = method_stub
|
243
|
+
end
|
244
|
+
|
245
|
+
def original_syntax
|
246
|
+
syntax = base_syntax
|
247
|
+
syntax << '.any_number_of_times' if @method_stub.any_number_of_times?
|
248
|
+
syntax << '.at_least(0)' if @method_stub.at_least_zero?
|
249
|
+
syntax
|
250
|
+
end
|
251
|
+
|
252
|
+
def converted_syntax
|
253
|
+
base_syntax
|
254
|
+
end
|
255
|
+
|
256
|
+
private
|
257
|
+
|
258
|
+
def base_syntax
|
259
|
+
"obj.#{@method_stub.method_name}(:message)"
|
260
|
+
end
|
261
|
+
end
|
226
262
|
end
|
227
263
|
end
|
228
264
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'active_support/concern'
|
4
4
|
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/util'
|
5
6
|
|
6
7
|
module Transpec
|
7
8
|
class Syntax
|
@@ -24,9 +25,7 @@ module Transpec
|
|
24
25
|
|
25
26
|
def any_instance_block_node
|
26
27
|
return unless any_instance?
|
27
|
-
|
28
|
-
return node if node.block_type?
|
29
|
-
end
|
28
|
+
Util.each_backward_chained_node(node).find(&:block_type?)
|
30
29
|
end
|
31
30
|
|
32
31
|
class AnyInstanceBlockRecord < Record
|
@@ -35,11 +34,21 @@ module Transpec
|
|
35
34
|
end
|
36
35
|
|
37
36
|
def original_syntax
|
38
|
-
"
|
37
|
+
"#{base_syntax} { |arg| }"
|
39
38
|
end
|
40
39
|
|
41
40
|
def converted_syntax
|
42
|
-
"
|
41
|
+
"#{base_syntax} { |instance, arg| }"
|
42
|
+
end
|
43
|
+
|
44
|
+
def base_syntax
|
45
|
+
fail NotImplementedError
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class MonkeyPatchAnyInstanceBlockRecord < AnyInstanceBlockRecord
|
50
|
+
def base_syntax
|
51
|
+
"Klass.any_instance.#{@host.method_name}(:message)"
|
43
52
|
end
|
44
53
|
end
|
45
54
|
end
|
@@ -27,6 +27,10 @@ module Transpec
|
|
27
27
|
:expect
|
28
28
|
end
|
29
29
|
|
30
|
+
def method_name_for_instance
|
31
|
+
fail NotImplementedError
|
32
|
+
end
|
33
|
+
|
30
34
|
def positive?
|
31
35
|
to_method_name = to_node.children[1]
|
32
36
|
to_method_name == :to
|
@@ -34,11 +38,8 @@ module Transpec
|
|
34
38
|
|
35
39
|
def matcher_node
|
36
40
|
to_arg_node = to_node.children[2]
|
37
|
-
|
38
|
-
|
39
|
-
else
|
40
|
-
to_arg_node
|
41
|
-
end
|
41
|
+
Util.each_forward_chained_node(to_arg_node, :include_origin)
|
42
|
+
.select(&:send_type?).to_a.last
|
42
43
|
end
|
43
44
|
|
44
45
|
def block_node
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/any_instance_block'
|
5
|
+
require 'transpec/syntax/mixin/no_message_allowance'
|
6
|
+
require 'transpec/syntax/mixin/useless_and_return'
|
7
|
+
|
8
|
+
module Transpec
|
9
|
+
class Syntax
|
10
|
+
module Mixin
|
11
|
+
module MessagingHost
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
include Mixin::AnyInstanceBlock, Mixin::NoMessageAllowance, Mixin::UselessAndReturn
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'active_support/concern'
|
4
4
|
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/util'
|
5
6
|
require 'ast'
|
6
7
|
|
7
8
|
module Transpec
|
8
9
|
class Syntax
|
9
10
|
module Mixin
|
10
|
-
module
|
11
|
+
module NoMessageAllowance
|
11
12
|
extend ActiveSupport::Concern
|
12
13
|
include Send, ::AST::Sexp
|
13
14
|
|
@@ -15,7 +16,7 @@ module Transpec
|
|
15
16
|
any_number_of_times? || at_least_zero?
|
16
17
|
end
|
17
18
|
|
18
|
-
def
|
19
|
+
def remove_no_message_allowance!
|
19
20
|
remove_any_number_of_times!
|
20
21
|
remove_at_least_zero!
|
21
22
|
end
|
@@ -47,14 +48,14 @@ module Transpec
|
|
47
48
|
end
|
48
49
|
|
49
50
|
def any_number_of_times_node
|
50
|
-
|
51
|
+
Util.each_backward_chained_node(node) do |chained_node|
|
51
52
|
method_name = chained_node.children[1]
|
52
53
|
return chained_node if method_name == :any_number_of_times
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
57
|
def at_least_zero_node
|
57
|
-
|
58
|
+
Util.each_backward_chained_node(node) do |chained_node|
|
58
59
|
_, method_name, arg_node = *chained_node
|
59
60
|
next unless method_name == :at_least
|
60
61
|
return chained_node if arg_node == s(:int, 0)
|
@@ -107,19 +107,6 @@ module Transpec
|
|
107
107
|
def range_after_arg
|
108
108
|
arg_range.end.join(expression_range.end)
|
109
109
|
end
|
110
|
-
|
111
|
-
def each_chained_method_node
|
112
|
-
return to_enum(__method__) unless block_given?
|
113
|
-
|
114
|
-
@node.each_ancestor_node.reduce(@node) do |child_node, parent_node|
|
115
|
-
return unless [:send, :block].include?(parent_node.type)
|
116
|
-
return unless parent_node.children.first == child_node
|
117
|
-
yield parent_node, child_node
|
118
|
-
parent_node
|
119
|
-
end
|
120
|
-
|
121
|
-
nil
|
122
|
-
end
|
123
110
|
end
|
124
111
|
end
|
125
112
|
end
|
@@ -4,6 +4,7 @@ require 'active_support/concern'
|
|
4
4
|
require 'transpec/syntax/mixin/send'
|
5
5
|
require 'transpec/syntax/mixin/have_matcher_owner'
|
6
6
|
require 'transpec/syntax/operator_matcher'
|
7
|
+
require 'transpec/util'
|
7
8
|
|
8
9
|
module Transpec
|
9
10
|
class Syntax
|
@@ -25,7 +26,12 @@ module Transpec
|
|
25
26
|
end
|
26
27
|
|
27
28
|
def matcher_node
|
28
|
-
arg_node
|
29
|
+
if arg_node
|
30
|
+
Util.each_forward_chained_node(arg_node, :include_origin)
|
31
|
+
.select(&:send_type?).to_a.last
|
32
|
+
else
|
33
|
+
parent_node
|
34
|
+
end
|
29
35
|
end
|
30
36
|
|
31
37
|
def should_range
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/util'
|
6
|
+
|
7
|
+
module Transpec
|
8
|
+
class Syntax
|
9
|
+
module Mixin
|
10
|
+
module UselessAndReturn
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
include Send
|
13
|
+
|
14
|
+
def remove_useless_and_return!
|
15
|
+
return unless useless_and_return?
|
16
|
+
map = and_return_node.loc
|
17
|
+
and_return_range = map.dot.join(map.expression.end)
|
18
|
+
remove(and_return_range)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def useless_and_return?
|
23
|
+
return false unless and_return?
|
24
|
+
arg_node = and_return_node.children[2]
|
25
|
+
arg_node.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def and_return_with_block?
|
29
|
+
block_node = Util.block_node_taken_by_method(and_return_node)
|
30
|
+
!block_node.nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def and_return?
|
34
|
+
!and_return_node.nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
def and_return_node
|
38
|
+
return @and_return_node if instance_variable_defined?(:@and_return_node)
|
39
|
+
|
40
|
+
@and_return_node = Util.each_backward_chained_node(node) do |chained_node|
|
41
|
+
method_name = chained_node.children[1]
|
42
|
+
break chained_node if method_name == :and_return
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class UselessAndReturnRecord < Record
|
47
|
+
def initialize(host, *)
|
48
|
+
@host = host
|
49
|
+
end
|
50
|
+
|
51
|
+
def original_syntax
|
52
|
+
syntax = base_syntax
|
53
|
+
syntax << '.and_return'
|
54
|
+
syntax << ' { value }' if @host.and_return_with_block?
|
55
|
+
syntax
|
56
|
+
end
|
57
|
+
|
58
|
+
def converted_syntax
|
59
|
+
syntax = base_syntax
|
60
|
+
syntax << ' { value }' if @host.and_return_with_block?
|
61
|
+
syntax
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def base_syntax
|
67
|
+
fail NotImplementedError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class MonkeyPatchUselessAndReturnRecord < UselessAndReturnRecord
|
72
|
+
def base_syntax
|
73
|
+
"obj.#{@host.method_name}(:message)"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|