lib/power_assert/context.rb in power_assert-1.0.2 vs lib/power_assert/context.rb in power_assert-1.1.0
- old
+ new
@@ -3,22 +3,23 @@
require 'power_assert/inspector'
require 'power_assert/parser'
module PowerAssert
class Context
- Value = Struct.new(:name, :value, :column)
+ Value = Struct.new(:name, :value, :lineno, :column)
- attr_reader :message_proc
-
def initialize(base_caller_length)
@fired = false
@target_thread = Thread.current
method_id_set = nil
- return_values = []
+ @return_values = []
trace_alias_method = PowerAssert.configuration._trace_alias_method
@trace_return = TracePoint.new(:return, :c_return) do |tp|
- method_id_set ||= @parser.method_id_set
+ unless method_id_set
+ next unless Thread.current == @target_thread
+ method_id_set = @parser.method_id_set
+ end
method_id = SUPPORT_ALIAS_METHOD ? tp.callee_id :
trace_alias_method && tp.event == :return ? tp.binding.eval('::Kernel.__callee__') :
tp.method_id
next if ! method_id_set[method_id]
next if tp.event == :c_return and
@@ -29,48 +30,51 @@
idx = -(base_caller_length + 1)
if @parser.path == locs[idx].path and @parser.lineno == locs[idx].lineno
val = PowerAssert.configuration.lazy_inspection ?
tp.return_value :
InspectedValue.new(SafeInspectable.new(tp.return_value).inspect)
- return_values << Value[method_id.to_s, val, nil]
+ @return_values << Value[method_id.to_s, val, locs[idx].lineno, nil]
end
end
end
- @message_proc = -> {
- raise RuntimeError, 'call #yield or #enable at first' unless fired?
- @message ||= build_assertion_message(@parser.line, @parser.idents, @parser.binding, return_values).freeze
- }
end
def message
- @message_proc.()
+ raise 'call #yield or #enable at first' unless fired?
+ @message ||= build_assertion_message(@parser, @return_values).freeze
end
+ def message_proc
+ -> { message }
+ end
+
private
def fired?
@fired
end
- def build_assertion_message(line, idents, proc_binding, return_values)
+ def build_assertion_message(parser, return_values)
if PowerAssert.configuration._colorize_message
- line = Pry::Code.new(line).highlighted
+ line = Pry::Code.new(parser.line).highlighted
+ else
+ line = parser.line
end
- path = detect_path(idents, return_values)
+ path = detect_path(parser, return_values)
return line unless path
- delete_unidentified_calls(return_values, path)
- methods, refs = path.partition {|i| i.type == :method }
- return_values.zip(methods) do |i, j|
+ return_values, methods_in_path = find_all_identified_calls(return_values, path)
+ return_values.zip(methods_in_path) do |i, j|
unless i.name == j.name
warn "power_assert: [BUG] Failed to get column: #{i.name}"
return line
end
i.column = j.column
end
- ref_values = refs.map {|i| Value[i.name, proc_binding.eval(i.name), i.column] }
+ refs_in_path = path.find_all {|i| i.type == :ref }
+ ref_values = refs_in_path.map {|i| Value[i.name, parser.binding.eval(i.name), parser.lineno, i.column] }
vals = (return_values + ref_values).find_all(&:column).sort_by(&:column).reverse
return line if vals.empty?
fmt = (0..vals[0].column).map {|i| vals.find {|v| v.column == i } ? "%<#{i}>s" : ' ' }.join
lines = []
@@ -86,13 +90,13 @@
end
end
lines.join("\n")
end
- def detect_path(idents, return_values)
- return @parser.call_paths.flatten.uniq if @parser.method_id_set.empty?
- all_paths = @parser.call_paths
+ def detect_path(parser, return_values)
+ return parser.call_paths.flatten.uniq if parser.method_id_set.empty?
+ all_paths = parser.call_paths
return_value_names = return_values.map(&:name)
uniq_calls = uniq_calls(all_paths)
uniq_call = return_value_names.find {|i| uniq_calls.include?(i) }
detected_paths = all_paths.find_all do |path|
method_names = path.find_all {|ident| ident.type == :method }.map(&:name)
@@ -106,16 +110,18 @@
def uniq_calls(paths)
all_calls = enum_count_by(paths.map {|path| path.find_all {|ident| ident.type == :method }.map(&:name).uniq }.flatten) {|i| i }
all_calls.find_all {|_, call_count| call_count == 1 }.map {|name, _| name }
end
- def delete_unidentified_calls(return_values, path)
+ def find_all_identified_calls(return_values, path)
return_value_num_of_calls = enum_count_by(return_values, &:name)
path_num_of_calls = enum_count_by(path.find_all {|ident| ident.type == :method }, &:name)
identified_calls = return_value_num_of_calls.find_all {|name, num| path_num_of_calls[name] == num }.map(&:first)
- return_values.delete_if {|val| ! identified_calls.include?(val.name) }
- path.delete_if {|ident| ident.type == :method and ! identified_calls.include?(ident.name) }
+ [
+ return_values.find_all {|val| identified_calls.include?(val.name) },
+ path.find_all {|ident| ident.type == :method and identified_calls.include?(ident.name) }
+ ]
end
def enum_count_by(enum, &blk)
Hash[enum.group_by(&blk).map{|k, v| [k, v.length] }]
end
@@ -150,10 +156,10 @@
locs = PowerAssert.app_caller_locations
path = locs.last.path
lineno = locs.last.lineno
if File.exist?(path)
line ||= open(path).each_line.drop(lineno - 1).first
- @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s)
+ @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc)
end
end
end
end