lib/surrogate/api_comparer.rb in surrogate-0.6.1 vs lib/surrogate/api_comparer.rb in surrogate-0.6.2
- old
+ new
@@ -6,11 +6,15 @@
# compares a surrogate to an object
class ApiComparer
attr_accessor :surrogate, :actual
- def initialize(surrogate, actual)
+ def initialize(actual, surrogate)
+ unless surrogate.instance_variable_get(:@hatchery).kind_of?(Hatchery) && surrogate.instance_variable_get(:@hatchling).kind_of?(Hatchling)
+ Kernel.warn "You said #{actual} should substitute for #{surrogate}`, but as of 0.6.2, this should be asserted in the other direction."
+ surrogate, actual = actual, surrogate
+ end
self.surrogate, self.actual = surrogate, actual
end
def surrogate_methods
@surrogate_methods ||= SurrogateClassReflector.new(surrogate).methods
@@ -24,15 +28,17 @@
@compare ||= {
instance: {
not_on_surrogate: instance_not_on_surrogate,
not_on_actual: instance_not_on_actual,
types: instance_types,
+ names: instance_names,
},
class: {
not_on_surrogate: class_not_on_surrogate,
not_on_actual: class_not_on_actual,
types: class_types,
+ names: class_names,
},
}
end
def instance_not_on_surrogate
@@ -51,36 +57,67 @@
def class_not_on_actual
surrogate_methods[:class][:api] - actual_methods[:class][:inherited] - actual_methods[:class][:other]
end
+
+ # there is a lot of duplication in these next four methods -.-
+ # idk if there is something we can do about it.
+
# types are only shown for methods on both objects
def class_types
- surrogate_class_methods = surrogate_methods[:class][:api] + surrogate_methods[:class][:inherited]
- actual_class_methods = actual_methods[:class][:inherited] + actual_methods[:class][:other]
- class_methods_that_should_match = (surrogate_class_methods & actual_class_methods) - surrogate_methods[:class][:without_bodies] - actual_methods[:class][:without_bodies]
class_methods_that_should_match.each_with_object Hash.new do |name, hash|
surrogate_type, actual_type = class_types_for name
next if surrogate_type == actual_type
hash[name] = { surrogate: surrogate_type, actual: actual_type }
end
end
# types are only shown for methods on both objects
def instance_types
- surrogate_instance_methods = surrogate_methods[:instance][:api] + surrogate_methods[:instance][:inherited]
- actual_instance_methods = actual_methods[:instance][:inherited] + actual_methods[:instance][:other]
- instance_methods_that_should_match = (surrogate_instance_methods & actual_instance_methods) - surrogate_methods[:instance][:without_bodies] - actual_methods[:instance][:without_bodies]
instance_methods_that_should_match.each_with_object Hash.new do |name, hash|
surrogate_type, actual_type = instance_types_for name
next if surrogate_type == actual_type
hash[name] = { surrogate: surrogate_type, actual: actual_type }
end
end
+ # names are only shown for methods on both objects
+ def class_names
+ class_methods_that_should_match.each_with_object Hash.new do |method_name, hash|
+ surrogate_name, actual_name = class_parameter_names_for method_name
+ next if surrogate_name == actual_name
+ hash[method_name] = { surrogate: surrogate_name, actual: actual_name }
+ end
+ end
+
+ # names are only shown for methods on both objects
+ def instance_names
+ instance_methods_that_should_match.each_with_object Hash.new do |method_name, hash|
+ surrogate_name, actual_name = instance_parameter_names_for method_name
+ next if surrogate_name == actual_name
+ hash[method_name] = { surrogate: surrogate_name, actual: actual_name }
+ end
+ end
+
private
+ def instance_methods_that_should_match
+ surrogate_instance_methods = surrogate_methods[:instance][:api] + surrogate_methods[:instance][:inherited]
+ actual_instance_methods = actual_methods[:instance][:inherited] + actual_methods[:instance][:other]
+ instance_methods_that_should_match = (surrogate_instance_methods & actual_instance_methods) - surrogate_methods[:instance][:without_bodies] - actual_methods[:instance][:without_bodies]
+ end
+
+ def class_methods_that_should_match
+ surrogate_class_methods = surrogate_methods[:class][:api] + surrogate_methods[:class][:inherited]
+ actual_class_methods = actual_methods[:class][:inherited] + actual_methods[:class][:other]
+ (surrogate_class_methods & actual_class_methods) - surrogate_methods[:class][:without_bodies] - actual_methods[:class][:without_bodies]
+ end
+
+ # there is a lot of duplication in these next four methods -.-
+ # also, it seems like a lot of this shit could move into the reflectors
+
def class_types_for(name)
surrogate_method = class_api_method_for name
surrogate_method &&= to_lambda surrogate_method
surrogate_method ||= surrogate.method name
actual_method = actual.method name
@@ -93,11 +130,31 @@
surrogate_method ||= surrogate.instance_method name
actual_method = actual.instance_method name
return type_for(surrogate_method), type_for(actual_method)
end
+ def class_parameter_names_for(name)
+ surrogate_method = class_api_method_for name
+ surrogate_method &&= to_lambda surrogate_method
+ surrogate_method ||= surrogate.method name
+ actual_method = actual.method name
+ return parameter_names_for(surrogate_method), parameter_names_for(actual_method)
+ end
+
+ def instance_parameter_names_for(name)
+ surrogate_method = instance_api_method_for name
+ surrogate_method &&= to_lambda surrogate_method
+ surrogate_method ||= surrogate.instance_method name
+ actual_method = actual.instance_method name
+ return parameter_names_for(surrogate_method), parameter_names_for(actual_method)
+ end
+
def type_for(method)
method.parameters.map(&:first)
+ end
+
+ def parameter_names_for(method)
+ method.parameters.map(&:last)
end
def to_lambda(proc)
obj = Object.new
obj.singleton_class.send :define_method, :abc123, &proc