power_assert 2.0.5 → 3.0.0

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: f842260e6bea4e899b1e6af63144e7eda3ce9703788902893576890d61c1f6be
4
- data.tar.gz: e1c53238ed0eb63702879ecedf209cbe5cea34ee8829d9ffb18af1694b2f8e26
3
+ metadata.gz: 705f51cc47d3a6d949df579d782c02ed246b1dc782794a1855a7bdd412ccbb63
4
+ data.tar.gz: 38ca48e3a3efccafce2c68715c592a62dd98d388925e5bb60088258deaa52273
5
5
  SHA512:
6
- metadata.gz: d43ea1d5aa5c3e78defd497e9fda7077aae1f989d0e8b4428eb2fad5852559e597e27313b8867d665cc3c0c141a8ab56a3720c42075922d33b465d465a147481
7
- data.tar.gz: 35a8335719afd408c219bb2838496fc0e438f404fdd1abf15147a28fd77d46ed32c6ef59a46caf55cf96ffbd0b03f20f277af37959d97b6510f77c9c73c952f0
6
+ metadata.gz: a8e8d18cca0c77c0bd0d9092ba167a3c3e99628516b053e37f4f218c9e512eef4c9d348f2ac00276841d0c9ee7470556f99382fd551e2231084f4cebdf052926
7
+ data.tar.gz: f665351eb5861e18676a17e7247c939cf59815df6692b64af1c5aabe4f1d303403ffe60341c940c7f304ffcec9c9596377b91f1c46007c9a51a04a0b24a78e84
@@ -5,7 +5,7 @@ jobs:
5
5
  uses: ruby/actions/.github/workflows/ruby_versions.yml@master
6
6
  with:
7
7
  engine: cruby
8
- min_version: 2.5
8
+ min_version: 3.1
9
9
  test:
10
10
  needs: ruby-versions
11
11
  name: >-
@@ -21,15 +21,12 @@ jobs:
21
21
  os: "ubuntu-latest"
22
22
  TEST_SYMLINK: yes
23
23
  rubyopt: "--enable-frozen-string-literal"
24
- exclude:
25
- - ruby-version: "2.5"
26
- os: "macos-latest"
27
24
  runs-on: ${{ matrix.os }}
28
25
  env:
29
26
  TEST_SYMLINK: ${{ matrix.TEST_SYMLINK }}
30
27
  continue-on-error: ${{ matrix.ruby-version == 'head' }}
31
28
  steps:
32
- - uses: actions/checkout@v4
29
+ - uses: actions/checkout@v5
33
30
  - name: Set up Ruby
34
31
  uses: ruby/setup-ruby@v1
35
32
  with:
data/Gemfile CHANGED
@@ -12,8 +12,7 @@ group :development do
12
12
  gem 'test-unit'
13
13
  gem 'rake'
14
14
  gem 'simplecov'
15
- gem 'bundler'
16
15
  gem 'irb', '>= 1.3.1'
17
- gem 'byebug'
16
+ gem 'fiddle'
18
17
  gem 'benchmark-ips'
19
18
  end
data/README.md CHANGED
@@ -20,79 +20,89 @@ Use following test frameworks or extensions instead.
20
20
  * [rspec-power_assert](https://github.com/joker1007/rspec-power_assert)
21
21
  * [rspec-matchers-power_assert_matchers](https://github.com/kachick/rspec-matchers-power_assert_matchers)
22
22
  * [pry-power_assert](https://github.com/yui-knk/pry-power_assert)
23
- * [pry-byebug-power_assert](https://github.com/k-tsj/pry-byebug-power_assert)
24
23
  * [irb-power_assert](https://github.com/kachick/irb-power_assert)
25
24
  * [power_p](https://github.com/k-tsj/power_p)
26
25
 
27
26
  ## Requirement
28
- * CRuby 2.5+
27
+ * CRuby 3.1+
29
28
 
30
29
  ## Configuration
31
30
  To colorize output messages, add <code>require "power_assert/colorize"</code> to your code.
32
- (It requires CRuby 3.0.1+ or irb 1.3.1+)
31
+ (It requires irb 1.3.1+)
33
32
 
34
33
  ## Known Limitations
35
- * Expressions must be put in one line. Expressions with folded long lines produce nothing report, e.g.:
34
+ * Expressions must be on a single line. Splitting an assertion across multiple lines prevents any report from being generated, e.g.:
36
35
 
37
36
  ```ruby
38
37
  assert do
39
- # reported
38
+ # Reported
40
39
  func(foo: 0123456789, bar: "abcdefg")
41
40
  end
42
41
 
43
42
  assert do
44
- # won't be reported
43
+ # Not reported
45
44
  func(foo: 0123456789,
46
45
  bar: "abcdefg")
47
46
  end
48
47
  ```
49
48
 
50
- * Expressions must have one or more method call. Expressions with no method call produce nothing report, e.g.:
49
+ * Expressions must include at least one method call. Assertions without method calls generate no report, e.g.:
51
50
 
52
51
  ```ruby
53
52
  val = false
54
53
  assert do
55
- # reported
54
+ # Reported
56
55
  val == true
57
56
  end
58
57
 
59
58
  assert do
60
- # won't be reported
59
+ # Not reported
61
60
  val
62
61
  end
63
62
  ```
64
63
 
65
- * Returned values from accessor methods, method missing, or "super" produce nothing report, e.g:
64
+ * Return values from `method_missing` or `super` generate no report, e.g.:
66
65
 
67
66
  ```ruby
68
67
  class Foo
69
- attr_accessor :val
68
+ def method_missing(*)
69
+ :foo
70
+ end
70
71
  end
71
72
  foo = Foo.new
72
- foo.val = false
73
73
 
74
74
  assert do
75
- # reported (only the value of "foo" and the literal "true")
76
- foo.val == true
77
- end
78
-
79
- assert do
80
- # won't be reported
81
- foo.val
75
+ # Not reported
76
+ foo.foo
82
77
  end
83
78
  ```
84
79
 
85
- * Expressions should not have conditional branches. Expressions with such conditional codes may produce nothing report, e.g.:
80
+ * Avoid conditional branches inside assertions. Conditional logic may prevent a report from being generated, e.g.:
86
81
 
87
82
  ```ruby
88
83
  condition = true
89
84
  expected = false
90
85
  actual = true
91
86
  assert do
92
- # this will fail but nothing reported
87
+ # This fails, but nothing is reported
93
88
  condition ? expected == actual : expected == actual
94
89
  end
95
90
  ```
96
91
 
92
+ * (CRuby 4.0+) `<Struct subclass>.new` generates no report. Use `<Struct subclass>.[]` instead, e.g.:
93
+
94
+ ```ruby
95
+ s = Struct.new(:a)
96
+ assert do
97
+ # Not reported
98
+ s.new(0)
99
+ end
100
+
101
+ assert do
102
+ # Reported
103
+ s[0]
104
+ end
105
+ ```
106
+
97
107
  ## Reference
98
108
  * [Power Assert in Ruby (at RubyKaigi 2014) // Speaker Deck](https://speakerdeck.com/k_tsj/power-assert-in-ruby)
data/Rakefile CHANGED
@@ -8,7 +8,6 @@ Rake::TestTask.new(:test) do |t|
8
8
  t.ruby_opts = ["-w", "-r#{helper_path}"]
9
9
  t.test_files = FileList["test/**/*_test.rb"].exclude do |i|
10
10
  begin
11
- next false unless defined?(RubyVM)
12
11
  RubyVM::InstructionSequence.compile(File.read(i))
13
12
  false
14
13
  rescue SyntaxError
@@ -7,9 +7,34 @@ module PowerAssert
7
7
  class Context
8
8
  Value = Struct.new(:name, :value, :lineno, :column, :display_offset)
9
9
 
10
- def initialize(base_caller_length)
10
+ def initialize(assertion_proc_or_source, assertion_method, source_binding)
11
11
  @fired = false
12
12
  @target_thread = Thread.current
13
+
14
+ if assertion_proc_or_source.respond_to?(:to_proc)
15
+ @assertion_proc = assertion_proc_or_source.to_proc
16
+ line = nil
17
+ else
18
+ @assertion_proc = source_binding.eval "Proc.new {#{assertion_proc_or_source}}"
19
+ line = assertion_proc_or_source
20
+ end
21
+
22
+ @parser = Parser::DUMMY
23
+ @trace_call = TracePoint.new(:call, :c_call) do
24
+ if PowerAssert.app_context? and Thread.current == @target_thread
25
+ @trace_call.disable
26
+ locs = PowerAssert.app_caller_locations
27
+ path = locs.last.path
28
+ lineno = locs.last.lineno
29
+ if File.exist?(path)
30
+ line ||= File.open(path) {|fp| fp.each_line.drop(lineno - 1).first }
31
+ end
32
+ if line
33
+ @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc)
34
+ end
35
+ end
36
+ end
37
+
13
38
  method_id_set = nil
14
39
  @return_values = []
15
40
  @trace_return = TracePoint.new(:return, :c_return) do |tp|
@@ -22,14 +47,12 @@ module PowerAssert
22
47
  next if tp.event == :c_return and
23
48
  not (@parser.lineno == tp.lineno and @parser.path == tp.path)
24
49
  locs = PowerAssert.app_caller_locations
25
- diff = locs.length - base_caller_length
26
- if (tp.event == :c_return && diff == 1 || tp.event == :return && diff <= 2) and Thread.current == @target_thread
27
- idx = -(base_caller_length + 1)
28
- if @parser.path == locs[idx].path and @parser.lineno == locs[idx].lineno
50
+ if (tp.event == :c_return && locs.length == 1 || tp.event == :return && locs.length <= 2) and Thread.current == @target_thread
51
+ if @parser.path == locs.last.path and @parser.lineno == locs.last.lineno
29
52
  val = PowerAssert.configuration.lazy_inspection ?
30
53
  tp.return_value :
31
54
  InspectedValue.new(SafeInspectable.new(tp.return_value).inspect)
32
- @return_values << Value[method_id.to_s, val, locs[idx].lineno, nil]
55
+ @return_values << Value[method_id.to_s, val, locs.last.lineno, nil]
33
56
  end
34
57
  end
35
58
  rescue Exception => e
@@ -41,7 +64,7 @@ module PowerAssert
41
64
  end
42
65
 
43
66
  def message
44
- raise 'call #yield or #enable at first' unless fired?
67
+ raise 'call #yield at first' unless fired?
45
68
  @message ||= build_assertion_message(@parser, @return_values).freeze
46
69
  end
47
70
 
@@ -49,8 +72,21 @@ module PowerAssert
49
72
  -> { message }
50
73
  end
51
74
 
75
+ def yield
76
+ @fired = true
77
+ invoke_yield(&@assertion_proc)
78
+ end
79
+
52
80
  private
53
81
 
82
+ def invoke_yield
83
+ @trace_return.enable do
84
+ @trace_call.enable do
85
+ yield
86
+ end
87
+ end
88
+ end
89
+
54
90
  def fired?
55
91
  @fired
56
92
  end
@@ -157,77 +193,4 @@ module PowerAssert
157
193
  end
158
194
  end
159
195
  private_constant :Context
160
-
161
- class BlockContext < Context
162
- def initialize(assertion_proc_or_source, assertion_method, source_binding)
163
- super(0)
164
- if assertion_proc_or_source.respond_to?(:to_proc)
165
- @assertion_proc = assertion_proc_or_source.to_proc
166
- line = nil
167
- else
168
- @assertion_proc = source_binding.eval "Proc.new {#{assertion_proc_or_source}}"
169
- line = assertion_proc_or_source
170
- end
171
- @parser = Parser::DUMMY
172
- @trace_call = TracePoint.new(:call, :c_call) do
173
- if PowerAssert.app_context? and Thread.current == @target_thread
174
- @trace_call.disable
175
- locs = PowerAssert.app_caller_locations
176
- path = locs.last.path
177
- lineno = locs.last.lineno
178
- if File.exist?(path)
179
- line ||= File.open(path) {|fp| fp.each_line.drop(lineno - 1).first }
180
- end
181
- if line
182
- @parser = Parser.new(line, path, lineno, @assertion_proc.binding, assertion_method.to_s, @assertion_proc)
183
- end
184
- end
185
- end
186
- end
187
-
188
- def yield
189
- @fired = true
190
- invoke_yield(&@assertion_proc)
191
- end
192
-
193
- private
194
-
195
- def invoke_yield
196
- @trace_return.enable do
197
- @trace_call.enable do
198
- yield
199
- end
200
- end
201
- end
202
- end
203
- private_constant :BlockContext
204
-
205
- class TraceContext < Context
206
- def initialize(binding)
207
- target_frame, *base = PowerAssert.app_caller_locations
208
- super(base.length)
209
- path = target_frame.path
210
- lineno = target_frame.lineno
211
- if File.exist?(path)
212
- line = File.open(path) {|fp| fp.each_line.drop(lineno - 1).first }
213
- @parser = Parser.new(line, path, lineno, binding)
214
- else
215
- @parser = Parser::DUMMY
216
- end
217
- end
218
-
219
- def enable
220
- @fired = true
221
- @trace_return.enable
222
- end
223
-
224
- def disable
225
- @trace_return.disable
226
- end
227
-
228
- def enabled?
229
- @trace_return.enabled?
230
- end
231
- end
232
- private_constant :TraceContext
233
196
  end
@@ -1,62 +1,53 @@
1
1
  require 'power_assert/configuration'
2
2
 
3
- if defined?(RubyVM)
4
- if PowerAssert.configuration._redefinition
5
- module PowerAssert
6
- # set redefined flag
7
- basic_classes = [
8
- Integer, Float, String, Array, Hash, Symbol, Time, Regexp, NilClass, TrueClass, FalseClass
9
- ]
10
-
11
- verbose = $VERBOSE
12
- begin
13
- $VERBOSE = nil
14
- [:Fixnum, :Bignum].each do |c|
15
- if Object.const_defined?(c) and (c = Object.const_get(c)) != Integer
16
- basic_classes << c
3
+ if PowerAssert.configuration._redefinition
4
+ module PowerAssert
5
+ # set redefined flag
6
+ basic_classes = [
7
+ Integer, Float, String, Array, Hash, Symbol, Time, Regexp, NilClass, TrueClass, FalseClass
8
+ ]
9
+
10
+ basic_operators = [
11
+ :+, :-, :*, :/, :%, :==, :===, :<, :<=, :<<, :[], :[]=, :length, :size,
12
+ :empty?, :nil?, :succ, :>, :>=, :!, :!=, :=~, :freeze, :-@, :max, :min,
13
+ # :call (it is just used for block call optimization)
14
+ :&, :|,
15
+ # :default (no specialized instruction for this)
16
+ :pack, :include?,
17
+ ]
18
+
19
+ basic_classes.each do |klass|
20
+ basic_operators.each do |bop|
21
+ if klass.public_method_defined?(bop)
22
+ refine(klass) do
23
+ define_method(bop) {}
17
24
  end
18
25
  end
19
- ensure
20
- $VERBOSE = verbose
21
26
  end
27
+ end
22
28
 
23
- basic_operators = [
24
- :+, :-, :*, :/, :%, :==, :===, :<, :<=, :<<, :[], :[]=, :length, :size,
25
- :empty?, :nil?, :succ, :>, :>=, :!, :!=, :=~, :freeze, :-@, :max, :min,
26
- # :call (it is just used for block call optimization)
27
- :&, :|,
28
- # :default (no specialized instruction for this)
29
- :pack, :include?,
30
- ]
31
-
32
- basic_classes.each do |klass|
33
- basic_operators.each do |bop|
34
- if klass.public_method_defined?(bop)
35
- refine(klass) do
36
- define_method(bop) {}
37
- end
38
- end
39
- end
29
+ # bypass check_cfunc
30
+ refine BasicObject do
31
+ def !
40
32
  end
41
33
 
42
- # bypass check_cfunc
43
- refine BasicObject do
44
- def !
45
- end
34
+ def ==
35
+ end
36
+ end
46
37
 
47
- def ==
48
- end
38
+ refine Module do
39
+ def ==
49
40
  end
41
+ end
50
42
 
51
- refine Module do
52
- def ==
53
- end
43
+ refine Class do
44
+ def new
54
45
  end
55
46
  end
56
47
  end
57
-
58
- # disable optimization
59
- RubyVM::InstructionSequence.compile_option = {
60
- specialized_instruction: false
61
- }
62
48
  end
49
+
50
+ # disable optimization
51
+ RubyVM::InstructionSequence.compile_option = {
52
+ specialized_instruction: false
53
+ }
@@ -33,16 +33,13 @@ module PowerAssert
33
33
  private
34
34
 
35
35
  def valid_syntax?(str)
36
- return true unless defined?(RubyVM)
37
- begin
38
- verbose, $VERBOSE = $VERBOSE, nil
39
- RubyVM::InstructionSequence.compile(str)
40
- true
41
- rescue SyntaxError
42
- false
43
- ensure
44
- $VERBOSE = verbose
45
- end
36
+ verbose, $VERBOSE = $VERBOSE, nil
37
+ RubyVM::InstructionSequence.compile(str)
38
+ true
39
+ rescue SyntaxError
40
+ false
41
+ ensure
42
+ $VERBOSE = verbose
46
43
  end
47
44
 
48
45
  def slice_expression(str)
@@ -68,113 +65,81 @@ module PowerAssert
68
65
  # +--------+
69
66
  #
70
67
  def extract_idents(sexp)
71
- tag, * = sexp
72
- case tag
73
- when :arg_paren, :assoc_splat, :fcall, :hash, :method_add_block, :string_literal, :return
74
- extract_idents(sexp[1])
75
- when :assign, :massign
76
- extract_idents(sexp[2])
77
- when :opassign
78
- _, _, (_, op_name, (_, op_column)), s0 = sexp
79
- extract_idents(s0) + [Ident[:method, op_name.sub(/=\z/, ''), op_column]]
80
- when :dyna_symbol
81
- if sexp[1][0].kind_of?(Symbol)
82
- # sexp[1] can be [:string_content, [..]] while parsing { "a": 1 }
83
- extract_idents(sexp[1])
84
- else
85
- sexp[1].flat_map {|s| extract_idents(s) }
86
- end
87
- when :assoclist_from_args, :bare_assoc_hash, :paren, :string_embexpr,
88
- :regexp_literal, :xstring_literal
89
- sexp[1].flat_map {|s| extract_idents(s) }
90
- when :command
91
- [sexp[2], sexp[1]].flat_map {|s| extract_idents(s) }
92
- when :assoc_new, :dot2, :dot3, :string_content
93
- sexp[1..-1].flat_map {|s| extract_idents(s) }
94
- when :unary
95
- handle_columnless_ident([], sexp[1], extract_idents(sexp[2]))
96
- when :binary
97
- op = sexp[2]
98
- if AND_OR_OPS.include?(op)
99
- extract_idents(sexp[1]) + [Branch[extract_idents(sexp[3]), []]]
100
- else
101
- handle_columnless_ident(extract_idents(sexp[1]), op, extract_idents(sexp[3]))
102
- end
103
- when :call
104
- _, recv, (op_sym, op_name, _), method = sexp
68
+ case sexp
69
+ in [:arg_paren | :assoc_splat | :fcall | :hash | :method_add_block | :string_literal | :return, s, *]
70
+ extract_idents(s)
71
+ in [:assign | :massign, _, s]
72
+ extract_idents(s)
73
+ in [:opassign, _, [_, op_name, [_, op_column]], s]
74
+ extract_idents(s) + [Ident[:method, op_name.sub(/=\z/, ''), op_column]]
75
+ in [:dyna_symbol, [Symbol, *] => s]
76
+ # s can be [:string_content, [..]] while parsing an expression like { "a": 1 }
77
+ extract_idents(s)
78
+ in [:dyna_symbol, ss]
79
+ ss.flat_map {|s| extract_idents(s) }
80
+ in [:assoclist_from_args | :bare_assoc_hash | :paren | :string_embexpr | :regexp_literal | :xstring_literal, ss, *]
81
+ ss.flat_map {|s| extract_idents(s) }
82
+ in [:command, s0, s1]
83
+ [s1, s0].flat_map {|s| extract_idents(s) }
84
+ in [:assoc_new | :dot2 | :dot3 | :string_content, *ss]
85
+ ss.flat_map {|s| extract_idents(s) }
86
+ in [:unary, mid, s]
87
+ handle_columnless_ident([], mid, extract_idents(s))
88
+ in [:binary, s0, op, s1] if AND_OR_OPS.include?(op)
89
+ extract_idents(s0) + [Branch[extract_idents(s1), []]]
90
+ in [:binary, s0, op, s1]
91
+ handle_columnless_ident(extract_idents(s0), op, extract_idents(s1))
92
+ in [:call, recv, [op_sym, op_name, _], method]
105
93
  with_safe_op = ((op_sym == :@op and op_name == '&.') or op_sym == :"&.")
106
94
  if method == :call
107
95
  handle_columnless_ident(extract_idents(recv), :call, [], with_safe_op)
108
96
  else
109
97
  extract_idents(recv) + (with_safe_op ? [Branch[extract_idents(method), []]] : extract_idents(method))
110
98
  end
111
- when :array
112
- sexp[1] ? sexp[1].flat_map {|s| extract_idents(s) } : []
113
- when :command_call
114
- [sexp[1], sexp[4], sexp[3]].flat_map {|s| extract_idents(s) }
115
- when :aref
116
- handle_columnless_ident(extract_idents(sexp[1]), :[], extract_idents(sexp[2]))
117
- when :method_add_arg
118
- idents = extract_idents(sexp[1])
119
- if idents.empty?
120
- # idents may be empty(e.g. ->{}.())
121
- extract_idents(sexp[2])
122
- else
123
- if idents[-1].kind_of?(Branch) and idents[-1][1].empty?
124
- # Safe navigation operator is used. See :call clause also.
125
- idents[0..-2] + [Branch[extract_idents(sexp[2]) + idents[-1][0], []]]
126
- else
127
- idents[0..-2] + extract_idents(sexp[2]) + [idents[-1]]
128
- end
129
- end
130
- when :args_add_block
131
- _, (tag, ss0, *ss1), _ = sexp
132
- if tag == :args_add_star
133
- (ss0 + ss1).flat_map {|s| extract_idents(s) }
134
- else
135
- sexp[1].flat_map {|s| extract_idents(s) }
136
- end
137
- when :vcall
138
- _, (tag, name, (_, column)) = sexp
139
- if tag == :@ident
140
- [Ident[@proc_local_variables.include?(name) ? :ref : :method, name, column]]
141
- else
142
- []
143
- end
144
- when :program
145
- _, ((tag0, (tag1, (tag2, (tag3, mname, _)), _), (tag4, _, ss))) = sexp
146
- if tag0 == :method_add_block and tag1 == :method_add_arg and tag2 == :fcall and
147
- (tag3 == :@ident or tag3 == :@const) and mname == @assertion_method_name and (tag4 == :brace_block or tag4 == :do_block)
148
- ss.flat_map {|s| extract_idents(s) }
149
- else
150
- _, (s0, *) = sexp
151
- extract_idents(s0)
99
+ in [:array, ss]
100
+ ss ? ss.flat_map {|s| extract_idents(s) } : []
101
+ in [:command_call, s0, _, s1, s2]
102
+ [s0, s2, s1].flat_map {|s| extract_idents(s) }
103
+ in [:aref, s0, s1]
104
+ handle_columnless_ident(extract_idents(s0), :[], extract_idents(s1))
105
+ in [:method_add_arg, s0, s1]
106
+ case extract_idents(s0)
107
+ in []
108
+ # idents(s0) may be empty(e.g. ->{}.())
109
+ extract_idents(s1)
110
+ in [*is0, Branch[is1, []]]
111
+ # Safe navigation operator is used. See :call clause also.
112
+ is0 + [Branch[extract_idents(s1) + is1, []]]
113
+ in [*is, i]
114
+ is + extract_idents(s1) + [i]
152
115
  end
153
- when :ifop
154
- _, s0, s1, s2 = sexp
116
+ in [:args_add_block, [:args_add_star, ss0, *ss1], _]
117
+ (ss0 + ss1).flat_map {|s| extract_idents(s) }
118
+ in [:args_add_block, ss, _]
119
+ ss.flat_map {|s| extract_idents(s) }
120
+ in [:vcall, [:@ident, name, [_, column]]]
121
+ [Ident[@proc_local_variables.include?(name) ? :ref : :method, name, column]]
122
+ in [:vcall, _]
123
+ []
124
+ in [:program, [[:method_add_block, [:method_add_arg, [:fcall, [:@ident | :@const, ^@assertion_method_name, _]], _], [:brace_block | :do_block, _, ss]]]]
125
+ ss.flat_map {|s| extract_idents(s) }
126
+ in [:program, [s, *]]
127
+ extract_idents(s)
128
+ in [:ifop, s0, s1, s2]
155
129
  [*extract_idents(s0), Branch[extract_idents(s1), extract_idents(s2)]]
156
- when :if, :unless
157
- _, s0, ss0, (_, ss1) = sexp
158
- [*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, ss1 ? ss1.flat_map {|s| extract_idents(s) } : []]]
159
- when :if_mod, :unless_mod
160
- _, s0, s1 = sexp
130
+ in [:if | :unless, s0, ss0, [_, ss1]]
131
+ [*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, ss1.flat_map {|s| extract_idents(s) }]]
132
+ in [:if | :unless, s0, ss0, _]
133
+ [*extract_idents(s0), Branch[ss0.flat_map {|s| extract_idents(s) }, []]]
134
+ in [:if_mod | :unless_mod, s0, s1]
161
135
  [*extract_idents(s0), Branch[extract_idents(s1), []]]
162
- when :var_ref, :var_field
163
- _, (tag, ref_name, (_, column)) = sexp
164
- case tag
165
- when :@kw
166
- if ref_name == 'self'
167
- [Ident[:ref, 'self', column]]
168
- else
169
- []
170
- end
171
- when :@ident, :@const, :@cvar, :@ivar, :@gvar
172
- [Ident[:ref, ref_name, column]]
173
- else
174
- []
175
- end
176
- when :@ident, :@const, :@op
177
- _, method_name, (_, column) = sexp
136
+ in [:var_ref | :var_field, [:@kw, 'self', [_, column]]]
137
+ [Ident[:ref, 'self', column]]
138
+ in [:var_ref | :var_field, [:@ident | :@const | :@cvar | :@ivar | :@gvar, ref_name, [_, column]]]
139
+ [Ident[:ref, ref_name, column]]
140
+ in [:var_ref | :var_field, _]
141
+ []
142
+ in [:@ident | :@const | :@op, method_name, [_, column]]
178
143
  [Ident[:method, method_name, column]]
179
144
  else
180
145
  []
@@ -1,3 +1,3 @@
1
1
  module PowerAssert
2
- VERSION = "2.0.5"
2
+ VERSION = "3.0.0"
3
3
  end
data/lib/power_assert.rb CHANGED
@@ -3,18 +3,16 @@
3
3
  # Copyright (C) 2014 Kazuki Tsujimoto
4
4
 
5
5
  begin
6
- unless defined?(Byebug)
7
- captured = false
8
- target_thread = Thread.current
9
- TracePoint.new(:return, :c_return) do |tp|
10
- next unless Thread.current == target_thread
11
- captured = true
12
- unless tp.return_value and tp.callee_id
13
- raise ''
14
- end
15
- end.enable { __id__ }
16
- raise '' unless captured
17
- end
6
+ captured = false
7
+ target_thread = Thread.current
8
+ TracePoint.new(:return, :c_return) do |tp|
9
+ next unless Thread.current == target_thread
10
+ captured = true
11
+ unless tp.return_value and tp.callee_id
12
+ raise ''
13
+ end
14
+ end.enable { __id__ }
15
+ raise '' unless captured
18
16
  rescue
19
17
  raise LoadError, 'Fully compatible TracePoint API required'
20
18
  end
@@ -30,21 +28,8 @@ module PowerAssert
30
28
 
31
29
  class << self
32
30
  def start(assertion_proc_or_source, assertion_method: nil, source_binding: TOPLEVEL_BINDING)
33
- if respond_to?(:clear_global_method_cache, true)
34
- clear_global_method_cache
35
- end
36
- yield BlockContext.new(assertion_proc_or_source, assertion_method, source_binding)
37
- end
38
-
39
- def trace(frame)
40
- begin
41
- raise 'Byebug is not started yet' unless Byebug.started?
42
- rescue NameError
43
- raise "PowerAssert.#{__method__} requires Byebug"
44
- end
45
- ctx = TraceContext.new(frame._binding)
46
- ctx.enable
47
- ctx
31
+ clear_global_method_cache
32
+ yield Context.new(assertion_proc_or_source, assertion_method, source_binding)
48
33
  end
49
34
 
50
35
  def app_caller_locations
@@ -59,31 +44,16 @@ module PowerAssert
59
44
  private
60
45
 
61
46
  def internal_file?(file)
62
- setup_internal_lib_dir(Byebug, :attach, 2) if defined?(Byebug)
63
- setup_internal_lib_dir(PryByebug, :start_with_pry_byebug, 2, Pry) if defined?(PryByebug)
64
47
  INTERNAL_LIB_DIRS.find do |_, dir|
65
48
  file.start_with?(dir)
66
49
  end
67
50
  end
68
51
 
69
- def setup_internal_lib_dir(lib, mid, depth, lib_obj = lib)
70
- unless INTERNAL_LIB_DIRS.key?(lib)
71
- INTERNAL_LIB_DIRS[lib] = lib_dir(lib_obj, mid, depth)
72
- end
73
- rescue NameError
74
- end
75
-
76
- def lib_dir(obj, mid, depth)
77
- File.expand_path('../' * depth, obj.method(mid).source_location[0])
78
- end
79
-
80
- if defined?(RubyVM)
81
- CLEAR_CACHE_ISEQ = RubyVM::InstructionSequence.compile('using PowerAssert.const_get(:Empty)')
82
- private_constant :CLEAR_CACHE_ISEQ
52
+ CLEAR_CACHE_ISEQ = RubyVM::InstructionSequence.compile('using PowerAssert.const_get(:Empty)')
53
+ private_constant :CLEAR_CACHE_ISEQ
83
54
 
84
- def clear_global_method_cache
85
- CLEAR_CACHE_ISEQ.eval
86
- end
55
+ def clear_global_method_cache
56
+ CLEAR_CACHE_ISEQ.eval
87
57
  end
88
58
  end
89
59
 
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: power_assert
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.5
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kazuki Tsujimoto
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-12-23 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: Power Assert shows each value of variables and method calls in the expression.
14
13
  It is useful for testing, providing which value wasn't correct when the condition
@@ -43,7 +42,6 @@ licenses:
43
42
  - BSD-2-Clause
44
43
  - Ruby
45
44
  metadata: {}
46
- post_install_message:
47
45
  rdoc_options:
48
46
  - "--main"
49
47
  - README.md
@@ -60,8 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
58
  - !ruby/object:Gem::Version
61
59
  version: '0'
62
60
  requirements: []
63
- rubygems_version: 3.5.3
64
- signing_key:
61
+ rubygems_version: 3.6.9
65
62
  specification_version: 4
66
63
  summary: Power Assert for Ruby
67
64
  test_files: []