Class: MethodSequenceChecker
- Inherits:
-
Object
- Object
- MethodSequenceChecker
- Defined in:
- lib/pippi/checks/method_sequence_checker.rb
Constant Summary collapse
- ARITY_TYPE_BLOCK_ARG =
1
- ARITY_TYPE_NONE =
2
Instance Attribute Summary collapse
-
#check ⇒ Object
readonly
Returns the value of attribute check.
-
#clazz_to_decorate ⇒ Object
readonly
Returns the value of attribute clazz_to_decorate.
-
#first_method_arity_type ⇒ Object
readonly
Returns the value of attribute first_method_arity_type.
-
#method1 ⇒ Object
readonly
Returns the value of attribute method1.
-
#method2 ⇒ Object
readonly
Returns the value of attribute method2.
-
#second_method_arity_type ⇒ Object
readonly
Returns the value of attribute second_method_arity_type.
-
#should_check_subsequent_calls ⇒ Object
readonly
Returns the value of attribute should_check_subsequent_calls.
Instance Method Summary collapse
- #array_mutator_methods ⇒ Object
- #decorate ⇒ Object
-
#initialize(check, clazz_to_decorate, method1, method2, first_method_arity_type, second_method_arity_type, should_check_subsequent_calls) ⇒ MethodSequenceChecker
constructor
A new instance of MethodSequenceChecker.
- #its_ok_watcher_proc(clazz, method_name) ⇒ Object
Constructor Details
permalink #initialize(check, clazz_to_decorate, method1, method2, first_method_arity_type, second_method_arity_type, should_check_subsequent_calls) ⇒ MethodSequenceChecker
Returns a new instance of MethodSequenceChecker.
8 9 10 11 12 13 14 15 16 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 8 def initialize(check, clazz_to_decorate, method1, method2, first_method_arity_type, second_method_arity_type, should_check_subsequent_calls) @check = check @clazz_to_decorate = clazz_to_decorate @method1 = method1 @method2 = method2 @first_method_arity_type = first_method_arity_type @second_method_arity_type = second_method_arity_type @should_check_subsequent_calls = should_check_subsequent_calls end |
Instance Attribute Details
permalink #check ⇒ Object (readonly)
Returns the value of attribute check.
6 7 8 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 6 def check @check end |
permalink #clazz_to_decorate ⇒ Object (readonly)
Returns the value of attribute clazz_to_decorate.
6 7 8 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 6 def clazz_to_decorate @clazz_to_decorate end |
permalink #first_method_arity_type ⇒ Object (readonly)
Returns the value of attribute first_method_arity_type.
6 7 8 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 6 def first_method_arity_type @first_method_arity_type end |
permalink #method1 ⇒ Object (readonly)
Returns the value of attribute method1.
6 7 8 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 6 def method1 @method1 end |
permalink #method2 ⇒ Object (readonly)
Returns the value of attribute method2.
6 7 8 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 6 def method2 @method2 end |
permalink #second_method_arity_type ⇒ Object (readonly)
Returns the value of attribute second_method_arity_type.
6 7 8 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 6 def second_method_arity_type @second_method_arity_type end |
permalink #should_check_subsequent_calls ⇒ Object (readonly)
Returns the value of attribute should_check_subsequent_calls.
6 7 8 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 6 def should_check_subsequent_calls @should_check_subsequent_calls end |
Instance Method Details
permalink #array_mutator_methods ⇒ Object
[View source]
72 73 74 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 72 def array_mutator_methods [:collect!, :compact!, :flatten!, :map!, :reject!, :reverse!, :rotate!, :select!, :shuffle!, :slice!, :sort!, :sort_by!, :uniq!] end |
permalink #decorate ⇒ Object
[View source]
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 18 def decorate clazz_to_decorate.class_exec(check, self) do |my_check, method_sequence_check_instance| name = "@_pippi_check_#{my_check.class.name.split('::').last.downcase}" self.instance_variable_set(name, my_check) self.class.send(:define_method, name[1..-1]) do instance_variable_get(name) end # e.g., "size" in "select followed by size" second_method_decorator = if method_sequence_check_instance.second_method_arity_type.kind_of?(Module) method_sequence_check_instance.second_method_arity_type else Module.new do define_method(method_sequence_check_instance.method2) do |*args, &blk| # Using "self.class" implies that the first method invocation returns the same type as the receiver # e.g., Array#select returns an Array. Would need to further parameterize this to get # different behavior. self.class.instance_variable_get(name).add_problem if method_sequence_check_instance.should_check_subsequent_calls && method_sequence_check_instance.clazz_to_decorate == Array problem_location = caller_locations.find { |c| c.to_s !~ /byebug|lib\/pippi\/checks/ } self.class.instance_variable_get(name).method_names_that_indicate_this_is_being_used_as_a_collection.each do |this_means_its_ok_sym| define_singleton_method(this_means_its_ok_sym, self.class.instance_variable_get(name).clear_fault_proc(self.class.instance_variable_get(name), problem_location)) end end if method_sequence_check_instance.second_method_arity_type == ARITY_TYPE_BLOCK_ARG super(&blk) elsif method_sequence_check_instance.second_method_arity_type == ARITY_TYPE_NONE super() end end end end # e.g., "select" in "select followed by size" first_method_decorator = Module.new do define_method(method_sequence_check_instance.method1) do |*args, &blk| result = if method_sequence_check_instance.first_method_arity_type == ARITY_TYPE_BLOCK_ARG super(&blk) elsif method_sequence_check_instance.first_method_arity_type == ARITY_TYPE_NONE super() end if self.class.instance_variable_get(name) result.extend second_method_decorator self.class.instance_variable_get(name).array_mutator_methods.each do |this_means_its_ok_sym| result.define_singleton_method(this_means_its_ok_sym, self.class.instance_variable_get(name).its_ok_watcher_proc(second_method_decorator, method_sequence_check_instance.method2)) end end result end end prepend first_method_decorator end end |
permalink #its_ok_watcher_proc(clazz, method_name) ⇒ Object
[View source]
76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/pippi/checks/method_sequence_checker.rb', line 76 def its_ok_watcher_proc(clazz, method_name) proc do |*args, &blk| begin singleton_class.ancestors.find { |x| x == clazz }.instance_eval { remove_method method_name } rescue NameError return super(*args, &blk) else return super(*args, &blk) end end end |