transpec 0.2.6 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +10 -0
- data/README.md +111 -56
- data/README.md.erb +117 -62
- data/lib/transpec/ast/node.rb +41 -0
- data/lib/transpec/base_rewriter.rb +55 -0
- data/lib/transpec/cli.rb +43 -153
- data/lib/transpec/configuration.rb +13 -9
- data/lib/transpec/{rewriter.rb → converter.rb} +44 -71
- data/lib/transpec/dynamic_analyzer/rewriter.rb +94 -0
- data/lib/transpec/dynamic_analyzer/runtime_data.rb +27 -0
- data/lib/transpec/dynamic_analyzer.rb +166 -0
- data/lib/transpec/file_finder.rb +53 -0
- data/lib/transpec/option_parser.rb +166 -0
- data/lib/transpec/{context.rb → static_context_inspector.rb} +2 -2
- data/lib/transpec/syntax/be_close.rb +7 -9
- data/lib/transpec/syntax/double.rb +6 -10
- data/lib/transpec/syntax/expect.rb +35 -0
- data/lib/transpec/syntax/have.rb +195 -0
- data/lib/transpec/syntax/method_stub.rb +22 -27
- data/lib/transpec/syntax/mixin/allow_no_message.rb +73 -0
- data/lib/transpec/syntax/mixin/any_instance.rb +22 -0
- data/lib/transpec/syntax/mixin/expectizable.rb +26 -0
- data/lib/transpec/syntax/mixin/have_matcher.rb +23 -0
- data/lib/transpec/syntax/mixin/monkey_patch.rb +37 -0
- data/lib/transpec/syntax/mixin/send.rb +109 -0
- data/lib/transpec/syntax/{matcher.rb → operator_matcher.rb} +27 -14
- data/lib/transpec/syntax/raise_error.rb +6 -10
- data/lib/transpec/syntax/rspec_configure.rb +29 -28
- data/lib/transpec/syntax/should.rb +45 -15
- data/lib/transpec/syntax/should_receive.rb +44 -16
- data/lib/transpec/syntax.rb +29 -21
- data/lib/transpec/util.rb +12 -2
- data/lib/transpec/version.rb +3 -3
- data/spec/spec_helper.rb +8 -6
- data/spec/support/cache_helper.rb +50 -0
- data/spec/support/shared_context.rb +49 -1
- data/spec/transpec/ast/node_spec.rb +65 -0
- data/spec/transpec/cli_spec.rb +33 -242
- data/spec/transpec/commit_message_spec.rb +2 -2
- data/spec/transpec/configuration_spec.rb +12 -8
- data/spec/transpec/{rewriter_spec.rb → converter_spec.rb} +198 -148
- data/spec/transpec/dynamic_analyzer/rewriter_spec.rb +183 -0
- data/spec/transpec/dynamic_analyzer_spec.rb +164 -0
- data/spec/transpec/file_finder_spec.rb +118 -0
- data/spec/transpec/option_parser_spec.rb +185 -0
- data/spec/transpec/{context_spec.rb → static_context_inspector_spec.rb} +27 -12
- data/spec/transpec/syntax/be_close_spec.rb +8 -4
- data/spec/transpec/syntax/double_spec.rb +105 -12
- data/spec/transpec/syntax/expect_spec.rb +83 -0
- data/spec/transpec/syntax/have_spec.rb +599 -0
- data/spec/transpec/syntax/method_stub_spec.rb +276 -115
- data/spec/transpec/syntax/{matcher_spec.rb → operator_matcher_spec.rb} +277 -98
- data/spec/transpec/syntax/raise_error_spec.rb +92 -46
- data/spec/transpec/syntax/should_receive_spec.rb +298 -92
- data/spec/transpec/syntax/should_spec.rb +230 -44
- data/spec/transpec/util_spec.rb +2 -9
- data/tasks/lib/transpec_demo.rb +1 -1
- data/tasks/lib/transpec_test.rb +5 -7
- data/tasks/test.rake +5 -1
- data/transpec.gemspec +1 -1
- metadata +46 -22
- data/lib/transpec/syntax/able_to_allow_no_message.rb +0 -73
- data/lib/transpec/syntax/able_to_target_any_instance.rb +0 -24
- data/lib/transpec/syntax/expectizable.rb +0 -27
- data/lib/transpec/syntax/send_node_syntax.rb +0 -57
@@ -1,28 +1,39 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
|
-
require 'transpec/syntax/
|
5
|
-
require 'transpec/syntax/
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/syntax/mixin/monkey_patch'
|
6
|
+
require 'transpec/syntax/mixin/allow_no_message'
|
7
|
+
require 'transpec/syntax/mixin/any_instance'
|
6
8
|
require 'transpec/util'
|
7
9
|
require 'English'
|
8
10
|
|
9
11
|
module Transpec
|
10
12
|
class Syntax
|
11
13
|
class MethodStub < Syntax
|
12
|
-
include
|
14
|
+
include Mixin::Send, Mixin::MonkeyPatch, Mixin::AllowNoMessage, Mixin::AnyInstance, Util
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def self.target_method?(receiver_node, method_name)
|
17
|
+
!receiver_node.nil? && [:stub, :unstub, :stub!, :unstub!].include?(method_name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def register_request_for_dynamic_analysis(rewriter)
|
21
|
+
register_request_of_syntax_availability_inspection(
|
22
|
+
rewriter,
|
23
|
+
:allow_to_receive_available?,
|
24
|
+
[:allow, :receive]
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def allow_to_receive_available?
|
29
|
+
check_syntax_availability(__method__)
|
30
|
+
end
|
18
31
|
|
19
32
|
def allowize!
|
20
33
|
# There's no way of unstubbing in #allow syntax.
|
21
34
|
return unless [:stub, :stub!].include?(method_name)
|
22
35
|
|
23
|
-
|
24
|
-
|
25
|
-
unless context.allow_to_receive_available?
|
36
|
+
unless allow_to_receive_available?
|
26
37
|
fail InvalidContextError.new(selector_range, "##{method_name}", '#allow')
|
27
38
|
end
|
28
39
|
|
@@ -35,34 +46,18 @@ module Transpec
|
|
35
46
|
end
|
36
47
|
|
37
48
|
register_record(:allow)
|
38
|
-
|
39
|
-
@allowized = true
|
40
49
|
end
|
41
50
|
|
42
|
-
def
|
51
|
+
def convert_deprecated_method!
|
43
52
|
return unless replacement_method_for_deprecated_method
|
44
53
|
|
45
|
-
fail 'Already allowized, cannot replace deprecated method.' if @allowized
|
46
|
-
|
47
54
|
replace(selector_range, replacement_method_for_deprecated_method)
|
48
55
|
|
49
56
|
register_record(:deprecated)
|
50
|
-
|
51
|
-
@replaced_deprecated_method = true
|
52
57
|
end
|
53
58
|
|
54
59
|
private
|
55
60
|
|
56
|
-
def self.target_receiver_node?(node)
|
57
|
-
return false if node.nil?
|
58
|
-
const_name = Util.const_name(node)
|
59
|
-
!CLASSES_DEFINING_OWN_STUB_METHOD.include?(const_name)
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.target_method_names
|
63
|
-
[:stub, :unstub, :stub!, :unstub!]
|
64
|
-
end
|
65
|
-
|
66
61
|
def build_allow_expressions_from_hash_node(hash_node)
|
67
62
|
expressions = []
|
68
63
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Transpec
|
4
|
+
class Syntax
|
5
|
+
module Mixin
|
6
|
+
module AllowNoMessage
|
7
|
+
include ::AST::Sexp
|
8
|
+
|
9
|
+
def allow_no_message?
|
10
|
+
any_number_of_times? || at_least_zero?
|
11
|
+
end
|
12
|
+
|
13
|
+
def remove_allowance_for_no_message!
|
14
|
+
remove_any_number_of_times!
|
15
|
+
remove_at_least_zero!
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def any_number_of_times?
|
21
|
+
!any_number_of_times_node.nil?
|
22
|
+
end
|
23
|
+
|
24
|
+
def at_least_zero?
|
25
|
+
!at_least_zero_node.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
def remove_any_number_of_times!
|
29
|
+
return unless any_number_of_times?
|
30
|
+
remove_dot_and_method!(any_number_of_times_node)
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_at_least_zero!
|
34
|
+
return unless at_least_zero?
|
35
|
+
remove_dot_and_method!(at_least_zero_node)
|
36
|
+
end
|
37
|
+
|
38
|
+
def remove_dot_and_method!(send_node)
|
39
|
+
map = send_node.loc
|
40
|
+
dot_and_method_range = map.dot.join(map.expression.end)
|
41
|
+
remove(dot_and_method_range)
|
42
|
+
end
|
43
|
+
|
44
|
+
def any_number_of_times_node
|
45
|
+
each_following_chained_method_node do |chained_node|
|
46
|
+
method_name = chained_node.children[1]
|
47
|
+
return chained_node if method_name == :any_number_of_times
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def at_least_zero_node
|
52
|
+
each_following_chained_method_node do |chained_node|
|
53
|
+
_, method_name, arg_node = *chained_node
|
54
|
+
next unless method_name == :at_least
|
55
|
+
return chained_node if arg_node == s(:int, 0)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def each_following_chained_method_node
|
60
|
+
return to_enum(__method__) unless block_given?
|
61
|
+
|
62
|
+
@ancestor_nodes.reverse.reduce(@node) do |child_node, parent_node|
|
63
|
+
return unless [:send, :block].include?(parent_node.type)
|
64
|
+
return unless parent_node.children.first == child_node
|
65
|
+
yield parent_node, child_node
|
66
|
+
parent_node
|
67
|
+
end
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Transpec
|
4
|
+
class Syntax
|
5
|
+
module Mixin
|
6
|
+
module AnyInstance
|
7
|
+
def any_instance?
|
8
|
+
!class_node_of_any_instance.nil?
|
9
|
+
end
|
10
|
+
|
11
|
+
def class_node_of_any_instance
|
12
|
+
return nil unless subject_node.type == :send
|
13
|
+
return nil unless subject_node.children.count == 2
|
14
|
+
receiver_node, method_name = *subject_node
|
15
|
+
return nil unless method_name == :any_instance
|
16
|
+
return nil unless receiver_node.type == :const
|
17
|
+
receiver_node
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'transpec/util'
|
4
|
+
|
5
|
+
module Transpec
|
6
|
+
class Syntax
|
7
|
+
module Mixin
|
8
|
+
module Expectizable
|
9
|
+
def wrap_subject_in_expect!
|
10
|
+
wrap_subject_with_method!('expect')
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def wrap_subject_with_method!(method)
|
16
|
+
if Util.in_parentheses?(subject_node)
|
17
|
+
insert_before(subject_range, method)
|
18
|
+
else
|
19
|
+
insert_before(subject_range, "#{method}(")
|
20
|
+
insert_after(subject_range, ')')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'transpec/syntax/have'
|
4
|
+
|
5
|
+
module Transpec
|
6
|
+
class Syntax
|
7
|
+
module Mixin
|
8
|
+
module HaveMatcher
|
9
|
+
def have_matcher
|
10
|
+
return @have_matcher if instance_variable_defined?(:@have_matcher)
|
11
|
+
|
12
|
+
@have_matcher ||= begin
|
13
|
+
if Have.target_node?(matcher_node, @runtime_data)
|
14
|
+
Have.new(matcher_node, self, @source_rewriter, @runtime_data, @report)
|
15
|
+
else
|
16
|
+
nil
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Transpec
|
4
|
+
class Syntax
|
5
|
+
module Mixin
|
6
|
+
module MonkeyPatch
|
7
|
+
def register_request_of_syntax_availability_inspection(rewriter, key, methods)
|
8
|
+
code = "self.class.name.start_with?('RSpec::')"
|
9
|
+
|
10
|
+
methods.each do |method|
|
11
|
+
code << " && respond_to?(#{method.inspect})"
|
12
|
+
end
|
13
|
+
|
14
|
+
rewriter.register_request(@node, key, code, :context)
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_syntax_availability(key)
|
18
|
+
node_data = runtime_node_data(@node)
|
19
|
+
|
20
|
+
if node_data
|
21
|
+
node_data[key].result
|
22
|
+
else
|
23
|
+
static_context_inspector.send(key)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def subject_node
|
28
|
+
receiver_node
|
29
|
+
end
|
30
|
+
|
31
|
+
def subject_range
|
32
|
+
receiver_range
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Transpec
|
4
|
+
class Syntax
|
5
|
+
module Mixin
|
6
|
+
module Send
|
7
|
+
def self.included(klass)
|
8
|
+
klass.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def register_request_for_dynamic_analysis(node, rewriter)
|
13
|
+
return unless target_node?(node)
|
14
|
+
|
15
|
+
receiver_node, method_name, *_ = *node
|
16
|
+
|
17
|
+
if receiver_node
|
18
|
+
target_node = receiver_node
|
19
|
+
target_object_type = :object
|
20
|
+
else
|
21
|
+
target_node = node
|
22
|
+
target_object_type = :context
|
23
|
+
end
|
24
|
+
|
25
|
+
key = source_location_key(method_name)
|
26
|
+
code = "method(#{method_name.inspect}).source_location"
|
27
|
+
rewriter.register_request(target_node, key, code, target_object_type)
|
28
|
+
end
|
29
|
+
|
30
|
+
def target_node?(node, runtime_data = nil)
|
31
|
+
check_target_node_statically(node) && check_target_node_dynamically(node, runtime_data)
|
32
|
+
end
|
33
|
+
|
34
|
+
def target_method?(receiver_node, method_name)
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_target_node_statically(node)
|
39
|
+
return false unless node && node.type == :send
|
40
|
+
receiver_node, method_name, *_ = *node
|
41
|
+
target_method?(receiver_node, method_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def check_target_node_dynamically(node, runtime_data)
|
45
|
+
return true unless runtime_data
|
46
|
+
|
47
|
+
receiver_node, method_name, *_ = *node
|
48
|
+
target_node = receiver_node ? receiver_node : node
|
49
|
+
|
50
|
+
return true unless (node_data = runtime_data[target_node])
|
51
|
+
return true unless (eval_data = node_data[source_location_key(method_name)])
|
52
|
+
return true unless (source_location = eval_data.result)
|
53
|
+
|
54
|
+
file_path = source_location.first
|
55
|
+
!file_path.match(%r{/gems/rspec\-[^/]+/lib/rspec/}).nil?
|
56
|
+
end
|
57
|
+
|
58
|
+
def source_location_key(method_name)
|
59
|
+
"#{method_name}_source_location".to_sym
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def receiver_node
|
64
|
+
@node.children[0]
|
65
|
+
end
|
66
|
+
|
67
|
+
def method_name
|
68
|
+
@node.children[1]
|
69
|
+
end
|
70
|
+
|
71
|
+
def arg_node
|
72
|
+
@node.children[2]
|
73
|
+
end
|
74
|
+
|
75
|
+
def arg_nodes
|
76
|
+
@node.children[2..-1]
|
77
|
+
end
|
78
|
+
|
79
|
+
def selector_range
|
80
|
+
@node.loc.selector
|
81
|
+
end
|
82
|
+
|
83
|
+
def receiver_range
|
84
|
+
receiver_node.loc.expression
|
85
|
+
end
|
86
|
+
|
87
|
+
def arg_range
|
88
|
+
arg_node.loc.expression
|
89
|
+
end
|
90
|
+
|
91
|
+
def parentheses_range
|
92
|
+
selector_range.end.join(expression_range.end)
|
93
|
+
end
|
94
|
+
|
95
|
+
def range_in_between_receiver_and_selector
|
96
|
+
receiver_range.end.join(selector_range.begin)
|
97
|
+
end
|
98
|
+
|
99
|
+
def range_in_between_selector_and_arg
|
100
|
+
selector_range.end.join(arg_range.begin)
|
101
|
+
end
|
102
|
+
|
103
|
+
def range_after_arg
|
104
|
+
arg_range.end.join(expression_range.end)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -1,22 +1,34 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
|
-
require 'transpec/syntax/
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
5
|
require 'transpec/util'
|
6
6
|
|
7
7
|
module Transpec
|
8
8
|
class Syntax
|
9
|
-
class
|
10
|
-
include
|
9
|
+
class OperatorMatcher < Syntax
|
10
|
+
include Mixin::Send, Util, ::AST::Sexp
|
11
11
|
|
12
|
-
|
12
|
+
OPERATORS = [:==, :===, :<, :<=, :>, :>=, :=~].freeze
|
13
|
+
|
14
|
+
def self.standalone?
|
13
15
|
false
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
18
|
+
def self.target_method?(receiver_node, method_name)
|
19
|
+
!receiver_node.nil? && OPERATORS.include?(method_name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(node, source_rewriter = nil, runtime_data = nil, report = nil)
|
17
23
|
@node = node
|
18
24
|
@source_rewriter = source_rewriter
|
19
|
-
@
|
25
|
+
@runtime_data = runtime_data
|
26
|
+
@report = report || Report.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def register_request_for_dynamic_analysis(rewriter)
|
30
|
+
return unless method_name == :=~
|
31
|
+
rewriter.register_request(arg_node, :arg_is_enumerable?, 'is_a?(Enumerable)')
|
20
32
|
end
|
21
33
|
|
22
34
|
def correct_operator!(parenthesize_arg = true)
|
@@ -31,7 +43,7 @@ module Transpec
|
|
31
43
|
end
|
32
44
|
|
33
45
|
def parenthesize!(always = true)
|
34
|
-
return if
|
46
|
+
return if contain_here_document?(arg_node)
|
35
47
|
|
36
48
|
left_of_arg_source = range_in_between_selector_and_arg.source
|
37
49
|
|
@@ -60,7 +72,7 @@ module Transpec
|
|
60
72
|
def convert_to_match!(parenthesize_arg)
|
61
73
|
handle_anterior_of_operator!
|
62
74
|
|
63
|
-
if
|
75
|
+
if arg_is_enumerable?
|
64
76
|
replace(selector_range, 'match_array')
|
65
77
|
else
|
66
78
|
replace(selector_range, 'match')
|
@@ -70,7 +82,7 @@ module Transpec
|
|
70
82
|
|
71
83
|
# Need to register record after all source rewrites are done
|
72
84
|
# to avoid false record when failed with overlapped rewrite.
|
73
|
-
if
|
85
|
+
if arg_is_enumerable?
|
74
86
|
register_record('=~ [1, 2]', 'match_array([1, 2])')
|
75
87
|
else
|
76
88
|
register_record('=~ /pattern/', 'match(/pattern/)')
|
@@ -85,6 +97,12 @@ module Transpec
|
|
85
97
|
end
|
86
98
|
end
|
87
99
|
|
100
|
+
def arg_is_enumerable?
|
101
|
+
return true if arg_node.type == :array
|
102
|
+
node_data = runtime_node_data(arg_node)
|
103
|
+
node_data && node_data[:arg_is_enumerable?].result
|
104
|
+
end
|
105
|
+
|
88
106
|
def parenthesize_single_line!(always)
|
89
107
|
if in_parentheses?(arg_node)
|
90
108
|
remove(range_in_between_selector_and_arg)
|
@@ -120,11 +138,6 @@ module Transpec
|
|
120
138
|
end
|
121
139
|
end
|
122
140
|
|
123
|
-
def argument_is_here_document?
|
124
|
-
here_document?(arg_node) ||
|
125
|
-
arg_node.each_descendent_node.any? { |n| here_document?(n) }
|
126
|
-
end
|
127
|
-
|
128
141
|
def register_record(original_syntax, converted_syntax)
|
129
142
|
original_syntax ||= "#{method_name} expected"
|
130
143
|
@report.records << Record.new(original_syntax, converted_syntax)
|
@@ -1,12 +1,16 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
|
-
require 'transpec/syntax/
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
5
|
|
6
6
|
module Transpec
|
7
7
|
class Syntax
|
8
8
|
class RaiseError < Syntax
|
9
|
-
include
|
9
|
+
include Mixin::Send
|
10
|
+
|
11
|
+
def self.target_method?(receiver_node, method_name)
|
12
|
+
receiver_node.nil? && method_name == :raise_error
|
13
|
+
end
|
10
14
|
|
11
15
|
def remove_error_specification_with_negative_expectation!
|
12
16
|
return if positive?
|
@@ -31,14 +35,6 @@ module Transpec
|
|
31
35
|
|
32
36
|
private
|
33
37
|
|
34
|
-
def self.target_receiver_node?(node)
|
35
|
-
node.nil?
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.target_method_names
|
39
|
-
[:raise_error]
|
40
|
-
end
|
41
|
-
|
42
38
|
def register_record
|
43
39
|
original_syntax = 'expect { }.not_to raise_error('
|
44
40
|
|
@@ -2,11 +2,39 @@
|
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
4
|
require 'transpec/util'
|
5
|
-
require 'transpec/ast/scanner'
|
6
5
|
|
7
6
|
module Transpec
|
8
7
|
class Syntax
|
9
8
|
class RSpecConfigure < Syntax
|
9
|
+
extend Util
|
10
|
+
|
11
|
+
def self.target_node?(node, runtime_data = nil)
|
12
|
+
return false unless node && node.type == :block
|
13
|
+
send_node = node.children.first
|
14
|
+
receiver_node, method_name, *_ = *send_node
|
15
|
+
const_name(receiver_node) == 'RSpec' && method_name == :configure
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.add_framework_configuration(type, config_method_name)
|
19
|
+
class_eval <<-END
|
20
|
+
def #{type}_syntaxes
|
21
|
+
#{type}_framework_configuration.syntaxes
|
22
|
+
end
|
23
|
+
|
24
|
+
def modify_#{type}_syntaxes!(syntaxes)
|
25
|
+
#{type}_framework_configuration.modify_syntaxes!(syntaxes)
|
26
|
+
end
|
27
|
+
|
28
|
+
def #{type}_framework_configuration
|
29
|
+
@#{type}_framework_configuration ||=
|
30
|
+
FrameworkConfiguration.new(node, :#{config_method_name}, source_rewriter)
|
31
|
+
end
|
32
|
+
END
|
33
|
+
end
|
34
|
+
|
35
|
+
add_framework_configuration :expectation, :expect_with
|
36
|
+
add_framework_configuration :mock, :mock_with
|
37
|
+
|
10
38
|
class FrameworkConfiguration
|
11
39
|
include ::AST::Sexp
|
12
40
|
|
@@ -83,33 +111,6 @@ module Transpec
|
|
83
111
|
end
|
84
112
|
end
|
85
113
|
|
86
|
-
def self.target_node?(node)
|
87
|
-
return false unless node.type == :block
|
88
|
-
send_node = node.children.first
|
89
|
-
receiver_node, method_name, *_ = *send_node
|
90
|
-
Util.const_name(receiver_node) == 'RSpec' && method_name == :configure
|
91
|
-
end
|
92
|
-
|
93
|
-
def self.add_framework_configuration(type, config_method_name)
|
94
|
-
class_eval <<-END
|
95
|
-
def #{type}_syntaxes
|
96
|
-
#{type}_framework_configuration.syntaxes
|
97
|
-
end
|
98
|
-
|
99
|
-
def modify_#{type}_syntaxes!(syntaxes)
|
100
|
-
#{type}_framework_configuration.modify_syntaxes!(syntaxes)
|
101
|
-
end
|
102
|
-
|
103
|
-
def #{type}_framework_configuration
|
104
|
-
@#{type}_framework_configuration ||=
|
105
|
-
FrameworkConfiguration.new(node, :#{config_method_name}, source_rewriter)
|
106
|
-
end
|
107
|
-
END
|
108
|
-
end
|
109
|
-
|
110
|
-
add_framework_configuration :expectation, :expect_with
|
111
|
-
add_framework_configuration :mock, :mock_with
|
112
|
-
|
113
114
|
class UnknownSyntaxError < StandardError; end
|
114
115
|
end
|
115
116
|
end
|
@@ -1,21 +1,50 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
require 'transpec/syntax'
|
4
|
-
require 'transpec/syntax/
|
5
|
-
require 'transpec/syntax/
|
4
|
+
require 'transpec/syntax/mixin/send'
|
5
|
+
require 'transpec/syntax/mixin/monkey_patch'
|
6
|
+
require 'transpec/syntax/mixin/expectizable'
|
7
|
+
require 'transpec/syntax/mixin/have_matcher'
|
6
8
|
require 'transpec/util'
|
9
|
+
require 'transpec/syntax/operator_matcher'
|
7
10
|
|
8
11
|
module Transpec
|
9
12
|
class Syntax
|
10
13
|
class Should < Syntax
|
11
|
-
include Expectizable, Util
|
14
|
+
include Mixin::Send, Mixin::MonkeyPatch, Mixin::Expectizable, Mixin::HaveMatcher, Util
|
15
|
+
|
16
|
+
attr_reader :current_syntax_type
|
17
|
+
|
18
|
+
def self.target_method?(receiver_node, method_name)
|
19
|
+
!receiver_node.nil? && [:should, :should_not].include?(method_name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(node, ancestor_nodes, source_rewriter = nil, runtime_data = nil, report = nil)
|
23
|
+
super
|
24
|
+
@current_syntax_type = :should
|
25
|
+
end
|
26
|
+
|
27
|
+
def register_request_for_dynamic_analysis(rewriter)
|
28
|
+
register_request_of_syntax_availability_inspection(
|
29
|
+
rewriter,
|
30
|
+
:expect_available?,
|
31
|
+
[:expect]
|
32
|
+
)
|
33
|
+
|
34
|
+
operator_matcher.register_request_for_dynamic_analysis(rewriter) if operator_matcher
|
35
|
+
have_matcher.register_request_for_dynamic_analysis(rewriter) if have_matcher
|
36
|
+
end
|
37
|
+
|
38
|
+
def expect_available?
|
39
|
+
check_syntax_availability(__method__)
|
40
|
+
end
|
12
41
|
|
13
42
|
def positive?
|
14
43
|
method_name == :should
|
15
44
|
end
|
16
45
|
|
17
46
|
def expectize!(negative_form = 'not_to', parenthesize_matcher_arg = true)
|
18
|
-
unless
|
47
|
+
unless expect_available?
|
19
48
|
fail InvalidContextError.new(selector_range, "##{method_name}", '#expect')
|
20
49
|
end
|
21
50
|
|
@@ -27,13 +56,22 @@ module Transpec
|
|
27
56
|
|
28
57
|
replace(should_range, positive? ? 'to' : negative_form)
|
29
58
|
|
59
|
+
@current_syntax_type = :expect
|
30
60
|
register_record(negative_form)
|
31
61
|
|
32
|
-
|
62
|
+
operator_matcher.correct_operator!(parenthesize_matcher_arg) if operator_matcher
|
33
63
|
end
|
34
64
|
|
35
|
-
def
|
36
|
-
@
|
65
|
+
def operator_matcher
|
66
|
+
return @operator_matcher if instance_variable_defined?(:@operator_matcher)
|
67
|
+
|
68
|
+
@operator_matcher ||= begin
|
69
|
+
if OperatorMatcher.target_node?(matcher_node, @runtime_data)
|
70
|
+
OperatorMatcher.new(matcher_node, @source_rewriter, @runtime_data, @report)
|
71
|
+
else
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
end
|
37
75
|
end
|
38
76
|
|
39
77
|
def matcher_node
|
@@ -42,14 +80,6 @@ module Transpec
|
|
42
80
|
|
43
81
|
private
|
44
82
|
|
45
|
-
def self.target_receiver_node?(node)
|
46
|
-
!node.nil?
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.target_method_names
|
50
|
-
[:should, :should_not]
|
51
|
-
end
|
52
|
-
|
53
83
|
def replace_proc_selector_with_expect!
|
54
84
|
send_node = subject_node.children.first
|
55
85
|
range_of_subject_method_taking_block = send_node.loc.expression
|