im-lost 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38b1a5b729438621357238f12f64f1d397ee56e18174c2cc1ec60067dd0ab15e
4
- data.tar.gz: 157e15bcf3c9e9539467347e9cac31b5ed40adf9953bc6ab28dab6d163907288
3
+ metadata.gz: 6a11bb08b82dde3d4d56939a25d4898c77ef75ce9e82659511f8a47e6b1d0b9d
4
+ data.tar.gz: 073e42d29b09cd54db36a39d12e334d7cc2a5b9fbd5d2f3447265cd84cc278da
5
5
  SHA512:
6
- metadata.gz: 8ad0cc365f318ef0113d6f099618204b11ecd547a84d525893cc2691a59a5159594c8606de34bad9268867751708cf98f03102a1b0feefbab6cefa41c2436449
7
- data.tar.gz: eb0a3abf3fffc2273593741c880c9aa5b4461d2b14877e324834216327d9ec427a80eaf2b075381df601b920477b50c8b95190c34ae9cc73fb3d1b25407aa4a1
6
+ metadata.gz: eb4ee264f51b598b2b086033958a6eb587934a8d2be08c009f6c6d4c9991b84fd0657b5b691cdde7e50a2fb662316a81b6b38a5d7ada949277c14da99d12021a
7
+ data.tar.gz: 8b183a0464fb8a64a238792347ae697e557440b3cfc58bb26251f7b23ce2ef7ee766f2ca02fd0382ff449f3c17244c45dbfee494122bd6f28efd97f9e1b80e89
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Mike Blumtritt
3
+ Copyright (c) 2024-2025 Mike Blumtritt
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -10,7 +10,7 @@ ImLost helps you by analyzing function calls of objects, informing you about exc
10
10
 
11
11
  ## Description
12
12
 
13
- If you like to undertsand method call details you get a call trace with `ImLost.trace`:
13
+ If you like to understand method call details you get a call trace with `ImLost.trace`:
14
14
 
15
15
  ```ruby
16
16
  File.open('test.txt', 'w') do |file|
@@ -75,8 +75,6 @@ See the [online help](https://rubydoc.info/gems/im-lost/ImLost) for more!
75
75
  ```ruby
76
76
  require 'im-lost'
77
77
 
78
- require_relative '../lib/im-lost'
79
-
80
78
  class Foo
81
79
  def self.create(value:) = new(value)
82
80
 
@@ -109,56 +107,56 @@ my_foo.foo(3) { puts _1 }
109
107
  ImLost.vars(my_foo)
110
108
 
111
109
  # output will look like
112
- # > Foo.create(:foo!)
113
- # /examples/foo.rb:24
114
- # > Foo.new(*)
115
- # /examples/foo.rb:6
116
- # < Foo.new(*)
117
- # /examples/foo.rb:6
118
- # = #<Foo:0x00000001006448c0 @value=:foo!>
119
- # < Foo.create(:foo!)
120
- # /examples/foo.rb:24
121
- # = #<Foo:0x00000001006448c0 @value=:foo!>
122
- # > Foo#foo(1, *[], :none, **{}, &nil)
123
- # /examples/foo.rb:27
124
- # > Foo#bar()
125
- # /examples/foo.rb:15
126
- # < Foo#bar()
127
- # /examples/foo.rb:15
128
- # = :bar
129
- # < Foo#foo(1, *[], :none, **{}, &nil)
130
- # /examples/foo.rb:27
131
- # = "1-none-[]-{}-bar"
132
- # * /examples/foo.rb:28
133
- # > instance variables
134
- # @value: "1-none-[]-{}-bar"
135
- # > Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
136
- # /examples/foo.rb:30
137
- # > Foo#bar()
138
- # /examples/foo.rb:15
139
- # < Foo#bar()
140
- # /examples/foo.rb:15
141
- # = :bar
142
- # < Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
143
- # /examples/foo.rb:30
144
- # = "2-some-[a,b,c]-{:name=>:value}-bar"
145
- # * /examples/foo.rb:31
146
- # > instance variables
147
- # @value: "2-some-[a,b,c]-{:name=>:value}-bar"
148
- # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100641d28 /examples/foo.rb:33>)
149
- # /examples/foo.rb:33
150
- # > Foo#bar()
151
- # /examples/foo.rb:15
152
- # < Foo#bar()
153
- # /examples/foo.rb:15
154
- # = :bar
155
- # 3--[]-{}-bar
156
- # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100641d28 /examples/foo.rb:33>)
157
- # /examples/foo.rb:33
158
- # = nil
159
- # * /examples/foo.rb:34
160
- # > instance variables
161
- # @value: "3--[]-{}-bar"
110
+ # > Foo.create(:foo!)
111
+ # ./examples/foo.rb:24
112
+ # > Foo.new(*args)
113
+ # ./examples/foo.rb:6
114
+ # < Foo.new(*args)
115
+ # ./examples/foo.rb:6
116
+ # = #<Foo:0x0000000104c24b88 @value=:foo!>
117
+ # < Foo.create(:foo!)
118
+ # ./examples/foo.rb:24
119
+ # = #<Foo:0x0000000104c24b88 @value=:foo!>
120
+ # > Foo#foo(1, *[], :none, **{}, &nil)
121
+ # ./examples/foo.rb:27
122
+ # > Foo#bar()
123
+ # ./examples/foo.rb:15
124
+ # < Foo#bar()
125
+ # ./examples/foo.rb:15
126
+ # = :bar
127
+ # < Foo#foo(1, *[], :none, **{}, &nil)
128
+ # ./examples/foo.rb:27
129
+ # = "1-none-[]-{}-bar"
130
+ # * ./examples/foo.rb:28
131
+ # > instance variables
132
+ # @value: "1-none-[]-{}-bar"
133
+ # > Foo#foo(2, *[:a, :b, :c], :some, **{name: :value}, &nil)
134
+ # ./examples/foo.rb:30
135
+ # > Foo#bar()
136
+ # ./examples/foo.rb:15
137
+ # < Foo#bar()
138
+ # ./examples/foo.rb:15
139
+ # = :bar
140
+ # < Foo#foo(2, *[:a, :b, :c], :some, **{name: :value}, &nil)
141
+ # ./examples/foo.rb:30
142
+ # = "2-some-[a,b,c]-{name: :value}-bar"
143
+ # * ./examples/foo.rb:31
144
+ # > instance variables
145
+ # @value: "2-some-[a,b,c]-{name: :value}-bar"
146
+ # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000104c22180 ./examples/foo.rb:33>)
147
+ # ./examples/foo.rb:33
148
+ # > Foo#bar()
149
+ # ./examples/foo.rb:15
150
+ # < Foo#bar()
151
+ # ./examples/foo.rb:15
152
+ # = :bar
153
+ # 3--[]-{}-bar
154
+ # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000104c22180 ./examples/foo.rb:33>)
155
+ # ./examples/foo.rb:33
156
+ # = nil
157
+ # * ./examples/foo.rb:34
158
+ # > instance variables
159
+ # @value: "3--[]-{}-bar"
162
160
  ```
163
161
 
164
162
  See [examples dir](./examples) for more…
data/examples/foo.rb CHANGED
@@ -34,53 +34,53 @@ my_foo.foo(3) { puts _1 }
34
34
  ImLost.vars(my_foo)
35
35
 
36
36
  # output will look like
37
- # > Foo.create(:foo!)
38
- # /examples/foo.rb:24
39
- # > Foo.new(*)
40
- # /examples/foo.rb:6
41
- # < Foo.new(*)
42
- # /examples/foo.rb:6
43
- # = #<Foo:0x00000001006448c0 @value=:foo!>
44
- # < Foo.create(:foo!)
45
- # /examples/foo.rb:24
46
- # = #<Foo:0x00000001006448c0 @value=:foo!>
47
- # > Foo#foo(1, *[], :none, **{}, &nil)
48
- # /examples/foo.rb:27
49
- # > Foo#bar()
50
- # /examples/foo.rb:15
51
- # < Foo#bar()
52
- # /examples/foo.rb:15
53
- # = :bar
54
- # < Foo#foo(1, *[], :none, **{}, &nil)
55
- # /examples/foo.rb:27
56
- # = "1-none-[]-{}-bar"
57
- # * /examples/foo.rb:28
58
- # > instance variables
59
- # @value: "1-none-[]-{}-bar"
60
- # > Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
61
- # /examples/foo.rb:30
62
- # > Foo#bar()
63
- # /examples/foo.rb:15
64
- # < Foo#bar()
65
- # /examples/foo.rb:15
66
- # = :bar
67
- # < Foo#foo(2, *[:a, :b, :c], :some, **{:name=>:value}, &nil)
68
- # /examples/foo.rb:30
69
- # = "2-some-[a,b,c]-{:name=>:value}-bar"
70
- # * /examples/foo.rb:31
71
- # > instance variables
72
- # @value: "2-some-[a,b,c]-{:name=>:value}-bar"
73
- # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100641d28 /examples/foo.rb:33>)
74
- # /examples/foo.rb:33
75
- # > Foo#bar()
76
- # /examples/foo.rb:15
77
- # < Foo#bar()
78
- # /examples/foo.rb:15
79
- # = :bar
80
- # 3--[]-{}-bar
81
- # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000100641d28 /examples/foo.rb:33>)
82
- # /examples/foo.rb:33
83
- # = nil
84
- # * /examples/foo.rb:34
85
- # > instance variables
86
- # @value: "3--[]-{}-bar"
37
+ # > Foo.create(:foo!)
38
+ # ./examples/foo.rb:24
39
+ # > Foo.new(*args)
40
+ # ./examples/foo.rb:6
41
+ # < Foo.new(*args)
42
+ # ./examples/foo.rb:6
43
+ # = #<Foo:0x0000000104c24b88 @value=:foo!>
44
+ # < Foo.create(:foo!)
45
+ # ./examples/foo.rb:24
46
+ # = #<Foo:0x0000000104c24b88 @value=:foo!>
47
+ # > Foo#foo(1, *[], :none, **{}, &nil)
48
+ # ./examples/foo.rb:27
49
+ # > Foo#bar()
50
+ # ./examples/foo.rb:15
51
+ # < Foo#bar()
52
+ # ./examples/foo.rb:15
53
+ # = :bar
54
+ # < Foo#foo(1, *[], :none, **{}, &nil)
55
+ # ./examples/foo.rb:27
56
+ # = "1-none-[]-{}-bar"
57
+ # * ./examples/foo.rb:28
58
+ # > instance variables
59
+ # @value: "1-none-[]-{}-bar"
60
+ # > Foo#foo(2, *[:a, :b, :c], :some, **{name: :value}, &nil)
61
+ # ./examples/foo.rb:30
62
+ # > Foo#bar()
63
+ # ./examples/foo.rb:15
64
+ # < Foo#bar()
65
+ # ./examples/foo.rb:15
66
+ # = :bar
67
+ # < Foo#foo(2, *[:a, :b, :c], :some, **{name: :value}, &nil)
68
+ # ./examples/foo.rb:30
69
+ # = "2-some-[a,b,c]-{name: :value}-bar"
70
+ # * ./examples/foo.rb:31
71
+ # > instance variables
72
+ # @value: "2-some-[a,b,c]-{name: :value}-bar"
73
+ # > Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000104c22180 ./examples/foo.rb:33>)
74
+ # ./examples/foo.rb:33
75
+ # > Foo#bar()
76
+ # ./examples/foo.rb:15
77
+ # < Foo#bar()
78
+ # ./examples/foo.rb:15
79
+ # = :bar
80
+ # 3--[]-{}-bar
81
+ # < Foo#foo(3, *[], nil, **{}, &#<Proc:0x0000000104c22180 ./examples/foo.rb:33>)
82
+ # ./examples/foo.rb:33
83
+ # = nil
84
+ # * ./examples/foo.rb:34
85
+ # > instance variables
86
+ # @value: "3--[]-{}-bar"
@@ -2,5 +2,5 @@
2
2
 
3
3
  module ImLost
4
4
  # The version number of the gem.
5
- VERSION = '1.2.0'
5
+ VERSION = '1.2.2'
6
6
  end
data/lib/im-lost.rb CHANGED
@@ -54,7 +54,7 @@ module ImLost
54
54
  return @output = value if defined?(value.<<)
55
55
  raise(
56
56
  NoMethodError,
57
- "undefined method `<<' for an instance of #{
57
+ "undefined method '#<<' for an instance of #{
58
58
  Kernel.instance_method(:class).bind(value).call
59
59
  }"
60
60
  )
@@ -73,18 +73,18 @@ module ImLost
73
73
  # @attribute [r] trace_calls
74
74
  # @return [Boolean] whether method calls will be traced
75
75
  #
76
- def trace_calls = @trace_calls[0].enabled?
76
+ def trace_calls = @trace_calls.enabled?
77
77
 
78
78
  def trace_calls=(value)
79
79
  if value
80
- @trace_calls.each(&:enable) unless trace_calls
80
+ @trace_calls.enable unless trace_calls
81
81
  elsif trace_calls
82
- @trace_calls.each(&:disable)
82
+ @trace_calls.disable
83
83
  end
84
84
  end
85
85
 
86
86
  #
87
- # Traces execptions raised within a given block.
87
+ # Traces exceptions raised within a given block.
88
88
  #
89
89
  # @example Trace exception and rescue handling
90
90
  # ImLost.trace_exceptions do
@@ -101,36 +101,38 @@ module ImLost
101
101
  # # x RuntimeError: something went wrong!
102
102
  # # /examples/test.rb:4
103
103
  #
104
- # @param with_locations [Boolean] wheter the locations should be included
104
+ # @param with_locations [Boolean] whether the locations should be included
105
105
  # into the exception trace information
106
106
  # @yieldreturn [Object] return result
107
107
  #
108
108
  def trace_exceptions(with_locations: true)
109
109
  return unless block_given?
110
- we = @trace_exceptions.enabled?
111
- el = @exception_locations
112
- @exception_locations = with_locations
113
- @trace_exceptions.enable unless we
114
- yield
115
- ensure
116
- @trace_exceptions.disable unless we
117
- @exception_locations = el
110
+ begin
111
+ we = @trace_exceptions.enabled?
112
+ el = @exception_locations
113
+ @exception_locations = with_locations
114
+ @trace_exceptions.enable unless we
115
+ yield
116
+ ensure
117
+ @trace_exceptions.disable unless we
118
+ @exception_locations = el
119
+ end
118
120
  end
119
121
 
120
122
  #
121
- # Enables/disables tracing of returned valuess of method calls.
123
+ # Enables/disables tracing of returned values of method calls.
122
124
  # This is enabled by default.
123
125
  #
124
126
  # @attribute [r] trace_results
125
127
  # @return [Boolean] whether return values will be traced
126
128
  #
127
- def trace_results = @trace_results[0].enabled?
129
+ def trace_results = @trace_results.enabled?
128
130
 
129
131
  def trace_results=(value)
130
132
  if value
131
- @trace_results.each(&:enable) unless trace_results
133
+ @trace_results.enable unless trace_results
132
134
  elsif trace_results
133
- @trace_results.each(&:disable)
135
+ @trace_results.disable
134
136
  end
135
137
  end
136
138
 
@@ -259,7 +261,7 @@ module ImLost
259
261
  #
260
262
  # Inspect internal variables of a given object.
261
263
  #
262
- # @note The dedictaed handling of `Fiber` is platform dependend!
264
+ # @note The dedicated handling of `Fiber` is platform dependent!
263
265
  #
264
266
  # @example Inspect current instance variables
265
267
  # @a = 22
@@ -303,19 +305,18 @@ module ImLost
303
305
  # @return [Object] the given object
304
306
  #
305
307
  def vars(object)
306
- out = Out.new
308
+ out = LineStore.new
307
309
  traced = @trace.delete(object)
308
310
  return _local_vars(out, object) if Binding === object
309
- location = Kernel.caller_locations(1, 1)[0]
310
- out << "* #{location.path}:#{location.lineno}"
311
+ out.location(Kernel.caller_locations(1, 1)[0])
311
312
  return _thread_vars(out, object) if Thread === object
312
- return _fiber_vars(out, object) if @fiber_supported && Fiber === object
313
+ return _fiber_vars(out, object) if @fiber_support && Fiber === object
313
314
  return _instance_vars(out, object) if defined?(object.instance_variables)
314
315
  out << ' !!! unable to retrieve vars'
315
316
  object
316
317
  ensure
317
318
  @trace[traced] = traced if traced
318
- out.flush(@output)
319
+ @output << out
319
320
  end
320
321
 
321
322
  private
@@ -329,10 +330,7 @@ module ImLost
329
330
  arg
330
331
  end
331
332
 
332
- def _trace_all(args)
333
- args.each { |arg| @trace[arg] = arg if _can_trace?(arg) }
334
- args
335
- end
333
+ def _trace_all(args) = args.each { @trace[_1] = _1 if _can_trace?(_1) }
336
334
 
337
335
  def _trace_b(arg)
338
336
  return yield(arg) if @trace.key?(arg) || !_can_trace?(arg)
@@ -384,20 +382,17 @@ module ImLost
384
382
  end
385
383
 
386
384
  def _instance_vars(out, object)
387
- out.vars('instance variables', object.instance_variables) do |n|
388
- object.instance_variable_get(n)
385
+ out.vars('instance variables', object.instance_variables) do |name|
386
+ object.instance_variable_get(name)
389
387
  end
390
388
  object
391
389
  end
392
390
 
393
- def _thread_identifier(thread)
394
- "#{THREAD_STATE[thread.status] || thread.status} Thread #{
395
- if defined?(thread.native_thread_id)
396
- thread.native_thread_id
397
- else
398
- thread.__id__
399
- end
400
- } #{thread.name}".rstrip
391
+ def _thread_identifier(thr)
392
+ state = thr.status
393
+ "#{state || (state.nil? ? 'aborted' : 'terminated')} Thread #{
394
+ defined?(thr.native_thread_id) ? thr.native_thread_id : thr.__id__
395
+ } #{thr.name}".rstrip
401
396
  end
402
397
  end
403
398
 
@@ -456,12 +451,16 @@ module ImLost
456
451
  def count = ids.size
457
452
 
458
453
  # @attribute [r] empty?
459
- # @return [Boolean] wheter the timer store is empty or not
454
+ # @return [Boolean] whether the timer store is empty or not
460
455
  def empty? = ids.empty?
461
456
 
462
457
  # @attribute [r] ids
463
458
  # @return [Array<Integer>] IDs of all registered timers
464
- def ids = (@ll.keys.keep_if { _1.is_a?(Integer) })
459
+ def ids = @ll.keys.keep_if { Integer === _1 }
460
+
461
+ # @attribute [r] names
462
+ # @return [Array<String>] names of all registered named timers
463
+ def names = @ll.keys.delete_if { Integer === _1 }
465
464
 
466
465
  #
467
466
  # Create and register a new named or anonymous timer.
@@ -487,7 +486,7 @@ module ImLost
487
486
  #
488
487
  def delete(*id_or_names)
489
488
  id_or_names.flatten.each do |id|
490
- if id.is_a?(Integer)
489
+ if Integer === id
491
490
  del = @ll.delete(id)
492
491
  @ll.delete(del[0]) if del
493
492
  else
@@ -498,6 +497,16 @@ module ImLost
498
497
  nil
499
498
  end
500
499
 
500
+ #
501
+ # Delete and unregister all timers.
502
+ #
503
+ # @return [self] itself
504
+ #
505
+ def clear
506
+ @ll = {}
507
+ self
508
+ end
509
+
501
510
  #
502
511
  # Print the ID or name and the runtime since a timer was created.
503
512
  # It includes the location.
@@ -508,10 +517,10 @@ module ImLost
508
517
  # identifier or name
509
518
  #
510
519
  def [](id_or_name)
511
- time = self.class.now
512
- timer = @ll[id_or_name.is_a?(Integer) ? id_or_name : id_or_name.to_s]
520
+ now = self.class.now
521
+ timer = @ll[Integer === id_or_name ? id_or_name : id_or_name.to_s]
513
522
  raise(ArgumentError, "not a timer - #{id_or_name.inspect}") unless timer
514
- @cb[timer[0], Kernel.caller_locations(1, 1)[0], time - timer[1]]
523
+ @cb[timer[0], Kernel.caller_locations(1, 1)[0], (now - timer[1]).round(4)]
515
524
  timer.__id__
516
525
  end
517
526
 
@@ -528,125 +537,131 @@ module ImLost
528
537
  nil
529
538
  end
530
539
 
531
- # @!visibility private
540
+ private
541
+
532
542
  def initialize(&block)
533
543
  @cb = block
534
- @ll = {}
544
+ clear
535
545
  end
536
546
  end
537
547
 
538
- class Out
548
+ class LineStore
539
549
  def initialize(*lines) = (@lines = lines)
550
+ def to_s = (@lines << nil).join("\n")
540
551
  def <<(str) = @lines << str
541
- def location(loc) = @lines << " #{loc.path}:#{loc.lineno}"
542
- def flush(dev) = dev << (@lines << nil).join("\n")
552
+ def location(loc) = @lines << "* #{loc.path}:#{loc.lineno}"
543
553
 
544
- def sig(prefix, info, args)
545
- args = args.join(', ')
546
- @lines << case info.self
554
+ def vars(kind, names)
555
+ return @lines << " <no #{kind} defined>" if names.empty?
556
+ @lines << " > #{kind}"
557
+ names.sort!.each { @lines << " #{_1}: #{yield(_1).inspect}" }
558
+ end
559
+ end
560
+ private_constant :LineStore
561
+
562
+ class CCallLineStore < LineStore
563
+ def initialize(prefix, info, include_location)
564
+ @info = info
565
+ sig = "#{info.method_id}(#{args.join(', ')})"
566
+ case info.self
547
567
  when Class, Module
548
- "#{prefix} #{info.self}.#{info.method_id}(#{args})"
568
+ super("#{prefix} #{info.self}.#{sig}")
549
569
  else
550
- "#{prefix} #{info.defined_class}##{info.method_id}(#{args})"
570
+ super("#{prefix} #{info.defined_class}##{sig}")
551
571
  end
572
+ return unless include_location
573
+ loc = location
574
+ path = loc.path
575
+ path = path[10..-2] if path.start_with?('<internal:')
576
+ @lines << " #{path}:#{loc.lineno}"
552
577
  end
553
578
 
554
- def vars(kind, names)
555
- return @lines << " <no #{kind} defined>" if names.empty?
556
- @lines << " > #{kind}"
557
- names.sort!.each { @lines << " #{_1}: #{yield(_1).inspect}" }
579
+ def location = @info
580
+
581
+ def args
582
+ argc = -1
583
+ @info.parameters.map do |kind, _|
584
+ argc += 1
585
+ CARG_TYPE[kind] || "arg#{argc}"
586
+ end
558
587
  end
588
+
589
+ CARG_TYPE = {
590
+ rest: '*args',
591
+ keyrest: '**kwargs',
592
+ block: '&block'
593
+ }.compare_by_identity.freeze
559
594
  end
560
- private_constant :Out
595
+ private_constant :CCallLineStore
561
596
 
562
- ARG_SIG = { rest: '*', keyrest: '**', block: '&' }.compare_by_identity.freeze
563
- NO_NAME = { :* => 1, :** => 1, :& => 1 }.compare_by_identity.freeze
564
- THREAD_STATE = {
565
- false => 'terminated',
566
- nil => 'aborted'
567
- }.compare_by_identity.freeze
568
- private_constant :ARG_SIG, :NO_NAME, :THREAD_STATE
597
+ class RbCallLineStore < CCallLineStore
598
+ def initialize(prefix, info, include_location)
599
+ @ctx = info.binding
600
+ super
601
+ @ctx = nil
602
+ end
569
603
 
570
- @trace = {}.compare_by_identity
571
- @caller_locations = @exception_locations = true
572
- @output = STDERR
604
+ def location
605
+ locations = @ctx.eval('caller_locations(7,3)')
606
+ unless locations[1].path.start_with?('<internal:prelude')
607
+ return locations[1]
608
+ end
609
+ locations[0].path.start_with?('<internal:') ? locations[0] : locations[2]
610
+ end
573
611
 
574
- @timer = TimerStore.new { |title, location, time| @output << <<~TIMER_MSG }
575
- T #{title}: #{time ? "#{time} sec." : 'created'}
576
- #{location.path}:#{location.lineno}
577
- TIMER_MSG
578
- TimerStore.private_class_method(:new)
612
+ def args
613
+ @info.parameters.map do |kind, name|
614
+ next name if ARG_SKIP.key?(name)
615
+ "#{ARG_TYPE[kind]}#{@ctx.local_variable_get(name).inspect}"
616
+ end
617
+ end
579
618
 
580
- @trace_calls = [
581
- TracePoint.new(:c_call) do |tp|
582
- next if !@trace.key?(tp.self) || tp.path == __FILE__
583
- out = Out.new
584
- out.sig('>', tp, tp.parameters.map { ARG_SIG[_1[0]] || '?' })
585
- out.location(tp) if @caller_locations
586
- out.flush(@output)
587
- end,
588
- TracePoint.new(:call) do |tp|
619
+ ARG_TYPE = { rest: :*, keyrest: :**, block: :& }.compare_by_identity.freeze
620
+ ARG_SKIP = ARG_TYPE.invert.compare_by_identity.freeze
621
+ end
622
+ private_constant :RbCallLineStore
623
+
624
+ @trace_calls =
625
+ TracePoint.new(:c_call, :call) do |tp|
589
626
  next if !@trace.key?(tp.self) || tp.path == __FILE__
590
- ctx = tp.binding
591
- out = Out.new
592
- out.sig(
593
- '>',
594
- tp,
595
- tp.parameters.map do |kind, name|
596
- next name if NO_NAME.key?(name)
597
- "#{ARG_SIG[kind]}#{ctx.local_variable_get(name).inspect}"
598
- end
599
- )
600
- out.location(ctx.eval('caller_locations(4,1)')[0]) if @caller_locations
601
- out.flush(@output)
627
+ klass = tp.event == :c_call ? CCallLineStore : RbCallLineStore
628
+ @output << klass.new('>', tp, @caller_locations).to_s
602
629
  end
603
- ]
604
630
 
605
- @trace_results = [
606
- TracePoint.new(:c_return) do |tp|
631
+ @trace_results =
632
+ TracePoint.new(:c_return, :return) do |tp|
607
633
  next if !@trace.key?(tp.self) || tp.path == __FILE__
608
- out = Out.new
609
- out.sig('<', tp, tp.parameters.map { ARG_SIG[_1[0]] || '?' })
610
- out.location(tp) if @caller_locations
611
- out << " = #{tp.return_value.inspect}"
612
- out.flush(@output)
613
- end,
614
- TracePoint.new(:return) do |tp|
615
- next if !@trace.key?(tp.self) || tp.path == __FILE__
616
- ctx = tp.binding
617
- out = Out.new
618
- out.sig(
619
- '<',
620
- tp,
621
- tp.parameters.map do |kind, name|
622
- next name if NO_NAME.key?(name)
623
- "#{ARG_SIG[kind]}#{ctx.local_variable_get(name).inspect}"
624
- end
625
- )
626
- out.location(ctx.eval('caller_locations(4,1)')[0]) if @caller_locations
634
+ klass = tp.event == :c_return ? CCallLineStore : RbCallLineStore
635
+ out = klass.new('<', tp, @caller_locations)
627
636
  out << " = #{tp.return_value.inspect}"
628
- out.flush(@output)
637
+ @output << out.to_s
629
638
  end
630
- ]
631
639
 
632
- supported = RUBY_VERSION.to_f < 3.3 ? %i[raise] : %i[raise rescue]
640
+ exception_support = RUBY_VERSION.to_f < 3.3 ? %i[raise] : %i[raise rescue]
633
641
  @trace_exceptions =
634
- TracePoint.new(*supported) do |tp|
642
+ TracePoint.new(*exception_support) do |tp|
635
643
  ex = tp.raised_exception
636
644
  mark, parent = tp.event == :rescue ? ['!', ex.cause] : 'x'
637
645
  ex = ex.inspect
638
- out = Out.new("#{mark} #{ex[0] == '#' ? ex[2..-2] : ex}")
646
+ out = LineStore.new("#{mark} #{ex[0] == '#' ? ex[2..-2] : ex}")
639
647
  while parent
640
648
  ex = parent.inspect
641
649
  out << " [#{ex[0] == '#' ? ex[2..-2] : ex}]"
642
650
  parent = parent.cause
643
651
  end
644
- out.location(tp) if @exception_locations
645
- out.flush(@output)
652
+ out << " #{tp.path}:#{tp.lineno}" if @exception_locations
653
+ @output << out.to_s
646
654
  end
647
655
 
648
- @fiber_supported =
649
- !!(defined?(Fiber.current) && defined?(Fiber.current.storage))
656
+ @timer = TimerStore.new { |title, location, time| @output << <<~TIMER_MSG }
657
+ T #{title}: #{time ? "#{time} sec." : 'created'}
658
+ #{location.path}:#{location.lineno}
659
+ TIMER_MSG
660
+ TimerStore.private_class_method(:new)
650
661
 
662
+ untrace_all!
663
+ @output = STDERR
664
+ @fiber_support = !!defined?(Fiber.current.storage)
665
+ @caller_locations = @exception_locations = true
651
666
  self.trace_calls = self.trace_results = true
652
667
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: im-lost
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-06-18 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: |
14
13
  If you have overlooked something again and don't really understand what
@@ -19,12 +18,11 @@ description: |
19
18
  ImLost helps you by analyzing function calls of objects, informing you
20
19
  about exceptions and logging your way through your code. In short, ImLost
21
20
  is your debugging helper!
22
- email:
23
21
  executables: []
24
22
  extensions: []
25
23
  extra_rdoc_files:
26
- - README.md
27
24
  - LICENSE
25
+ - README.md
28
26
  files:
29
27
  - LICENSE
30
28
  - README.md
@@ -42,7 +40,6 @@ metadata:
42
40
  bug_tracker_uri: https://github.com/mblumtritt/im-lost/issues
43
41
  documentation_uri: https://rubydoc.info/gems/im-lost
44
42
  rubygems_mfa_required: 'true'
45
- post_install_message:
46
43
  rdoc_options: []
47
44
  require_paths:
48
45
  - lib
@@ -57,8 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
57
54
  - !ruby/object:Gem::Version
58
55
  version: '0'
59
56
  requirements: []
60
- rubygems_version: 3.5.13
61
- signing_key:
57
+ rubygems_version: 3.6.8
62
58
  specification_version: 4
63
59
  summary: Your debugging helper.
64
60
  test_files: []