From 1bc02fef2ef19eaac89c4226a6ede767ed39b5b1 Mon Sep 17 00:00:00 2001 From: Kazuki Tsujimoto Date: Mon, 5 May 2025 13:40:55 +0900 Subject: [PATCH] Remove `PowerAssert.trace` --- Gemfile | 1 - README.md | 1 - lib/power_assert.rb | 48 ++++---------- lib/power_assert/context.rb | 123 ++++++++++++----------------------- test/test_core_ext_helper.rb | 21 ------ test/test_helper.rb | 5 -- test/trace_test.rb | 94 -------------------------- 7 files changed, 54 insertions(+), 239 deletions(-) delete mode 100644 test/test_core_ext_helper.rb delete mode 100644 test/trace_test.rb diff --git a/Gemfile b/Gemfile index 93efdce..22399a2 100644 --- a/Gemfile +++ b/Gemfile @@ -14,6 +14,5 @@ group :development do gem 'simplecov' gem 'bundler' gem 'irb', '>= 1.3.1' - gem 'byebug' gem 'benchmark-ips' end diff --git a/README.md b/README.md index 71adbcc..0ff93db 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,6 @@ Use following test frameworks or extensions instead. * [rspec-power_assert](https://github.com/joker1007/rspec-power_assert) * [rspec-matchers-power_assert_matchers](https://github.com/kachick/rspec-matchers-power_assert_matchers) * [pry-power_assert](https://github.com/yui-knk/pry-power_assert) -* [pry-byebug-power_assert](https://github.com/k-tsj/pry-byebug-power_assert) * [irb-power_assert](https://github.com/kachick/irb-power_assert) * [power_p](https://github.com/k-tsj/power_p) diff --git a/lib/power_assert.rb b/lib/power_assert.rb index 935661b..785b19c 100644 --- a/lib/power_assert.rb +++ b/lib/power_assert.rb @@ -3,18 +3,16 @@ # Copyright (C) 2014 Kazuki Tsujimoto begin - unless defined?(Byebug) - captured = false - target_thread = Thread.current - TracePoint.new(:return, :c_return) do |tp| - next unless Thread.current == target_thread - captured = true - unless tp.return_value and tp.callee_id - raise '' - end - end.enable { __id__ } - raise '' unless captured - end + captured = false + target_thread = Thread.current + TracePoint.new(:return, :c_return) do |tp| + next unless Thread.current == target_thread + captured = true + unless tp.return_value and tp.callee_id + raise '' + end + end.enable { __id__ } + raise '' unless captured rescue raise LoadError, 'Fully compatible TracePoint API required' end @@ -33,18 +31,7 @@ def start(assertion_proc_or_source, assertion_method: nil, source_binding: TOPLE if respond_to?(:clear_global_method_cache, true) clear_global_method_cache end - yield BlockContext.new(assertion_proc_or_source, assertion_method, source_binding) - end - - def trace(frame) - begin - raise 'Byebug is not started yet' unless Byebug.started? - rescue NameError - raise "PowerAssert.#{__method__} requires Byebug" - end - ctx = TraceContext.new(frame._binding) - ctx.enable - ctx + yield Context.new(assertion_proc_or_source, assertion_method, source_binding) end def app_caller_locations @@ -59,24 +46,11 @@ def app_context? private def internal_file?(file) - setup_internal_lib_dir(Byebug, :attach, 2) if defined?(Byebug) - setup_internal_lib_dir(PryByebug, :start_with_pry_byebug, 2, Pry) if defined?(PryByebug) INTERNAL_LIB_DIRS.find do |_, dir| file.start_with?(dir) end end - def setup_internal_lib_dir(lib, mid, depth, lib_obj = lib) - unless INTERNAL_LIB_DIRS.key?(lib) - INTERNAL_LIB_DIRS[lib] = lib_dir(lib_obj, mid, depth) - end - rescue NameError - end - - def lib_dir(obj, mid, depth) - File.expand_path('../' * depth, obj.method(mid).source_location[0]) - end - if defined?(RubyVM) CLEAR_CACHE_ISEQ = RubyVM::InstructionSequence.compile('using PowerAssert.const_get(:Empty)') private_constant :CLEAR_CACHE_ISEQ diff --git a/lib/power_assert/context.rb b/lib/power_assert/context.rb index 25b0a66..4a28e03 100644 --- a/lib/power_assert/context.rb +++ b/lib/power_assert/context.rb @@ -7,9 +7,34 @@ module PowerAssert class Context Value = Struct.new(:name, :value, :lineno, :column, :display_offset) - def initialize(base_caller_length) + def initialize(assertion_proc_or_source, assertion_method, source_binding) @fired = false @target_thread = Thread.current + + if assertion_proc_or_source.respond_to?(:to_proc) + @assertion_proc = assertion_proc_or_source.to_proc + line = nil + else + @assertion_proc = source_binding.eval "Proc.new {#{assertion_proc_or_source}}" + line = assertion_proc_or_source + end + + @parser = Parser::DUMMY + @trace_call = TracePoint.new(:call, :c_call) do + if PowerAssert.app_context? and Thread.current == @target_thread + @trace_call.disable + locs = PowerAssert.app_caller_locations + path = locs.last.path + lineno = locs.last.lineno + if File.exist?(path) + line ||= File.open(path) {|fp| fp.each_line.drop(lineno - 1).first } + end + if line + @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc) + end + end + end + method_id_set = nil @return_values = [] @trace_return = TracePoint.new(:return, :c_return) do |tp| @@ -22,14 +47,12 @@ def initialize(base_caller_length) next if tp.event == :c_return and not (@parser.lineno == tp.lineno and @parser.path == tp.path) locs = PowerAssert.app_caller_locations - diff = locs.length - base_caller_length - if (tp.event == :c_return && diff == 1 || tp.event == :return && diff <= 2) and Thread.current == @target_thread - idx = -(base_caller_length + 1) - if @parser.path == locs[idx].path and @parser.lineno == locs[idx].lineno + if (tp.event == :c_return && locs.length == 1 || tp.event == :return && locs.length <= 2) and Thread.current == @target_thread + if @parser.path == locs.last.path and @parser.lineno == locs.last.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, locs[idx].lineno, nil] + @return_values << Value[method_id.to_s, val, locs.last.lineno, nil] end end rescue Exception => e @@ -41,7 +64,7 @@ def initialize(base_caller_length) end def message - raise 'call #yield or #enable at first' unless fired? + raise 'call #yield at first' unless fired? @message ||= build_assertion_message(@parser, @return_values).freeze end @@ -49,8 +72,21 @@ def message_proc -> { message } end + def yield + @fired = true + invoke_yield(&@assertion_proc) + end + private + def invoke_yield + @trace_return.enable do + @trace_call.enable do + yield + end + end + end + def fired? @fired end @@ -157,77 +193,4 @@ def column2display_offset(str) end end private_constant :Context - - class BlockContext < Context - def initialize(assertion_proc_or_source, assertion_method, source_binding) - super(0) - if assertion_proc_or_source.respond_to?(:to_proc) - @assertion_proc = assertion_proc_or_source.to_proc - line = nil - else - @assertion_proc = source_binding.eval "Proc.new {#{assertion_proc_or_source}}" - line = assertion_proc_or_source - end - @parser = Parser::DUMMY - @trace_call = TracePoint.new(:call, :c_call) do - if PowerAssert.app_context? and Thread.current == @target_thread - @trace_call.disable - locs = PowerAssert.app_caller_locations - path = locs.last.path - lineno = locs.last.lineno - if File.exist?(path) - line ||= File.open(path) {|fp| fp.each_line.drop(lineno - 1).first } - end - if line - @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc) - end - end - end - end - - def yield - @fired = true - invoke_yield(&@assertion_proc) - end - - private - - def invoke_yield - @trace_return.enable do - @trace_call.enable do - yield - end - end - end - end - private_constant :BlockContext - - class TraceContext < Context - def initialize(binding) - target_frame, *base = PowerAssert.app_caller_locations - super(base.length) - path = target_frame.path - lineno = target_frame.lineno - if File.exist?(path) - line = File.open(path) {|fp| fp.each_line.drop(lineno - 1).first } - @parser = Parser.new(line, path, lineno, binding) - else - @parser = Parser::DUMMY - end - end - - def enable - @fired = true - @trace_return.enable - end - - def disable - @trace_return.disable - end - - def enabled? - @trace_return.enabled? - end - end - private_constant :TraceContext end diff --git a/test/test_core_ext_helper.rb b/test/test_core_ext_helper.rb deleted file mode 100644 index d804f14..0000000 --- a/test/test_core_ext_helper.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'byebug' -require 'byebug/core' - -class << PowerAssert - prepend Module.new { - def internal_file?(file) - super or file == __FILE__ - end - } -end - -module PowerAssertTestHelper - class TestProcessor < Byebug::CommandProcessor - attr_reader :pa_context - - def at_line - super - @pa_context ||= PowerAssert.trace(frame) - end - end -end diff --git a/test/test_helper.rb b/test/test_helper.rb index 98a2571..5cc39ef 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -16,11 +16,6 @@ require 'power_assert' require 'ripper' -begin - require_relative 'test_core_ext_helper' -rescue LoadError -end - module PowerAssertTestHelper class << self def included(base) diff --git a/test/trace_test.rb b/test/trace_test.rb deleted file mode 100644 index c46be7f..0000000 --- a/test/trace_test.rb +++ /dev/null @@ -1,94 +0,0 @@ -if defined?(RubyVM) and ! RubyVM::InstructionSequence.compile_option[:specialized_instruction] - warn "#{__FILE__}: specialized_instruction is set to false" -end - -require_relative 'test_helper' - -class TestTraceContext < Test::Unit::TestCase - include PowerAssertTestHelper - - class TestInterface < Byebug::Interface - def readline(prompt) - 'next' - end - - def do_nothing(*) - end - - alias puts do_nothing - alias print do_nothing - alias errmsg do_nothing - end - - class << self - def startup - Byebug::Context.interface = TestInterface.new - Byebug::Context.processor = PowerAssertTestHelper::TestProcessor - Byebug::Setting[:autosave] = false - end - - def iseq - :iseq - end - - define_method(:bmethod) do - :bmethod - end - end - - setup do - Byebug.start - end - - teardown do - Byebug.stop - end - - def trace_test(expected_message, file, lineno, binding = TOPLEVEL_BINDING) - code = "byebug\n#{expected_message.each_line.first}\n" - lineno -= 1 # For 'byebug' at the first line - eval(code, binding, file, lineno) - pa = Byebug.current_context.__send__(:processor).pa_context - assert_equal(expected_message, pa.message) - assert_true(pa.enabled?) - pa.disable - assert_false(pa.enabled?) - end - - def test_iseq - trace_test(<