rshade 0.1.9.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/Gemfile +6 -2
  4. data/Gemfile.lock +10 -1
  5. data/README.md +19 -3
  6. data/Rakefile +5 -3
  7. data/bin/console +4 -3
  8. data/lib/rshade/config/registry.rb +47 -0
  9. data/lib/rshade/config/stack_store.rb +58 -0
  10. data/lib/rshade/config/store.rb +6 -5
  11. data/lib/rshade/config.rb +4 -3
  12. data/lib/rshade/core_extensions/object/reveal.rb +34 -5
  13. data/lib/rshade/event.rb +15 -5
  14. data/lib/rshade/event_observer.rb +3 -1
  15. data/lib/rshade/event_processor.rb +12 -11
  16. data/lib/rshade/event_tree.rb +13 -15
  17. data/lib/rshade/filter/abstract_filter.rb +3 -1
  18. data/lib/rshade/filter/default.rb +3 -1
  19. data/lib/rshade/filter/exclude_path_filter.rb +5 -3
  20. data/lib/rshade/filter/filter_builder.rb +14 -3
  21. data/lib/rshade/filter/filter_composition.rb +26 -24
  22. data/lib/rshade/filter/include_path_filter.rb +5 -1
  23. data/lib/rshade/filter/variable_filter.rb +4 -1
  24. data/lib/rshade/formatter/stack/json.rb +51 -0
  25. data/lib/rshade/formatter/stack/stdout.rb +13 -0
  26. data/lib/rshade/formatter/stack/string.rb +41 -0
  27. data/lib/rshade/formatter/trace/file.rb +33 -0
  28. data/lib/rshade/formatter/trace/html.rb +38 -0
  29. data/lib/rshade/formatter/trace/json.rb +61 -0
  30. data/lib/rshade/formatter/trace/stdout.rb +14 -0
  31. data/lib/rshade/formatter/trace/string.rb +48 -0
  32. data/lib/rshade/rspec/rspec.rb +7 -6
  33. data/lib/rshade/serializer/traversal.rb +16 -9
  34. data/lib/rshade/stack.rb +26 -0
  35. data/lib/rshade/stack_frame.rb +60 -0
  36. data/lib/rshade/trace.rb +7 -4
  37. data/lib/rshade/trace_observable.rb +5 -0
  38. data/lib/rshade/version.rb +3 -1
  39. data/lib/rshade.rb +25 -8
  40. data/rshade.gemspec +24 -21
  41. metadata +43 -8
  42. data/lib/rshade/formatter/file.rb +0 -28
  43. data/lib/rshade/formatter/html.rb +0 -33
  44. data/lib/rshade/formatter/json.rb +0 -59
  45. data/lib/rshade/formatter/stdout.rb +0 -10
  46. data/lib/rshade/formatter/string.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91ab4d11c9af8066bff925ab208f10e20c5bf7fd5685418b0c8ef01880c13d2f
4
- data.tar.gz: 7c0e95c99b1707e5290440cf3459e02cd465c653bdbfbfdc3f216d77a3647c66
3
+ metadata.gz: 39758f070ab0a6b6e7dc0bdc09aa03bb107130f84fe7115331189a31c0e013eb
4
+ data.tar.gz: 0331bdd526cd0155df7d210603bb07a15c9541bcce62197b2754731e640060c3
5
5
  SHA512:
6
- metadata.gz: 21fe1fa50bf9c63261fbed6651ad8999edc22734567c3f33b2ba872ba95640cb70b3cff8fa0c640fd13faa8cf73371bb107ee8d0303e3e1322bba06a87f30d58
7
- data.tar.gz: 2b657588399858bcc1aa9f60cac2baf92ea3427b341542c40f15c7a7a26cbfb17cabfa3b98a2c5465c1905a3c8dfeb9500ed772351d89bdd7c2b6ca3ac223392
6
+ metadata.gz: b0c97b53d02f997d05484e850655dfe561c82da1d110a111022885278ece826b5fc75b2e5d70260ff59095ca29178e681c85915301a6b171efe263aa42c82f64
7
+ data.tar.gz: ed9a95bceb71f94cd17587bd88086a6e26d77b5a19fe14ed96b4cfbd559fa1574ffaca380ec3fc49167e788197008bc08b581f83fb5997fb058dedba77e49bf8
data/.gitignore CHANGED
@@ -5,6 +5,7 @@
5
5
  /doc/
6
6
  /pkg/
7
7
  /spec/reports/
8
+ /spec/store/
8
9
  /tmp/
9
10
  .idea
10
11
 
@@ -12,4 +13,4 @@
12
13
  .rspec_status
13
14
  .ruby-version
14
15
  .DS_Store
15
- test.rb
16
+ test.rb
data/Gemfile CHANGED
@@ -1,10 +1,14 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
6
 
5
7
  # Specify your gem's dependencies in rshade.gemspec
6
8
  gemspec
7
9
 
8
10
  group :development, :test do
11
+ gem 'binding_of_caller'
12
+ gem 'prism'
9
13
  gem 'pry'
10
14
  end
data/Gemfile.lock CHANGED
@@ -1,16 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rshade (0.1.9.1)
4
+ rshade (0.2.0)
5
+ binding_of_caller
5
6
  colorize
7
+ prism
6
8
 
7
9
  GEM
8
10
  remote: https://rubygems.org/
9
11
  specs:
12
+ binding_of_caller (1.0.1)
13
+ debug_inspector (>= 1.2.0)
10
14
  coderay (1.1.3)
11
15
  colorize (0.8.1)
16
+ debug_inspector (1.2.0)
12
17
  diff-lcs (1.5.0)
13
18
  method_source (1.0.0)
19
+ prism (1.3.0)
14
20
  pry (0.14.1)
15
21
  coderay (~> 1.1)
16
22
  method_source (~> 1.0)
@@ -32,9 +38,12 @@ GEM
32
38
  PLATFORMS
33
39
  x86_64-darwin-19
34
40
  x86_64-darwin-20
41
+ x86_64-darwin-22
35
42
 
36
43
  DEPENDENCIES
44
+ binding_of_caller
37
45
  bundler (~> 2.2.33)
46
+ prism
38
47
  pry
39
48
  rake (>= 12.3.3)
40
49
  rshade!
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # RShade
2
-
3
- ![warcraft shade](https://github.com/gingray/rshade/raw/master/shade.jpg)
2
+ <p align="center">
3
+ <img src="https://github.com/gingray/rshade/raw/master/shade.jpg">
4
+ </p>
4
5
 
5
6
  RShade is a debugging/code exploration tool based on `TracePoint` functionality.
6
7
  Recent years I've working with relatively huge legacy code and I need a tool which can help me to figure out what is going on due execution.
@@ -85,7 +86,7 @@ On such huge codebase as spree it's helpful to know what callbacks are triggered
85
86
  context 'when cost currency is nil' do
86
87
  before { variant.cost_currency = nil }
87
88
 
88
- it 'populates cost currency with the default value on save', focus: true do
89
+ it 'populates cost currency with the default value on save' do
89
90
  RShade::Trace.reveal do
90
91
  variant.save!
91
92
  end
@@ -99,6 +100,21 @@ Below is example how output will look like.
99
100
  As you can see all code that have been in use is printed.
100
101
  [![asciicast](https://asciinema.org/a/MR5KL7TmHmYRUhwBUWQjBI373.svg)](https://asciinema.org/a/MR5KL7TmHmYRUhwBUWQjBI373)
101
102
 
103
+ ## Stack reveal
104
+ Config
105
+ ```ruby
106
+ ::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 })
110
+ end
111
+ ```
112
+
113
+ Execute (put in any place where you want reveal stack)
114
+ ```ruby
115
+ ::RShade::Stack.trace
116
+ ```
117
+
102
118
  ## TODO
103
119
  Use stack to keep connections between current method and caller
104
120
  take a look on https://github.com/matugm/visual-call-graph
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "rshade"
4
+ require 'bundler/setup'
5
+ require 'rshade'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "rshade"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RShade
4
+ class Config
5
+ class Registry
6
+ attr_reader :map, :mutex
7
+
8
+ include Singleton
9
+
10
+ def initialize
11
+ @map = {}
12
+ @mutex = Mutex.new
13
+ defaults
14
+ end
15
+
16
+ def set_default_stack(config)
17
+ mutex.synchronize do
18
+ map[:store_default] = config
19
+ end
20
+ end
21
+
22
+ def default_stack_config
23
+ val = nil
24
+ mutex.synchronize do
25
+ val = map[:store_default]
26
+ end
27
+ val
28
+ end
29
+
30
+ def stack_config(&block)
31
+ val = nil
32
+ mutex.synchronize do
33
+ val = ::RShade::Config::StackStore.new
34
+ block.call(val)
35
+ map[:store_default] = val
36
+ end
37
+ val
38
+ end
39
+
40
+ def defaults
41
+ mutex.synchronize do
42
+ map[:store_default] = ::RShade::Config::StackStore.new
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RShade
4
+ class Config
5
+ class StackStore
6
+ attr_reader :filter, :formatter, :custom_serializers
7
+
8
+ DEFAULT_FORMATTER = {
9
+ json: ::RShade::Formatter::Stack::Json
10
+ }.freeze
11
+
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, {})
19
+ end
20
+
21
+ def add_custom_serializers(hash)
22
+ custom_serializers.merge!(hash)
23
+ self
24
+ end
25
+
26
+ def config_filter(filter_type, &block)
27
+ filter.config_filter(filter_type, &block)
28
+ self
29
+ end
30
+
31
+ def set_formatter(formatter, opts = {})
32
+ @formatter = formatter.is_a?(Symbol) ? set_symbol_formatter(formatter, opts) : formatter
33
+ self
34
+ end
35
+
36
+ def exclude_gems!
37
+ config_filter(::RShade::Filter::ExcludePathFilter) do |paths|
38
+ paths.concat(RShade::Config.default_excluded_path)
39
+ end
40
+ self
41
+ end
42
+
43
+ private
44
+
45
+ def set_symbol_formatter(type, opts)
46
+ formatter_class = DEFAULT_FORMATTER[type]
47
+ return formatter_class unless formatter_class
48
+
49
+ @formatter = formatter_class.new(**opts)
50
+ end
51
+
52
+ def default_filter_composition
53
+ RShade::Filter::FilterBuilder.build([:or,
54
+ [:or, RShade::Filter::VariableFilter.new, RShade::Filter::IncludePathFilter.new], RShade::Filter::ExcludePathFilter.new])
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module RShade
3
4
  class Config
@@ -8,10 +9,10 @@ module RShade
8
9
  # @option options [RShade::Filter::FilterComposition] :filter_composition
9
10
  # @option options [#call(event_store)] :formatter
10
11
  # @option options [Array<Symbol>] :tp_events
11
- def initialize(options={})
12
+ def initialize(options = {})
12
13
  @filter_composition = options.fetch(:filter_composition, default_filter_composition)
13
- @formatter = options.fetch(:formatter, ::RShade::Formatter::Stdout)
14
- @tp_events = options.fetch(:tp_events, [:call, :return])
14
+ @formatter = options.fetch(:formatter, ::RShade::Formatter::Trace::Stdout)
15
+ @tp_events = options.fetch(:tp_events, %i[call return])
15
16
  @custom_serializers = options.fetch(:custom_serializers, {})
16
17
  end
17
18
 
@@ -25,7 +26,6 @@ module RShade
25
26
  self
26
27
  end
27
28
 
28
-
29
29
  def config_filter(filter_type, &block)
30
30
  filter_composition.config_filter(filter_type, &block)
31
31
  self
@@ -39,7 +39,8 @@ module RShade
39
39
  private
40
40
 
41
41
  def default_filter_composition
42
- RShade::Filter::FilterBuilder.build([:or,[:or, RShade::Filter::VariableFilter.new, RShade::Filter::IncludePathFilter.new] , RShade::Filter::ExcludePathFilter.new])
42
+ RShade::Filter::FilterBuilder.build([:or,
43
+ [:or, RShade::Filter::VariableFilter.new, RShade::Filter::IncludePathFilter.new], RShade::Filter::ExcludePathFilter.new])
43
44
  end
44
45
  end
45
46
  end
data/lib/rshade/config.rb CHANGED
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  class Config
3
5
  RUBY_VERSION_PATTERN = /ruby-[0-9.]*/
4
6
 
5
7
  def self.default
6
- ::RShade::Config::Store.new.set_formatter(::RShade::Formatter::Stdout.new)
8
+ ::RShade::Config::Store.new.set_formatter(::RShade::Formatter::Trace::Stdout.new)
7
9
  .config_filter(::RShade::Filter::ExcludePathFilter) do |paths|
8
10
  default_excluded_path.each do |path|
9
11
  paths << path
@@ -20,7 +22,7 @@ module RShade
20
22
  # @option options [RShade::Filter::FilterComposition] :filter_composition
21
23
  # @option options [#call(event_store)] :formatter
22
24
  # @option options [Array<Symbol>] :tp_events
23
- def self.create(options={})
25
+ def self.create(options = {})
24
26
  new(Config::Store.new(options))
25
27
  end
26
28
 
@@ -68,7 +70,6 @@ module RShade
68
70
  @root_dir ||= File.expand_path('../../', __dir__)
69
71
  end
70
72
 
71
- private
72
73
  def self.default_excluded_path
73
74
  [ENV['GEM_PATH'].split(':'), RUBY_VERSION_PATTERN, /internal/].flatten.compact
74
75
  end
@@ -1,8 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Object
2
- def reveal(&block)
3
- trace = ::RShade::Trace.reveal do
4
- block.call
4
+ def reveal(method_name = nil, **opts, &block)
5
+ if method_name
6
+ @__cache_rshade_reveal ||= {}
7
+ config = opts.fetch(:config, ::RShade::Config.default)
8
+ @__cache_rshade_reveal[method_name] = config
9
+ instance_eval do
10
+ def method_added(name)
11
+ return unless @__cache_rshade_reveal[name]
12
+
13
+ if @__reveal_rewrite
14
+ @__reveal_rewrite = false
15
+ return
16
+ end
17
+ @__reveal_rewrite = true
18
+ config = @__cache_rshade_reveal[name]
19
+ origin_method = instance_method(name)
20
+ define_method(name) do |*args, &fn|
21
+ val = nil
22
+ trace = ::RShade::Trace.reveal(config) do
23
+ val = origin_method.bind(self).call(*args, &fn)
24
+ end
25
+ trace.show
26
+ val
27
+ end
28
+ end
29
+ end
30
+ else
31
+ trace = ::RShade::Trace.reveal do
32
+ block.call if block_given?
33
+ end
34
+ trace.show
5
35
  end
6
- trace.show
7
36
  end
8
- end
37
+ end
data/lib/rshade/event.rb CHANGED
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  # nodoc
3
5
  class Event
4
6
  attr_reader :hash, :skipped
5
- RETURN_EVENTS = [:return, :b_return, :c_return]
6
7
 
8
+ RETURN_EVENTS = %i[return b_return c_return].freeze
7
9
 
8
10
  def initialize(hash)
9
11
  @hash = hash
10
12
  end
11
13
 
12
- [:klass, :path, :lineno, :method_name, :vars, :level, :return_value].each do |method_name|
14
+ %i[klass path lineno method_name vars level return_value].each do |method_name|
13
15
  define_method method_name do
14
16
  fetch method_name
15
17
  end
@@ -38,12 +40,20 @@ module RShade
38
40
  def self.from_trace_point(evt)
39
41
  vars = {}
40
42
  evt.binding.local_variables.each do |var_name|
41
- vars[var_name] = evt.binding.local_variable_get var_name
43
+ local_val = evt.binding.local_variable_get(var_name)
44
+ local_val_type = local_val.is_a?(Class) ? local_val : local_val.class
45
+ hash = { name: var_name, value: local_val, type: local_val_type }
46
+ vars[var_name] = hash
42
47
  end
43
48
 
44
- hash = { path: evt.path, lineno: evt.lineno, klass: evt.defined_class, method_name: evt.method_id, vars: vars,
49
+ hash = { path: evt.path, lineno: evt.lineno, klass: evt.defined_class, method_name: evt.method_id, vars:,
45
50
  event_type: evt.event }
46
- hash.merge!({return_value: evt.return_value}) if RETURN_EVENTS.include?(evt.event)
51
+
52
+ if RETURN_EVENTS.include?(evt.event)
53
+ ret_val = evt.return_value
54
+ ret_val_type = evt.return_value.is_a?(Class) ? evt.return_value : evt.return_value.class
55
+ hash.merge!({ return_value: { value: ret_val, type: ret_val_type } })
56
+ end
47
57
  new(hash)
48
58
  end
49
59
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  class EventObserver
3
5
  attr_reader :event_processor, :config
@@ -42,4 +44,4 @@ module RShade
42
44
  config.filter_composition.call(event)
43
45
  end
44
46
  end
45
- end
47
+ end
@@ -1,36 +1,37 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  # nodoc
3
5
  class EventProcessor
4
- attr_reader :store
6
+ attr_reader :store, :serializer
5
7
 
6
8
  def initialize(store, config)
7
9
  @store = store
8
10
  custom_serializers = config.custom_serializers
9
- @var_serializer = ::RShade::Serializer::Traversal.new(custom_serializers)
11
+ @serializer = ::RShade::Serializer::Traversal.new(custom_serializers)
10
12
  end
11
13
 
12
14
  # @param [RShade::Event] event
13
15
  # @param [Integer] level
14
16
  def enter(event, level)
15
- event.with_serialized_vars!(@var_serializer).with_level!(level)
17
+ event.with_serialized_vars!(serializer).with_level!(level)
16
18
  store.add(event, level)
17
19
  end
18
20
 
19
21
  # @param [RShade::Event] event
20
22
  # @param [Integer] level
21
- def leave(event, level)
23
+ def leave(event, _level)
22
24
  store.current! do |node|
23
- node.value.set_return_value!(event.return_value)
24
- .with_serialized_return!(->(value) { value.inspect })
25
+ node.value.set_return_value!(event.return_value)
26
+ .with_serialized_return!(serializer)
25
27
  end
26
- rescue => e
28
+ rescue StandardError
27
29
  # this rescue here due this issue which reproduce in ruby-2.6.6 at least
28
30
  # https://bugs.ruby-lang.org/issues/18060
29
31
  end
32
+
30
33
  # @param [RShade::Event] event
31
34
  # @param [Integer] level
32
- def other(event, level)
33
-
34
- end
35
+ def other(event, level); end
35
36
  end
36
- end
37
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  class EventTree
3
5
  include Enumerable
@@ -16,21 +18,17 @@ module RShade
16
18
  if current.level + 1 < level
17
19
 
18
20
  last = current.children.last
19
- unless last
20
- current.children << EventTreeNode.new(nil, current.level + 1 , current)
21
- end
21
+ current.children << EventTreeNode.new(nil, current.level + 1, current) unless last
22
22
  @current = current.children.last
23
23
  add(value, level)
24
24
  return
25
25
  end
26
26
 
27
- if current.level + 1 > level
28
- unless current.parent
29
- return
30
- end
31
- @current = current.parent
32
- add(value, level)
33
- end
27
+ return unless current.level + 1 > level
28
+ return unless current.parent
29
+
30
+ @current = current.parent
31
+ add(value, level)
34
32
  end
35
33
 
36
34
  def current!(&block)
@@ -47,7 +45,7 @@ module RShade
47
45
  attr_reader :children, :level, :vlevel, :value
48
46
  attr_accessor :parent
49
47
 
50
- def initialize(value, level, parent=nil)
48
+ def initialize(value, level, parent = nil)
51
49
  @children = []
52
50
  @level = level
53
51
  @parent = parent
@@ -56,20 +54,20 @@ module RShade
56
54
  end
57
55
 
58
56
  def each(&block)
59
- block.call(self) if parent != nil || value != nil
57
+ block.call(self) if !parent.nil? || !value.nil?
60
58
  children.each { |item| item.each(&block) }
61
59
  end
62
60
 
63
61
  private
64
62
 
65
63
  def set_vlevel(node)
66
- return 0 if node == nil
64
+ return 0 if node.nil?
67
65
 
68
- if node.value || node.level == 0
66
+ if node.value || node.level.zero?
69
67
  node.vlevel + 1
70
68
  else
71
69
  set_vlevel(node.parent)
72
70
  end
73
71
  end
74
72
  end
75
- end
73
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  module Filter
3
5
  class AbstractFilter
@@ -23,4 +25,4 @@ module RShade
23
25
  end
24
26
  end
25
27
  end
26
- end
28
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  module Filter
3
5
  class Default
@@ -25,4 +27,4 @@ module RShade
25
27
  end
26
28
  end
27
29
  end
28
- end
30
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  module Filter
3
5
  class ExcludePathFilter < IncludePathFilter
@@ -13,13 +15,13 @@ module RShade
13
15
 
14
16
  def call(event)
15
17
  event_path = event.path
16
- !paths.any? do |path|
18
+ paths.none? do |path|
17
19
  next str?(path, event_path) if path.is_a? String
18
20
  next regexp?(path, event_path) if path.is_a? Regexp
21
+
19
22
  false
20
23
  end
21
24
  end
22
-
23
25
  end
24
26
  end
25
- end
27
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RShade
2
4
  module Filter
3
5
  class FilterBuilder
@@ -18,11 +20,20 @@ module RShade
18
20
  arg1 = arr[1]
19
21
  arg2 = nil
20
22
  arg2 = arr[2] if arity == 2
21
- arg1 = traverse(arg1) if arg1.is_a?(Array)
22
- arg2 = traverse(arg2) if arg2.is_a?(Array)
23
+ arg1 = if arg1.is_a?(Array)
24
+ traverse(arg1)
25
+ else
26
+ RShade::Filter::FilterComposition.new(arg1)
27
+ end
28
+
29
+ arg2 = if arg2.is_a?(Array)
30
+ traverse(arg2)
31
+ else
32
+ RShade::Filter::FilterComposition.new(arg2)
33
+ end
23
34
 
24
35
  RShade::Filter::FilterComposition.new(op, arg1, arg2)
25
36
  end
26
37
  end
27
38
  end
28
- end
39
+ end