Structured Warnings

Visit http://www.oreillynet.com/ruby/blog/2008/02/structured_warnings_now.html for a summary of what's to follow.

Ruby currently doesn't not support structured warnings, i.e. it uses the 'warn' method, and that emits a message to STDERR. It's behavior is governed by -W levels ranging from 0 to 2.

Problems with Ruby's warn system

  • The semantics aren't clearly understood and feel largely arbitrary.
  • It's impossible to suppress or allow warnings at a granular level, i.e. it's all or nothing.
  • They aren't testable.
  • There is no backtrace information provided. That means you have to wade through the source to find out where the warning came from.

Warnings in Sapphire

Sapphire will implement a structured warning system. In other words, there will be a hierarchy of warning classes that all descend from a base Warning class. Examples include TypeWarning, UninitializeWarning, UnusedBlockWarning, etc. A specific warning can then raised:
class Foo
  def old_method
    warn DeprecatedWarning, "This method is deprecated. Use 'new_method' instead." 
    # Continue on
  end
end

Testing Warnings

The ability to explicitly raise specific types of warnings then makes them testable. For example:
require 'test/unit'

class TC_Foo_Tests < Test::Unit::TestCase
  def setup
    @foo = Foo.new
  end

  # Assume we've added an assert_warn method to Test::Unit
  def test_old_method
    assert_warn(DeprecatedMethodWarning){ @foo.old_method }
  end
end

Disabling Warnings

Warnings can be disabled globally or temporarily within a block. For example, to globally disable deprecation warnings you could do this:
DeprecatedWarning.disable
To disable deprecation warnings temporarily, use a block. For example:
# No warnings here.
DeprecatedMethodWarning.disable{
  [1,2,3,4,5].indexes(1,3) # Array#indexes is a deprecated method
}

# But here I would get a warning since it's outside the block:
[1,2,3,4,5].indexes(1,3)

Other Semantics

  • Calling warn without an explicit warning type will raise a StandardWarning, just as raise without an explicit error type will raise a StandardError.
  • You cannot rescue a warning, nor use it in conjunction with retry. Warnings are informational only.

Third Party Implementations

Gregor Schmidt has implemented structured warnings as a library. See http://rug-b.rubyforge.org/structured_warnings/ for more information.

Also available in: HTML TXT