diff --git a/Gemfile b/Gemfile index 454fb24..d553644 100644 --- a/Gemfile +++ b/Gemfile @@ -9,5 +9,3 @@ gem "rake", "~> 13.0" gem "irb" gem "test-unit", "~> 3.0" - -gem "ruby-lsp" diff --git a/Gemfile.lock b/Gemfile.lock index 1efc807..f2b477b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -9,19 +9,10 @@ GEM io-console (0.6.0) irb (1.6.2) reline (>= 0.3.0) - language_server-protocol (3.17.0.3) power_assert (2.0.2) - prettier_print (1.2.0) rake (13.0.6) reline (0.3.2) io-console (~> 0.5) - ruby-lsp (0.3.8) - language_server-protocol (~> 3.17.0) - sorbet-runtime - syntax_tree (>= 5.0.0, < 6) - sorbet-runtime (0.5.10648) - syntax_tree (5.3.0) - prettier_print (>= 1.2.0) test-unit (3.5.5) power_assert @@ -33,7 +24,6 @@ PLATFORMS DEPENDENCIES irb rake (~> 13.0) - ruby-lsp test-unit (~> 3.0) tracer! diff --git a/lib/tracer/base.rb b/lib/tracer/base.rb index 491c4f0..234c0e1 100644 --- a/lib/tracer/base.rb +++ b/lib/tracer/base.rb @@ -70,12 +70,21 @@ def pretty_path(path) end end - def initialize(output: STDOUT, pattern: nil, colorize: nil, depth_offset: 0) + attr_reader :header + + def initialize( + output: STDOUT, + pattern: nil, + colorize: nil, + depth_offset: 0, + header: nil + ) @name = self.class.name @type = @name.sub(/Tracer\z/, "") @output = output @depth_offset = depth_offset @colorize = colorize || colorizable? + @header = header if pattern @pattern = Regexp.compile(pattern) @@ -90,10 +99,6 @@ def key [@type, @pattern, @into].freeze end - def header - "" - end - def to_s s = "#{@name} #{description}" s += " with pattern #{@pattern.inspect}" if @pattern @@ -141,10 +146,14 @@ def skip_internal?(tp) def out(tp, msg = nil, depth: caller.size - 1, location: nil) location ||= "#{tp.path}:#{tp.lineno}" - buff = - "#{header} \#depth:#{"%-2d" % depth}#{msg} at #{colorize("#{location}", [:GREEN])}" + if header + str = +"#{header} " + else + str = +"" + end + str << "\#depth:#{"%-2d" % depth}#{msg} at #{colorize("#{location}", [:GREEN])}" - puts buff + puts str end def puts(msg) diff --git a/test/ruby_tracer/call_tracer_test.rb b/test/ruby_tracer/call_tracer_test.rb deleted file mode 100644 index 493c871..0000000 --- a/test/ruby_tracer/call_tracer_test.rb +++ /dev/null @@ -1,46 +0,0 @@ -require_relative "../test_helper" - -module Tracer - class CallTracerTest < TestCase - include ActivationTests - - private - - def build_tracer - CallTracer.new(output: @output) - end - end - - class CallTracerIntegrationTest < IntegrationTestCase - def test_object_tracer_traces_method_calls - file = write_file("foo.rb", <<~RUBY) - obj = Object.new - - def obj.foo - 100 - end - - def bar(obj) - obj.foo - end - - CallTracer.new.start - - bar(obj) - RUBY - - out, err = execute_file(file) - - assert_empty(err) - assert_traces( - [ - %r{#depth:0 > Object#bar at .*/foo\.rb:13}, - %r{#depth:1 > #\.foo at .*/foo\.rb:8}, - %r{#depth:1 < #\.foo #=> 100 at .*/foo\.rb:8}, - %r{#depth:0 < Object#bar #=> 100 at .*/foo\.rb:13} - ], - out - ) - end - end -end diff --git a/test/tracer/call_tracer_test.rb b/test/tracer/call_tracer_test.rb new file mode 100644 index 0000000..3f67a6d --- /dev/null +++ b/test/tracer/call_tracer_test.rb @@ -0,0 +1,77 @@ +require_relative "../test_helper" + +module Tracer + class CallTracerTest < TestCase + include ActivationTests + + private + + def build_tracer + CallTracer.new(output: @output) + end + end + + class CallTracerIntegrationTest < IntegrationTestCase + def test_object_tracer_traces_method_calls + file = write_file("foo.rb", <<~RUBY) + obj = Object.new + + def obj.foo + 100 + end + + def bar(obj) + obj.foo + end + + CallTracer.new.start + + bar(obj) + RUBY + + out, err = execute_file(file) + + assert_empty(err) + assert_traces( + [ + %r{^#depth:0 > Object#bar at .*/foo\.rb:13}, + %r{^#depth:1 > #\.foo at .*/foo\.rb:8}, + %r{^#depth:1 < #\.foo #=> 100 at .*/foo\.rb:8}, + %r{^#depth:0 < Object#bar #=> 100 at .*/foo\.rb:13} + ], + out + ) + end + + def test_object_tracer_with_header + file = write_file("foo.rb", <<~RUBY) + obj = Object.new + + def obj.foo + 100 + end + + def bar(obj) + obj.foo + end + + CallTracer.new(header: "tracer-1").start + + bar(obj) + RUBY + + out, err = execute_file(file) + + assert_empty(err) + assert_traces( + [ + %r{^tracer-1 #depth:0 > Object#bar at .*/foo\.rb:13}, + %r{^tracer-1 #depth:1 > #\.foo at .*/foo\.rb:8}, + %r{^tracer-1 #depth:1 < #\.foo #=> 100 at .*/foo\.rb:8}, + %r{^tracer-1 #depth:0 < Object#bar #=> 100 at .*/foo\.rb:13} + ], + out + ) + end + end +end diff --git a/test/ruby_tracer/exception_tracer_test.rb b/test/tracer/exception_tracer_test.rb similarity index 56% rename from test/ruby_tracer/exception_tracer_test.rb rename to test/tracer/exception_tracer_test.rb index 23be166..1f40b05 100644 --- a/test/ruby_tracer/exception_tracer_test.rb +++ b/test/tracer/exception_tracer_test.rb @@ -22,7 +22,20 @@ def test_exception_tracer_traces_exceptions out, err = execute_file(file) assert_empty(err) - assert_traces([/#depth:0 # at .*foo.rb:3/], out) + assert_traces([/^#depth:0 # at .*foo.rb:3/], out) + end + + def test_exception_tracer_with_header + file = write_file("foo.rb", <<~RUBY) + ExceptionTracer.new(header: "tracer-1").start + + raise "boom" rescue nil + RUBY + + out, err = execute_file(file) + + assert_empty(err) + assert_traces([/^tracer-1 #depth:0 # at .*foo.rb:3/], out) end end end diff --git a/test/ruby_tracer/helper_test.rb b/test/tracer/helper_test.rb similarity index 100% rename from test/ruby_tracer/helper_test.rb rename to test/tracer/helper_test.rb diff --git a/test/ruby_tracer/line_tracer_test.rb b/test/tracer/line_tracer_test.rb similarity index 54% rename from test/ruby_tracer/line_tracer_test.rb rename to test/tracer/line_tracer_test.rb index 6a1561e..3701130 100644 --- a/test/ruby_tracer/line_tracer_test.rb +++ b/test/tracer/line_tracer_test.rb @@ -23,7 +23,21 @@ def test_line_tracer_traces_line_executions out, err = execute_file(file) assert_empty(err) - assert_traces([/#depth:1 at .*foo.rb:3/, /#depth:1 at .*foo.rb:4/], out) + assert_traces([/^#depth:1 at .*foo.rb:3/, /#depth:1 at .*foo.rb:4/], out) + end + + def test_line_tracer_with_header + file = write_file("foo.rb", <<~RUBY) + LineTracer.new(header: "tracer-1").start + + a = 1 + b = 2 + RUBY + + out, err = execute_file(file) + + assert_empty(err) + assert_traces([/^tracer-1 #depth:1 at .*foo.rb:3/, /#depth:1 at .*foo.rb:4/], out) end end end diff --git a/test/ruby_tracer/object_tracer_test.rb b/test/tracer/object_tracer_test.rb similarity index 66% rename from test/ruby_tracer/object_tracer_test.rb rename to test/tracer/object_tracer_test.rb index 98c2235..9c1421f 100644 --- a/test/ruby_tracer/object_tracer_test.rb +++ b/test/tracer/object_tracer_test.rb @@ -50,8 +50,37 @@ def bar(obj) assert_empty(err) assert_traces( [ - %r{#depth:0 # is used as a parameter obj of Object#bar at .*/foo\.rb:13}, - %r{#depth:1 # receives \.foo at .*/foo\.rb:8} + %r{^#depth:0 # is used as a parameter obj of Object#bar at .*/foo\.rb:13}, + %r{^#depth:1 # receives \.foo at .*/foo\.rb:8} + ], + out + ) + end + + def test_object_tracer_with_header + file = write_file("foo.rb", <<~RUBY) + obj = Object.new + + def obj.foo + 100 + end + + def bar(obj) + obj.foo + end + + ObjectTracer.new(obj, header: "tracer-1").start + + bar(obj) + RUBY + + out, err = execute_file(file) + + assert_empty(err) + assert_traces( + [ + %r{tracer-1 #depth:0 # is used as a parameter obj of Object#bar at .*/foo\.rb:13}, + %r{tracer-1 #depth:1 # receives \.foo at .*/foo\.rb:8} ], out ) @@ -78,8 +107,8 @@ def bar(**kwargs) assert_empty(err) assert_traces( [ - %r{#depth:0 # is used as a parameter in args of Object#foo at .*/foo\.rb:11}, - %r{#depth:0 # is used as a parameter in kwargs of Object#bar at .*/foo\.rb:12} + %r{^#depth:0 # is used as a parameter in args of Object#foo at .*/foo\.rb:11}, + %r{^#depth:0 # is used as a parameter in kwargs of Object#bar at .*/foo\.rb:12} ], out ) @@ -108,9 +137,9 @@ def bar(**kwargs) assert_empty(err) assert_traces( [ - %r{#depth:0 # is used as a parameter in args of Object#foo at .*/foo\.rb:12}, - %r{#depth:1 # is used as a parameter obj of block{} at .*/foo\.rb:4}, - %r{#depth:2 # is used as a parameter in kwargs of Object#bar at .*/foo\.rb:13} + %r{^#depth:0 # is used as a parameter in args of Object#foo at .*/foo\.rb:12}, + %r{^#depth:1 # is used as a parameter obj of block{} at .*/foo\.rb:4}, + %r{^#depth:2 # is used as a parameter in kwargs of Object#bar at .*/foo\.rb:13} ], out ) @@ -138,8 +167,8 @@ def bar(obj) assert_empty(err) assert_traces( [ - %r{#depth:0 # is used as a parameter obj of Object#bar at .*/foo\.rb:13}, - %r{#depth:1 # receives \.foo at .*/foo\.rb:8} + %r{^#depth:0 # is used as a parameter obj of Object#bar at .*/foo\.rb:13}, + %r{^#depth:1 # receives \.foo at .*/foo\.rb:8} ], out ) @@ -174,8 +203,8 @@ def test_object_tracer_works_with_nil_defined_class assert_empty(err) assert_traces( [ - /#depth:-1 # receives #instance_eval \(BasicObject#instance_eval\) at .*foo\.rb:4/, - /#depth:1 # receives at .*foo.rb:4:in `instance_eval'/ + /^#depth:-1 # receives #instance_eval \(BasicObject#instance_eval\) at .*foo\.rb:4/, + /^#depth:1 # receives at .*foo.rb:4:in `instance_eval'/ ], out ) @@ -208,9 +237,9 @@ def bar(obj) assert_empty(err) assert_traces( [ - %r{#depth:0 # is used as a parameter obj of Object#bar at .*/foo\.rb:17}, - %r{#depth:1 # receives \.foo at .*/foo\.rb:12}, - %r{#depth:0 # receives #baz \(Foo#baz\) at .*/foo\.rb:18} + %r{^#depth:0 # is used as a parameter obj of Object#bar at .*/foo\.rb:17}, + %r{^#depth:1 # receives \.foo at .*/foo\.rb:12}, + %r{^#depth:0 # receives #baz \(Foo#baz\) at .*/foo\.rb:18} ], out )