transpec 0.2.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +1 -1
  4. data/CHANGELOG.md +10 -0
  5. data/README.md +111 -56
  6. data/README.md.erb +117 -62
  7. data/lib/transpec/ast/node.rb +41 -0
  8. data/lib/transpec/base_rewriter.rb +55 -0
  9. data/lib/transpec/cli.rb +43 -153
  10. data/lib/transpec/configuration.rb +13 -9
  11. data/lib/transpec/{rewriter.rb → converter.rb} +44 -71
  12. data/lib/transpec/dynamic_analyzer/rewriter.rb +94 -0
  13. data/lib/transpec/dynamic_analyzer/runtime_data.rb +27 -0
  14. data/lib/transpec/dynamic_analyzer.rb +166 -0
  15. data/lib/transpec/file_finder.rb +53 -0
  16. data/lib/transpec/option_parser.rb +166 -0
  17. data/lib/transpec/{context.rb → static_context_inspector.rb} +2 -2
  18. data/lib/transpec/syntax/be_close.rb +7 -9
  19. data/lib/transpec/syntax/double.rb +6 -10
  20. data/lib/transpec/syntax/expect.rb +35 -0
  21. data/lib/transpec/syntax/have.rb +195 -0
  22. data/lib/transpec/syntax/method_stub.rb +22 -27
  23. data/lib/transpec/syntax/mixin/allow_no_message.rb +73 -0
  24. data/lib/transpec/syntax/mixin/any_instance.rb +22 -0
  25. data/lib/transpec/syntax/mixin/expectizable.rb +26 -0
  26. data/lib/transpec/syntax/mixin/have_matcher.rb +23 -0
  27. data/lib/transpec/syntax/mixin/monkey_patch.rb +37 -0
  28. data/lib/transpec/syntax/mixin/send.rb +109 -0
  29. data/lib/transpec/syntax/{matcher.rb → operator_matcher.rb} +27 -14
  30. data/lib/transpec/syntax/raise_error.rb +6 -10
  31. data/lib/transpec/syntax/rspec_configure.rb +29 -28
  32. data/lib/transpec/syntax/should.rb +45 -15
  33. data/lib/transpec/syntax/should_receive.rb +44 -16
  34. data/lib/transpec/syntax.rb +29 -21
  35. data/lib/transpec/util.rb +12 -2
  36. data/lib/transpec/version.rb +3 -3
  37. data/spec/spec_helper.rb +8 -6
  38. data/spec/support/cache_helper.rb +50 -0
  39. data/spec/support/shared_context.rb +49 -1
  40. data/spec/transpec/ast/node_spec.rb +65 -0
  41. data/spec/transpec/cli_spec.rb +33 -242
  42. data/spec/transpec/commit_message_spec.rb +2 -2
  43. data/spec/transpec/configuration_spec.rb +12 -8
  44. data/spec/transpec/{rewriter_spec.rb → converter_spec.rb} +198 -148
  45. data/spec/transpec/dynamic_analyzer/rewriter_spec.rb +183 -0
  46. data/spec/transpec/dynamic_analyzer_spec.rb +164 -0
  47. data/spec/transpec/file_finder_spec.rb +118 -0
  48. data/spec/transpec/option_parser_spec.rb +185 -0
  49. data/spec/transpec/{context_spec.rb → static_context_inspector_spec.rb} +27 -12
  50. data/spec/transpec/syntax/be_close_spec.rb +8 -4
  51. data/spec/transpec/syntax/double_spec.rb +105 -12
  52. data/spec/transpec/syntax/expect_spec.rb +83 -0
  53. data/spec/transpec/syntax/have_spec.rb +599 -0
  54. data/spec/transpec/syntax/method_stub_spec.rb +276 -115
  55. data/spec/transpec/syntax/{matcher_spec.rb → operator_matcher_spec.rb} +277 -98
  56. data/spec/transpec/syntax/raise_error_spec.rb +92 -46
  57. data/spec/transpec/syntax/should_receive_spec.rb +298 -92
  58. data/spec/transpec/syntax/should_spec.rb +230 -44
  59. data/spec/transpec/util_spec.rb +2 -9
  60. data/tasks/lib/transpec_demo.rb +1 -1
  61. data/tasks/lib/transpec_test.rb +5 -7
  62. data/tasks/test.rake +5 -1
  63. data/transpec.gemspec +1 -1
  64. metadata +46 -22
  65. data/lib/transpec/syntax/able_to_allow_no_message.rb +0 -73
  66. data/lib/transpec/syntax/able_to_target_any_instance.rb +0 -24
  67. data/lib/transpec/syntax/expectizable.rb +0 -27
  68. 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/able_to_allow_no_message'
5
- require 'transpec/syntax/able_to_target_any_instance'
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 AbleToAllowNoMessage, AbleToTargetAnyInstance, Util
14
+ include Mixin::Send, Mixin::MonkeyPatch, Mixin::AllowNoMessage, Mixin::AnyInstance, Util
13
15
 
14
- CLASSES_DEFINING_OWN_STUB_METHOD = [
15
- 'Typhoeus', # https://github.com/typhoeus/typhoeus/blob/6a59c62/lib/typhoeus.rb#L66-L85
16
- 'Excon' # https://github.com/geemus/excon/blob/6af4f9c/lib/excon.rb#L143-L178
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
- fail 'Already replaced deprecated method, cannot allowize.' if @replaced_deprecated_method
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 replace_deprecated_method!
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/send_node_syntax'
4
+ require 'transpec/syntax/mixin/send'
5
5
  require 'transpec/util'
6
6
 
7
7
  module Transpec
8
8
  class Syntax
9
- class Matcher < Syntax
10
- include SendNodeSyntax, Util, ::AST::Sexp
9
+ class OperatorMatcher < Syntax
10
+ include Mixin::Send, Util, ::AST::Sexp
11
11
 
12
- def self.target_node?(node)
12
+ OPERATORS = [:==, :===, :<, :<=, :>, :>=, :=~].freeze
13
+
14
+ def self.standalone?
13
15
  false
14
16
  end
15
17
 
16
- def initialize(node, source_rewriter, report = Report.new)
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
- @report = report
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 argument_is_here_document?
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 arg_node.type == :array
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 arg_node.type == :array
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/send_node_syntax'
4
+ require 'transpec/syntax/mixin/send'
5
5
 
6
6
  module Transpec
7
7
  class Syntax
8
8
  class RaiseError < Syntax
9
- include SendNodeSyntax
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/expectizable'
5
- require 'transpec/syntax/matcher'
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 context.expect_to_matcher_available?
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
- matcher.correct_operator!(parenthesize_matcher_arg)
62
+ operator_matcher.correct_operator!(parenthesize_matcher_arg) if operator_matcher
33
63
  end
34
64
 
35
- def matcher
36
- @matcher ||= Matcher.new(matcher_node, @source_rewriter, @report)
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