warning 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0fd71447749bdaad9176ecb3eb6302104bcaf5401516719beed80594d2fa234a
4
- data.tar.gz: 18eee8db50ef702428bcfd5690c3f92d013b4b8013dd6cd28e554ff808cccbd6
3
+ metadata.gz: 719af8cdb41da57d07edb0fa0eac81d2bb017d5d816cadf98e600cc75e63f4aa
4
+ data.tar.gz: 169550daf070386f36072d01c9c36303c631b6f598cf358e0f16e786f1d4ac68
5
5
  SHA512:
6
- metadata.gz: 8038062c8d96ec8eb800be734041654d3dd24a1a5ddda523c5c44f465f7cbdf3fdbaa3537e4d360ad9673effb4a54e27de544325235b0fe343ec13f6ee3ec948
7
- data.tar.gz: 26324dfc9591fda0a4627d515c3b18738e55f3213c0ff76b15f7493616980c54cf3cf3b945985d460d230db69b57ccd687f2b4ac5f367feec1b1efeae72319f0
6
+ metadata.gz: 5ddf24399c73e0b2b747189d02972c3616482ac90c3c9e89b16b8594a1e2c6cf005b3b81bab905de6f30d3fd1882d806c8746fd317f59e6915408f80f054ee8f
7
+ data.tar.gz: a5f1d714b59737dd6e67ab000687783acff87c3fe5cfd85bac2828c91556a7de5637d082e82d0a34198b53580a324c69639da93e07c0436e4f648e0031c7ff00
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ === 1.1.0 (2020-06-12)
2
+
3
+ * Allow Warning.process to be called with a hash of actions instead of a block (jeremyevans)
4
+
5
+ * Handle Warning.process blocks that return :default, :backtrace, or :raise specially (jeremyevans)
6
+
7
+ * Add support for :mismatched_indentations as regexp argument to Warning.ignore (qortex) (#7)
8
+
1
9
  === 1.0.0 (2020-01-21)
2
10
 
3
11
  * Add support for :taint as regexp argument to Warning.ignore (jeremyevans)
@@ -1,4 +1,4 @@
1
- Copyright (c) 2016 Jeremy Evans
1
+ Copyright (c) 2016-2020 Jeremy Evans
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
@@ -2,7 +2,8 @@
2
2
 
3
3
  ruby-warning adds custom processing for warnings, including the
4
4
  ability to ignore specific warning messages, ignore warnings
5
- in specific files/directories, deduplicate warnings, and add
5
+ in specific files/directories, include backtraces with warnings,
6
+ treat warnings as errors, deduplicate warnings, and add
6
7
  custom handling for all warnings in specific files/directories.
7
8
 
8
9
  ruby-warning requires ruby 2.4+, as previous versions of ruby do
@@ -32,6 +33,7 @@ appropriate regexp. The supported symbols are:
32
33
  * :fixnum
33
34
  * :keyword_separation
34
35
  * :method_redefined
36
+ * :mismatched_indentations
35
37
  * :missing_gvar
36
38
  * :missing_ivar
37
39
  * :not_reached
@@ -47,6 +49,14 @@ string instead of performing the default behavior. You can call
47
49
  <tt>Warning.process</tt> multiple times and it will operate intelligently,
48
50
  choosing the longest path prefix that the string starts with.
49
51
 
52
+ <tt>Warning.process</tt> blocks can return +:default+ to use the default
53
+ behavior, +:backtrace+ to use the default behavior and also print the backtrace
54
+ or +:raise+ to raise the warning string as a RuntimeError.
55
+
56
+ <tt>Warning.process</tt> can also accept a hash of actions instead of a block,
57
+ with keys being regexps (or symbols supported by <tt>Warning.ignore</tt>) and
58
+ values being callable objects (or +:default+, +:backtrace+, or +:raise+).
59
+
50
60
  <tt>Warning.dedup</tt> deduplicates warnings, so that if a warning is received
51
61
  that is the same as a warning that has already been processed, the warning is
52
62
  ignored. Note that this should be used with care, since if the application
@@ -93,6 +103,23 @@ loading any code that could cause warnings.
93
103
  LOGGER.error(warning)
94
104
  end
95
105
 
106
+ # Write warnings in the current file to $stderr, but include backtrace
107
+ Warning.process(__FILE__) do |warning|
108
+ :backtrace
109
+ end
110
+
111
+ # Raise warnings in the current file as RuntimeErrors, with the warning
112
+ # string as the exception message
113
+ Warning.process(__FILE__) do |warning|
114
+ :raise
115
+ end
116
+
117
+ # Raise keyword argument separation warnings in the current file as
118
+ # RuntimeErrors, and write ambiguous slash warnings to $stderr, including
119
+ # the backtrace
120
+ Warning.process(__FILE__, keyword_separation: :raise,
121
+ ambiguous_slash: :backtrace)
122
+
96
123
  # Deduplicate warnings
97
124
  Warning.dedup
98
125
 
@@ -18,8 +18,17 @@ module Warning
18
18
  keyword_separation: /: warning: (?:Using the last argument (?:for `.+' )?as keyword parameters is deprecated; maybe \*\* should be added to the call|Passing the keyword argument (?:for `.+' )?as the last hash parameter is deprecated|Splitting the last argument (?:for `.+' )?into positional and keyword parameters is deprecated|The called method (?:`.+' )?is defined here)\n\z/,
19
19
  safe: /: warning: (?:rb_safe_level_2_warning|rb_safe_level|rb_set_safe_level_force|rb_set_safe_level|rb_secure|rb_insecure_operation|rb_check_safe_obj|\$SAFE) will (?:be removed|become a normal global variable) in Ruby 3\.0\n\z/,
20
20
  taint: /: warning: (?:rb_error_untrusted|rb_check_trusted|Pathname#taint|Pathname#untaint|rb_env_path_tainted|Object#tainted\?|Object#taint|Object#untaint|Object#untrusted\?|Object#untrust|Object#trust|rb_obj_infect|rb_tainted_str_new|rb_tainted_str_new_cstr) is deprecated and will be removed in Ruby 3\.2\.\n\z/,
21
+ mismatched_indentations: /: warning: mismatched indentations at '.+' with '.+' at \d+\n\z/,
21
22
  }
22
23
 
24
+ # Map of action symbols to procs that return the symbol
25
+ ACTION_PROC_MAP = {
26
+ default: proc{|_| :default},
27
+ backtrace: proc{|_| :backtrace},
28
+ raise: proc{|_| :raise},
29
+ }
30
+ private_constant :ACTION_PROC_MAP
31
+
23
32
  # Clear all current ignored warnings, warning processors, and duplicate check cache.
24
33
  # Also disables deduplicating warnings if that is currently enabled.
25
34
  def clear
@@ -81,14 +90,7 @@ module Warning
81
90
  # # Ignore all uninitialized instance variable and method redefined warnings in current file
82
91
  # Warning.ignore([:missing_ivar, :method_redefined], __FILE__)
83
92
  def ignore(regexp, path='')
84
- case regexp
85
- when Regexp
86
- # already regexp
87
- when Symbol
88
- regexp = IGNORE_MAP.fetch(regexp)
89
- when Array
90
- regexp = Regexp.union(regexp.map{|re| IGNORE_MAP.fetch(re)})
91
- else
93
+ unless regexp = convert_regexp(regexp)
92
94
  raise TypeError, "first argument to Warning.ignore should be Regexp, Symbol, or Array of Symbols, got #{regexp.inspect}"
93
95
  end
94
96
 
@@ -110,7 +112,52 @@ module Warning
110
112
  # Warning.process(__FILE__) do |warning|
111
113
  # LOGGER.error(warning)
112
114
  # end
113
- def process(path='', &block)
115
+ #
116
+ # The block can return one of the following symbols:
117
+ #
118
+ # :default :: Take the default action (call super, printing to $stderr).
119
+ # :backtrace :: Take the default action (call super, printing to $stderr),
120
+ # and also print the backtrace.
121
+ # :raise :: Raise a RuntimeError with the warning as the message.
122
+ #
123
+ # If the block returns anything else, it is assumed the block completely handled
124
+ # the warning and takes no other action.
125
+ #
126
+ # Instead of passing a block, you can pass a hash of actions to take for specific
127
+ # warnings, using regexp as keys and a callable objects as values:
128
+ #
129
+ # Warning.ignore(__FILE__,
130
+ # /instance variable @\w+ not initialized/ => proc do |warning|
131
+ # LOGGER.warning(warning)
132
+ # end,
133
+ # /global variable `\$\w+' not initialized/ => proc do |warning|
134
+ # LOGGER.error(warning)
135
+ # end
136
+ # )
137
+ #
138
+ # Instead of passing a regexp as a key, you can pass a symbol that is recognized
139
+ # by Warning.ignore. Instead of passing a callable object as a value, you can
140
+ # pass a symbol, which will be treated as a callable object that returns that symbol:
141
+ #
142
+ # Warning.process(__FILE__, :missing_ivar=>:backtrace, :keyword_separation=>:raise)
143
+ def process(path='', actions=nil, &block)
144
+ if block
145
+ if actions
146
+ raise ArgumentError, "cannot pass both actions and block to Warning.process"
147
+ end
148
+ elsif actions
149
+ block = {}
150
+ actions.each do |regexp, value|
151
+ unless regexp = convert_regexp(regexp)
152
+ raise TypeError, "action provided to Warning.process should be Regexp, Symbol, or Array of Symbols, got #{regexp.inspect}"
153
+ end
154
+
155
+ block[regexp] = ACTION_PROC_MAP[value] || value
156
+ end
157
+ else
158
+ raise ArgumentError, "must pass either actions or block to Warning.process"
159
+ end
160
+
114
161
  synchronize do
115
162
  @process << [path, block]
116
163
  @process.sort_by!(&:first)
@@ -138,18 +185,55 @@ module Warning
138
185
  synchronize{@dedup[str] = true}
139
186
  end
140
187
 
141
- synchronize{@process.dup}.each do |path, block|
142
- if str.start_with?(path)
143
- block.call(str)
144
- return
188
+ action = catch(:action) do
189
+ synchronize{@process.dup}.each do |path, block|
190
+ if str.start_with?(path)
191
+ if block.is_a?(Hash)
192
+ block.each do |regexp, blk|
193
+ if str =~ regexp
194
+ throw :action, blk.call(str)
195
+ end
196
+ end
197
+ else
198
+ throw :action, block.call(str)
199
+ end
200
+ end
145
201
  end
202
+
203
+ :default
146
204
  end
147
205
 
148
- super
206
+ case action
207
+ when :default
208
+ super
209
+ when :backtrace
210
+ super
211
+ $stderr.puts caller
212
+ when :raise
213
+ raise str
214
+ else
215
+ # nothing
216
+ end
217
+
218
+ nil
149
219
  end
150
220
 
151
221
  private
152
222
 
223
+ # Convert the given Regexp, Symbol, or Array of Symbols into a Regexp.
224
+ def convert_regexp(regexp)
225
+ case regexp
226
+ when Regexp
227
+ regexp
228
+ when Symbol
229
+ IGNORE_MAP.fetch(regexp)
230
+ when Array
231
+ Regexp.union(regexp.map{|re| IGNORE_MAP.fetch(re)})
232
+ else
233
+ # nothing
234
+ end
235
+ end
236
+
153
237
  def synchronize(&block)
154
238
  @monitor.synchronize(&block)
155
239
  end
@@ -0,0 +1,4 @@
1
+ # Example that will trigger the "mismatched indentations" warning from Ruby
2
+ if 2 > 1
3
+ true
4
+ end
@@ -6,8 +6,12 @@ require 'pathname'
6
6
  class WarningTest < Minitest::Test
7
7
  module EnvUtil
8
8
  def verbose_warning
9
+ stderr = ""
9
10
  class << (stderr = "")
10
11
  alias write <<
12
+ def puts(*a)
13
+ self << a.join("\n")
14
+ end
11
15
  end
12
16
  stderr, $stderr, verbose, $VERBOSE = $stderr, stderr, $VERBOSE, true
13
17
  yield stderr
@@ -351,6 +355,18 @@ class WarningTest < Minitest::Test
351
355
  end
352
356
  end
353
357
 
358
+ def test_warning_ignore_mismatched_indentation
359
+ assert_warning(/warning: mismatched indentations/) do
360
+ load 'test/fixtures/mismatched_indentations.rb'
361
+ end
362
+
363
+ Warning.ignore(:mismatched_indentations, 'test/fixtures/mismatched_indentations.rb')
364
+
365
+ assert_warning '' do
366
+ load 'test/fixtures/mismatched_indentations.rb'
367
+ end
368
+ end
369
+
354
370
  def test_warning_process
355
371
  obj = Object.new
356
372
  warn = nil
@@ -414,4 +430,86 @@ class WarningTest < Minitest::Test
414
430
  assert_equal(4, warn.first)
415
431
  assert_match(/instance variable @ivar6 not initialized/, warn.last)
416
432
  end
433
+
434
+ def test_warning_process_block_return_default
435
+ w = nil
436
+ Warning.process(__FILE__) do |warning|
437
+ w = warning
438
+ :default
439
+ end
440
+
441
+ assert_warning(/instance variable @ivar not initialized/) do
442
+ ivar
443
+ end
444
+ assert_match(/instance variable @ivar not initialized/, w)
445
+ end
446
+
447
+ def test_warning_process_block_return_backtrace
448
+ w = nil
449
+ Warning.process(__FILE__) do |warning|
450
+ w = warning
451
+ :backtrace
452
+ end
453
+
454
+ assert_warning(/instance variable @ivar not initialized.*#{__FILE__}/m) do
455
+ ivar
456
+ end
457
+ assert_match(/instance variable @ivar not initialized/, w)
458
+ end
459
+
460
+ def test_warning_process_block_return_raise
461
+ w = nil
462
+ Warning.process(__FILE__) do |warning|
463
+ w = warning
464
+ :raise
465
+ end
466
+
467
+ assert_raises(RuntimeError, /instance variable @ivar not initialized/) do
468
+ EnvUtil.verbose_warning{ivar}
469
+ end
470
+ assert_match(/instance variable @ivar not initialized/, w)
471
+ end
472
+
473
+ def test_warning_process_action
474
+ w = nil
475
+ Warning.process(__FILE__, :missing_ivar=>:default, :missing_gvar=>:backtrace, :ambiguous_slash=>:raise)
476
+ Warning.process(__FILE__, :not_reached=>proc do |warning|
477
+ w = warning
478
+ :raise
479
+ end)
480
+
481
+ assert_warning(/instance variable @ivar not initialized/) do
482
+ ivar
483
+ end
484
+
485
+ assert_warning(/global variable `\$gvar' not initialized.*#{__FILE__}/m) do
486
+ $gvar
487
+ end
488
+
489
+ Warning.process(__FILE__) do |warning|
490
+ w = warning
491
+ :raise
492
+ end
493
+
494
+ assert_raises(RuntimeError, /warning: ambiguous first argument; put parentheses or a space even after `\/' operator/) do
495
+ EnvUtil.verbose_warning{instance_eval('d /a/', __FILE__)}
496
+ end
497
+
498
+ assert_raises(RuntimeError, /warning: statement not reached/) do
499
+ EnvUtil.verbose_warning{instance_eval('def self.b; return; 1 end', __FILE__)}
500
+ end
501
+ assert_match(/warning: statement not reached/, w)
502
+ end
503
+
504
+ def test_warning_process_action_and_block
505
+ assert_raises(ArgumentError) do
506
+ Warning.process(__FILE__)
507
+ end
508
+ end
509
+
510
+ def test_warning_process_no_action_and_no_block
511
+ assert_raises(ArgumentError) do
512
+ Warning.process(__FILE__, :missing_ivar=>:default){}
513
+ end
514
+ end
417
515
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: warning
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Evans
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-21 00:00:00.000000000 Z
11
+ date: 2020-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest-global_expectations
@@ -27,8 +27,9 @@ dependencies:
27
27
  description: |
28
28
  ruby-warning adds custom processing for warnings, including the
29
29
  ability to ignore specific warning messages, ignore warnings
30
- in specific files/directories, and add custom handling for all
31
- warnings in specific files/directories.
30
+ in specific files/directories, include backtraces with warnings,
31
+ treat warnings as errors, deduplicate warnings, and add
32
+ custom handling for all warnings in specific files/directories.
32
33
  email: code@jeremyevans.net
33
34
  executables: []
34
35
  extensions: []
@@ -42,6 +43,7 @@ files:
42
43
  - README.rdoc
43
44
  - Rakefile
44
45
  - lib/warning.rb
46
+ - test/fixtures/mismatched_indentations.rb
45
47
  - test/test_freeze_warning.rb
46
48
  - test/test_warning.rb
47
49
  homepage: https://github.com/jeremyevans/ruby-warning