rshade 0.2.0 → 0.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: 39758f070ab0a6b6e7dc0bdc09aa03bb107130f84fe7115331189a31c0e013eb
4
- data.tar.gz: 0331bdd526cd0155df7d210603bb07a15c9541bcce62197b2754731e640060c3
3
+ metadata.gz: e267f5e11b2c8624bc38c88c031a12e9b252b5581b803fe4076f40d532d75c81
4
+ data.tar.gz: 153c3b896ce3701be9bc26a9501f987220e23c8ebb4e253d42a0968cf2e43709
5
5
  SHA512:
6
- metadata.gz: b0c97b53d02f997d05484e850655dfe561c82da1d110a111022885278ece826b5fc75b2e5d70260ff59095ca29178e681c85915301a6b171efe263aa42c82f64
7
- data.tar.gz: ed9a95bceb71f94cd17587bd88086a6e26d77b5a19fe14ed96b4cfbd559fa1574ffaca380ec3fc49167e788197008bc08b581f83fb5997fb058dedba77e49bf8
6
+ metadata.gz: a0c00f405183f7f3a5a33d7e9fd9b5bf4cc4692aabc6cf7400bc32b4fb3e704c0e94b583da98447a868f5c7079b290df835e8f0ed75d8ec66544404748df5466
7
+ data.tar.gz: 273df7e4c8b3107bb8fb5a09c1ef36c8489caf2f5e87550aaa9631b79bd0cdc3a7f4a5641db2f38107e6c28203e0f21a7a51f4e2e47d5da47ab7d3f5d1d89e66
data/.rubocop.yml ADDED
@@ -0,0 +1,31 @@
1
+ # The behavior of RuboCop can be controlled via the .rubocop.yml
2
+ # configuration file. It makes it possible to enable/disable
3
+ # certain cops (checks) and to alter their behavior if they accept
4
+ # any parameters. The file can be placed either in your home
5
+ # directory or in some project directory.
6
+ #
7
+ # RuboCop will start looking for the configuration file in the directory
8
+ # where the inspected file is and continue its way up to the root directory.
9
+ #
10
+ # See https://docs.rubocop.org/rubocop/configuration
11
+ AllCops:
12
+ NewCops: enable
13
+ Exclude:
14
+ - 'spec/fixture/**/*'
15
+ Style/HashSyntax:
16
+ EnforcedShorthandSyntax: never
17
+
18
+ Naming/MethodParameterName:
19
+ Exclude:
20
+ - spec/**/*
21
+ - test.rb
22
+ Style/Documentation:
23
+ Enabled: false
24
+ Metrics/BlockLength:
25
+ Max: 75
26
+ Metrics/MethodLength:
27
+ Max: 30
28
+ Metrics/PerceivedComplexity:
29
+ Max: 10
30
+ Metrics/AbcSize:
31
+ Max: 30
data/Gemfile CHANGED
@@ -9,6 +9,9 @@ gemspec
9
9
 
10
10
  group :development, :test do
11
11
  gem 'binding_of_caller'
12
+ gem 'bundler', '~> 2.2.33'
12
13
  gem 'prism'
13
14
  gem 'pry'
15
+ gem 'rake', '>= 12.3.3'
16
+ gem 'rspec', '~> 3.0'
14
17
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rshade (0.2.0)
4
+ rshade (0.2.2)
5
5
  binding_of_caller
6
6
  colorize
7
7
  prism
@@ -12,7 +12,7 @@ GEM
12
12
  binding_of_caller (1.0.1)
13
13
  debug_inspector (>= 1.2.0)
14
14
  coderay (1.1.3)
15
- colorize (0.8.1)
15
+ colorize (1.1.0)
16
16
  debug_inspector (1.2.0)
17
17
  diff-lcs (1.5.0)
18
18
  method_source (1.0.0)
data/README.md CHANGED
@@ -16,6 +16,14 @@ gem install rshade
16
16
  Simple wrap code that you want to check in to block and it will pretty print all of the calls which was made in this block with pointing line of executions, variables what was pass
17
17
  inside methods and variables what was return
18
18
  ```ruby
19
+ # config
20
+ ::RShade::Config::Registry.instance.trace_config do |config|
21
+ config.exclude_gems!
22
+ filepath = File.join(Rails.root, 'log', 'rshade-trace.json.log')
23
+ config.formatter!(:json, { filepath: filepath, pretty: false })
24
+ end
25
+
26
+ # execute
19
27
  RShade::Trace.reveal do
20
28
  #your code here
21
29
  end.show
@@ -34,25 +42,41 @@ change this behaviour or add your own filter. Even when some piece of code are n
34
42
 
35
43
  ### Configuration
36
44
  ```ruby
37
- config = ::RShade::Config.default
38
-
39
- RShade::Trace.reveal(config) do
40
- end.show
45
+ ::RShade::Config::Registry.instance.trace_config do |config|
46
+ # exclude gems
47
+ config.exclude_gems!
48
+ # path where save output
49
+ filepath = File.join(Rails.root, 'log', 'rshade-trace.json.log')
50
+ # output can be json or stdout
51
+ config.formatter!(:json, { filepath: filepath, pretty: false })
52
+ end
41
53
  ```
42
54
  ### Filters
43
55
  Filters by default represent by expression `(include_path or variable_match) or (not exclude_path)`
44
56
  Filters can be chained like:
45
57
  ```ruby
46
- config = ::RShade::Config.default.include_paths { |paths| paths << /devise/ }
47
- .exclude_paths { |paths| paths << /warden/ }
48
- .match_variable { |name, value| name == :current_user }
58
+ ::RShade::Config::Registry.instance.trace_config do |config|
59
+ config.filter!(RShade::Filter::VariableFilter) do |name, value|
60
+ name == :current_user
61
+ end
62
+ config.filter!(::RShade::Filter::ExcludePathFilter) do |paths|
63
+ paths.concat(/gems/)
64
+ end
65
+ config.filter!(::RShade::Filter::IncludePathFilter) do |paths|
66
+ paths.concat(/devise/)
67
+ end
68
+ end
49
69
  ```
50
70
  #### Filter by path include
51
71
  `paths` - is array which accept regex or string
52
72
  ```ruby
53
- config = ::RShade::Config.default.include_paths { |paths| paths << /devise/ }
73
+ ::RShade::Config::Registry.instance.trace_config do |config|
74
+ config.filter!(::RShade::Filter::IncludePathFilter) do |paths|
75
+ paths.concat(/devise/)
76
+ end
77
+ end
54
78
 
55
- RShade::Trace.reveal(config) do
79
+ RShade::Trace.reveal do
56
80
  #your code
57
81
  end.show
58
82
 
@@ -60,9 +84,13 @@ end.show
60
84
  #### Filter by path exclude
61
85
  `paths` - is array which accept regex or string
62
86
  ```ruby
63
- config = ::RShade::Config.default.exclude_paths { |paths| paths << /devise/ }
87
+ ::RShade::Config::Registry.instance.trace_config do |config|
88
+ config.filter!(::RShade::Filter::ExcludePathFilter) do |paths|
89
+ paths.concat(/gems/)
90
+ end
91
+ end
64
92
 
65
- RShade::Trace.reveal(config) do
93
+ RShade::Trace.reveal do
66
94
  #your code
67
95
  end.show
68
96
  ```
@@ -71,9 +99,14 @@ end.show
71
99
  `name` - represent variable name as symbol
72
100
  `value` - actual variable value
73
101
  ```ruby
74
- config = ::RShade::Config.default.match_variable { |name, value| name == :current_user }
75
102
 
76
- RShade::Trace.reveal(config) do
103
+ ::RShade::Config::Registry.instance.trace_config do |config|
104
+ config.filter!(RShade::Filter::VariableFilter) do |name, value|
105
+ name == :current_user
106
+ end
107
+ end
108
+
109
+ RShade::Trace.reveal do
77
110
  #your code
78
111
  end.show
79
112
  ```
@@ -102,11 +135,18 @@ As you can see all code that have been in use is printed.
102
135
 
103
136
  ## Stack reveal
104
137
  Config
138
+
105
139
  ```ruby
106
140
  ::RShade::Config::Registry.instance.stack_config do |config|
107
- config.exclude_gems!
108
- filepath = File.join(Rails.root, 'log', 'rshade-stack.json.log')
109
- config.set_formatter(:json, { filepath: filepath, pretty: false })
141
+ config.exclude_gems!
142
+ filepath = File.join(Rails.root, 'log', 'rshade-stack.json.log')
143
+ config.formatter!(:json, { filepath: filepath, pretty: false })
144
+
145
+ config.serializer!({
146
+ ActionDispatch::Request => ->(value) do
147
+ "#{value.to_s} -> #{value.method} -> #{value.path}"
148
+ end
149
+ })
110
150
  end
111
151
  ```
112
152
 
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RShade
4
+ class Config
5
+ class EventStore
6
+ attr_reader :filter, :formatter, :tp_events, :variable_serializer
7
+
8
+ DEFAULT_FORMATTER = {
9
+ json: ::RShade::Formatter::Trace::Json,
10
+ stdout: ::RShade::Formatter::Trace::Stdout
11
+ }.freeze
12
+
13
+ def self.default
14
+ new.exclude_gems!
15
+ end
16
+
17
+ # @param [Array<Symbol>] tp_events
18
+ # @param [RShade::Formatter::Trace::Stdout] formatter
19
+ # @param [RShade::Filter::FilterComposition] filter
20
+ # @param [Hash] serializers
21
+ def initialize(tp_events: %i[call return], formatter: RShade::Formatter::Trace::Stdout.new,
22
+ filter: default_filter_composition,
23
+ serializers: {})
24
+ @filter = filter
25
+ @formatter = formatter
26
+ @tp_events = tp_events
27
+ @variable_serializer = serializers
28
+ end
29
+
30
+ def tp_events!(tp_events)
31
+ @tp_events = tp_events
32
+ self
33
+ end
34
+
35
+ def serializer!(hash)
36
+ variable_serializer.merge!(hash)
37
+ self
38
+ end
39
+
40
+ def filter!(filter_type, &block)
41
+ filter.filter(filter_type, &block)
42
+ self
43
+ end
44
+
45
+ def formatter!(formatter, opts = {})
46
+ @formatter = formatter.is_a?(Symbol) ? set_symbol_formatter(formatter, opts) : formatter
47
+ self
48
+ end
49
+
50
+ def exclude_gems!
51
+ filter!(::RShade::Filter::ExcludePathFilter) do |paths|
52
+ paths.concat(RShade::Utils.default_excluded_path)
53
+ end
54
+ self
55
+ end
56
+
57
+ private
58
+
59
+ def set_symbol_formatter(type, opts)
60
+ formatter_class = DEFAULT_FORMATTER[type]
61
+ return formatter_class unless formatter_class
62
+
63
+ @formatter = formatter_class.new(**opts)
64
+ end
65
+
66
+ def default_filter_composition
67
+ variable_filter = RShade::Filter::VariableFilter.new
68
+ include_filter = RShade::Filter::IncludePathFilter.new
69
+ exclude_filter = RShade::Filter::ExcludePathFilter.new
70
+
71
+ RShade::Filter::FilterBuilder.build([:or,
72
+ [:or, variable_filter, include_filter], exclude_filter])
73
+ end
74
+ end
75
+ end
76
+ end
@@ -3,9 +3,11 @@
3
3
  module RShade
4
4
  class Config
5
5
  class Registry
6
+ include Singleton
6
7
  attr_reader :map, :mutex
7
8
 
8
- include Singleton
9
+ DEFAULT_EVENT_STORE = :event_store_default
10
+ DEFAULT_STACK_STORE = :stack_store_default
9
11
 
10
12
  def initialize
11
13
  @map = {}
@@ -13,33 +15,51 @@ module RShade
13
15
  defaults
14
16
  end
15
17
 
16
- def set_default_stack(config)
18
+ def default_stack_config
19
+ val = nil
17
20
  mutex.synchronize do
18
- map[:store_default] = config
21
+ val = map[DEFAULT_STACK_STORE]
19
22
  end
23
+ val
20
24
  end
21
25
 
22
- def default_stack_config
26
+ def stack_config(&block)
27
+ val = nil
28
+ mutex.synchronize do
29
+ val = ::RShade::Config::StackStore.new
30
+ block.call(val)
31
+ map[DEFAULT_STACK_STORE] = val
32
+ end
33
+ val
34
+ end
35
+
36
+ def default_trace_config
23
37
  val = nil
24
38
  mutex.synchronize do
25
- val = map[:store_default]
39
+ val = map[DEFAULT_EVENT_STORE]
26
40
  end
27
41
  val
28
42
  end
29
43
 
30
- def stack_config(&block)
44
+ def trace_config(&block)
31
45
  val = nil
32
46
  mutex.synchronize do
33
- val = ::RShade::Config::StackStore.new
47
+ val = ::RShade::Config::EventStore.new
34
48
  block.call(val)
35
- map[:store_default] = val
49
+ map[DEFAULT_EVENT_STORE] = val
36
50
  end
37
51
  val
38
52
  end
39
53
 
40
54
  def defaults
41
55
  mutex.synchronize do
42
- map[:store_default] = ::RShade::Config::StackStore.new
56
+ stack_store = ::RShade::Config::StackStore.new
57
+ stack_store.exclude_gems!
58
+ map[DEFAULT_STACK_STORE] = stack_store
59
+
60
+ event_store = ::RShade::Config::EventStore.new
61
+ event_store.exclude_gems!
62
+ map[DEFAULT_EVENT_STORE] = event_store
43
63
  end
44
64
  end
45
65
  end
@@ -3,39 +3,41 @@
3
3
  module RShade
4
4
  class Config
5
5
  class StackStore
6
- attr_reader :filter, :formatter, :custom_serializers
6
+ attr_reader :filter, :formatter, :variable_serializer
7
7
 
8
8
  DEFAULT_FORMATTER = {
9
- json: ::RShade::Formatter::Stack::Json
9
+ json: ::RShade::Formatter::Stack::Json,
10
+ stdout: ::RShade::Formatter::Stack::Stdout
10
11
  }.freeze
11
12
 
12
- # @param [Hash] options
13
- # @option options [::RShade::Filter::FilterComposition] :filter_composition
14
- # @option options [#call(event_store)] :formatter
15
- def initialize(options = {})
16
- @filter = options.fetch(:filter, default_filter_composition)
17
- @formatter = options.fetch(:formatter, ::RShade::Formatter::Stack::Stdout.new)
18
- @custom_serializers = options.fetch(:custom_serializers, {})
13
+ # @param [RShade::Formatter::Stack::Stdout] formatter
14
+ # @param [RShade::Filter::FilterComposition] filter
15
+ # @param [Hash] serializers
16
+ def initialize(formatter: RShade::Formatter::Stack::Stdout.new, filter: default_filter_composition,
17
+ serializers: {})
18
+ @filter = filter
19
+ @formatter = formatter
20
+ @variable_serializer = ::RShade::Serializer::Traversal.new(serializers)
19
21
  end
20
22
 
21
- def add_custom_serializers(hash)
22
- custom_serializers.merge!(hash)
23
+ def serializer!(hash)
24
+ variable_serializer.merge!(hash)
23
25
  self
24
26
  end
25
27
 
26
- def config_filter(filter_type, &block)
27
- filter.config_filter(filter_type, &block)
28
+ def filter!(filter_type, &block)
29
+ filter.filter(filter_type, &block)
28
30
  self
29
31
  end
30
32
 
31
- def set_formatter(formatter, opts = {})
33
+ def formatter!(formatter, opts = {})
32
34
  @formatter = formatter.is_a?(Symbol) ? set_symbol_formatter(formatter, opts) : formatter
33
35
  self
34
36
  end
35
37
 
36
38
  def exclude_gems!
37
- config_filter(::RShade::Filter::ExcludePathFilter) do |paths|
38
- paths.concat(RShade::Config.default_excluded_path)
39
+ filter!(::RShade::Filter::ExcludePathFilter) do |paths|
40
+ paths.concat(RShade::Utils.default_excluded_path)
39
41
  end
40
42
  self
41
43
  end
@@ -50,8 +52,12 @@ module RShade
50
52
  end
51
53
 
52
54
  def default_filter_composition
55
+ variable_filter = RShade::Filter::VariableFilter.new
56
+ include_filter = RShade::Filter::IncludePathFilter.new
57
+ exclude_filter = RShade::Filter::ExcludePathFilter.new
58
+
53
59
  RShade::Filter::FilterBuilder.build([:or,
54
- [:or, RShade::Filter::VariableFilter.new, RShade::Filter::IncludePathFilter.new], RShade::Filter::ExcludePathFilter.new])
60
+ [:or, variable_filter, include_filter], exclude_filter])
55
61
  end
56
62
  end
57
63
  end
@@ -1,13 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Object
4
+ # rubocop:disable Metrics/MethodLength
4
5
  def reveal(method_name = nil, **opts, &block)
5
6
  if method_name
6
7
  @__cache_rshade_reveal ||= {}
7
- config = opts.fetch(:config, ::RShade::Config.default)
8
+ config = opts.fetch(:config, ::RShade::Config::Registry.instance.default_trace_config)
8
9
  @__cache_rshade_reveal[method_name] = config
9
10
  instance_eval do
10
11
  def method_added(name)
12
+ super
11
13
  return unless @__cache_rshade_reveal[name]
12
14
 
13
15
  if @__reveal_rewrite
@@ -19,7 +21,7 @@ class Object
19
21
  origin_method = instance_method(name)
20
22
  define_method(name) do |*args, &fn|
21
23
  val = nil
22
- trace = ::RShade::Trace.reveal(config) do
24
+ trace = ::RShade::Trace.reveal(config: config) do
23
25
  val = origin_method.bind(self).call(*args, &fn)
24
26
  end
25
27
  trace.show
@@ -34,4 +36,5 @@ class Object
34
36
  trace.show
35
37
  end
36
38
  end
39
+ # rubocop:enable Metrics/MethodLength
37
40
  end
data/lib/rshade/event.rb CHANGED
@@ -22,7 +22,7 @@ module RShade
22
22
  self
23
23
  end
24
24
 
25
- def set_return_value!(return_value)
25
+ def return_value!(return_value)
26
26
  @hash[:return_value] = return_value
27
27
  self
28
28
  end
@@ -46,7 +46,7 @@ module RShade
46
46
  vars[var_name] = hash
47
47
  end
48
48
 
49
- hash = { path: evt.path, lineno: evt.lineno, klass: evt.defined_class, method_name: evt.method_id, vars:,
49
+ hash = { path: evt.path, lineno: evt.lineno, klass: evt.defined_class, method_name: evt.method_id, vars: vars,
50
50
  event_type: evt.event }
51
51
 
52
52
  if RETURN_EVENTS.include?(evt.event)
@@ -4,7 +4,7 @@ module RShade
4
4
  class EventObserver
5
5
  attr_reader :event_processor, :config
6
6
 
7
- # @param [RShade::Config::Store] config
7
+ # @param [RShade::Config::EventStore] config
8
8
  # @param [RShade::EventProcessor] event_store
9
9
  def initialize(config, event_processor)
10
10
  @event_processor = event_processor
@@ -41,7 +41,7 @@ module RShade
41
41
  end
42
42
 
43
43
  def pass?(event)
44
- config.filter_composition.call(event)
44
+ config.filter.call(event)
45
45
  end
46
46
  end
47
47
  end
@@ -7,7 +7,7 @@ module RShade
7
7
 
8
8
  def initialize(store, config)
9
9
  @store = store
10
- custom_serializers = config.custom_serializers
10
+ custom_serializers = config.variable_serializer
11
11
  @serializer = ::RShade::Serializer::Traversal.new(custom_serializers)
12
12
  end
13
13
 
@@ -22,7 +22,7 @@ module RShade
22
22
  # @param [Integer] level
23
23
  def leave(event, _level)
24
24
  store.current! do |node|
25
- node.value.set_return_value!(event.return_value)
25
+ node.value.return_value!(event.return_value)
26
26
  .with_serialized_return!(serializer)
27
27
  end
28
28
  rescue StandardError
@@ -10,6 +10,7 @@ module RShade
10
10
  @current = @head = EventTreeNode.new(nil, 0, nil)
11
11
  end
12
12
 
13
+ # rubocop:disable Metrics/AbcSize
13
14
  def add(value, level)
14
15
  if current.level + 1 == level
15
16
  current.children << EventTreeNode.new(value, level, current)
@@ -30,6 +31,7 @@ module RShade
30
31
  @current = current.parent
31
32
  add(value, level)
32
33
  end
34
+ # rubocop:enable Metrics/AbcSize
33
35
 
34
36
  def current!(&block)
35
37
  block.call(current.children.last) if current.children.last
@@ -50,7 +52,7 @@ module RShade
50
52
  @level = level
51
53
  @parent = parent
52
54
  @value = value
53
- @vlevel = set_vlevel(parent)
55
+ @vlevel = vlevel!(parent)
54
56
  end
55
57
 
56
58
  def each(&block)
@@ -60,13 +62,13 @@ module RShade
60
62
 
61
63
  private
62
64
 
63
- def set_vlevel(node)
65
+ def vlevel!(node)
64
66
  return 0 if node.nil?
65
67
 
66
68
  if node.value || node.level.zero?
67
69
  node.vlevel + 1
68
70
  else
69
- set_vlevel(node.parent)
71
+ vlevel!(node.parent)
70
72
  end
71
73
  end
72
74
  end
@@ -3,7 +3,7 @@
3
3
  module RShade
4
4
  module Filter
5
5
  class Default
6
- RUBY_VERSION_PATTERN = /ruby-[0-9.]*/
6
+ RUBY_VERSION_PATTERN = /ruby-[0-9.]*/.freeze
7
7
 
8
8
  def self.create
9
9
  new.create
@@ -7,7 +7,7 @@ module RShade
7
7
  AND_OP = :and
8
8
  OR_OP = :or
9
9
  UNARY_OP = :unary
10
- attr_reader :value, :left, :right, :parent
10
+ attr_reader :value, :left, :right
11
11
  attr_accessor :parent
12
12
 
13
13
  # @param [#call, Enumerable] left
@@ -18,6 +18,7 @@ module RShade
18
18
  @right = right
19
19
  end
20
20
 
21
+ # rubocop:disable Metrics/CyclomaticComplexity
21
22
  def call(event)
22
23
  case value
23
24
  when UNARY_OP
@@ -30,6 +31,7 @@ module RShade
30
31
  value.call(event)
31
32
  end
32
33
  end
34
+ # rubocop:enable Metrics/CyclomaticComplexity
33
35
 
34
36
  def each(&block)
35
37
  yield value unless left && right
@@ -37,9 +39,9 @@ module RShade
37
39
  right&.each(&block)
38
40
  end
39
41
 
40
- def config_filter(type, &block)
41
- filter = find do |filter|
42
- filter.is_a? type
42
+ def filter(type, &block)
43
+ filter = find do |f|
44
+ f.is_a? type
43
45
  end
44
46
  filter&.config(&block)
45
47
  end
@@ -8,6 +8,7 @@ module RShade
8
8
  NAME = :include_paths
9
9
 
10
10
  def initialize
11
+ super
11
12
  @paths = []
12
13
  end
13
14
 
@@ -8,6 +8,7 @@ module RShade
8
8
  NAME = :variable_filter
9
9
 
10
10
  def initialize
11
+ super
11
12
  @matchers = []
12
13
  end
13
14
 
@@ -21,8 +22,8 @@ module RShade
21
22
 
22
23
  def call(event)
23
24
  matchers.each do |match|
24
- event.vars.each do |name, value|
25
- return true if match.call(name, value)
25
+ event.vars.each do |name, hash|
26
+ return true if match.call(name, hash[:value])
26
27
  end
27
28
  end
28
29
  false
@@ -4,7 +4,7 @@ module RShade
4
4
  module Formatter
5
5
  module Stack
6
6
  class Json
7
- attr_reader :filepath, :pretty
7
+ attr_reader :filepath, :pretty, :variable_serializer
8
8
 
9
9
  def initialize(filepath:, pretty: false)
10
10
  @filepath = filepath
@@ -12,9 +12,9 @@ module RShade
12
12
  end
13
13
 
14
14
  # @param [Array<RShade::StackFrame>] stack_frames
15
- def call(stack_frames)
15
+ def call(stack_frames, variable_serializer: nil)
16
16
  payload = stack_frames.map.with_index do |frame, idx|
17
- serialize(idx, frame)
17
+ serialize(idx, frame, variable_serializer)
18
18
  end
19
19
 
20
20
  File.open(filepath, 'a+') do |file|
@@ -37,12 +37,14 @@ module RShade
37
37
  end
38
38
 
39
39
  # @param [RShade::StackFrame] frame
40
- def serialize(idx, frame)
40
+ def serialize(idx, frame, variable_serializer)
41
+ local_vars = variable_serializer.nil? ? frame.local_vars : variable_serializer.call(frame.local_vars)
42
+ receiver_variables = variable_serializer.call(frame.receiver_variables) unless variable_serializer.nil?
41
43
  {
42
44
  frame: idx,
43
45
  source_location: "#{frame.source_location[:path]}:#{frame.source_location[:line]}",
44
- local_variables: frame.local_vars,
45
- receiver_variables: frame.receiver_variables
46
+ local_variables: local_vars,
47
+ receiver_variables: receiver_variables
46
48
  }
47
49
  end
48
50
  end
@@ -4,8 +4,8 @@ module RShade
4
4
  module Formatter
5
5
  module Stack
6
6
  class Stdout < String
7
- def call(stack)
8
- puts super(stack)
7
+ def call(stack_frames, variable_serializer: nil)
8
+ puts super
9
9
  end
10
10
  end
11
11
  end