Issue #12299 has been updated by jeremyevans0 (Jeremy Evans).


Eregon (Benoit Daloze) wrote:
> This feature is great, thank you for introducing it!
> 
> A couple things I noticed while using it for ruby/spec:
> https://github.com/ruby/mspec/commit/954054c03da1c90c9653f238c78c888644760ab8
> 
> * Parser warnings are emitted at parse time. This is expected but makes them harder to filter
>   as for instance changing $VERBOSE around does not have effect, nor defining Warning.warn before running a method.
>   One workaround is to use #eval which then delays the warnings until execution of the eval expression.

I think this is expected.  If you want to filter/process warnings, it's best to setup `Warning.warn` close to process initialization, before loading other files.

> * Kernel#warn does not use Warning.warn yet, so one needs to entirely redefine Kernel#warn which is not so trivial (see commit).

This was fixed after 2.4 was released (r57370).  In trunk, `Kernel#warn` calls `Warning.warn`.

> * Warning #extend itself. This is a common pattern in Ruby but I have never seen it in core modules before.
>   It confused me while looking in a REPL:
> 
> ~~~ ruby
> > Warning.methods(false)
> => []
> > Warning.method :warn
> => #<Method: Module(Warning)#warn>
> ~~~
> 
> On the upside it allows to call super in Warning.warn, but that's mostly $stderr.write(message).
> Is there any reason to make Warning#warn include-able?

Precisely because it makes it easier to define `Warning.warn` manually and call super to get default behavior.  Without this, if you wanted to override and call super, you would have to use `Module#prepend`, which is more work.  `Warning.warn` was added specifically to make it easy to override the default handling of warnings. 

> I think it would be less surprising to just have the singleton Warning.warn method.

Other than using `Warning.methods(false)`, I doubt anyone would notice.  In any case, it can't be changed now without breaking backwards compatibility, as existing libraries already rely on the current behavior.

----------------------------------------
Feature #12299: Add Warning module for customized warning handling
https://bugs.ruby-lang.org/issues/12299#change-64442

* Author: jeremyevans0 (Jeremy Evans)
* Status: Closed
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
This is another attempt to provide the same type of support for customized warning handling as #12026.  matz had a couple of issues with #12026.  First, he did not like the introduction of a new global variable.  Second, he wanted the ability to control warning handling on a per-gem and/or per-class basis.

The approach in this patch adds a Warning module instead of using a global variable, and allows for per-gem customization by using separate processing for separate gems based on the path prefix in the warning message.  I don't think per-class warnings are possible without major changes.

This changes all warnings raised call to Warning.warn, which by default does the same thing it does currently (rb_write_error_str).  You can override Warning.warn to change the behavior.

To provide a common API that can be used to modify warnings, add a lib/warning.rb file, which offers three methods: Warning.ignore, Warning.process, and Warning.clear.

Warning.ignore takes a regexp and optionally a path prefix, and ignores any warning that matches the regular expression if it starts with the path prefix.

Warning.process takes an optional path prefix and a block, and if the string starts with the path prefix, it calls the block with the warning string instead of performing the default behavior. You can call Warning.process multiple times and it will be operate intelligently, choosing the longest path prefix that the string starts with.

Warning.clear just clears the current ignored warnings and warning processors.

By using path prefixes, it's fairly easy for a gem to set that warnings should be ignored inside the gem's directory.

Note that path prefixes will not correctly handle warnings raised by Kernel#warn, unless the warning message given to Kernel#warn starts with the filename where the warning is used.

Note that the current implementations of Warning.ignore, Warning.process, and Warning.clear in the patch are not thread safe, but that can be changed without much difficulty.

Examples from the RDoc in the patch:

~~~
# Ignore all uninitialized instance variable warnings
Warning.ignore(/instance variable @\w+ not initialized/)

# Ignore all uninitialized instance variable warnings in current file
Warning.ignore(/instance variable @\w+ not initialized/, __FILE__)

# Write warning to LOGGER at level warning
Warning.process do |warning|
  LOGGER.warning(warning)
end

# Write warnings in the current file to LOGGER at level error
Warning.process(__FILE__) do |warning|
  LOGGER.error(warning)
end
~~~


---Files--------------------------------
0001-Add-Warning-module-for-customized-warning-handling.patch (10.1 KB)
0001-Add-Exception-Warning-module-for-customized-warning-.patch (10.7 KB)
0001-Add-Warning-module-for-customized-warning-handling.patch (4.7 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>