Skip to content

Commit 1efdf6b

Browse files
committed
Subclasses initialize must call super
Warn wrong code, #100: > Some Ruby apps subclass Logger without running the superclass > constructor, which means that `@level_override` isn't initialized > properly.
1 parent 30e4359 commit 1efdf6b

File tree

2 files changed

+24
-0
lines changed

2 files changed

+24
-0
lines changed

lib/logger.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -749,6 +749,15 @@ def format_severity(severity)
749749

750750
# Guarantee the existence of this ivar even when subclasses don't call the superclass constructor.
751751
def level_override
752+
unless defined?(@level_override)
753+
bad = self.class.instance_method(:initialize)
754+
file, line = bad.source_location
755+
Kernel.warn <<~";;;", uplevel: 2
756+
Logger not initialized properly
757+
#{file}:#{line}: info: #{bad.owner}\##{bad.name}: \
758+
does not call super probably
759+
;;;
760+
end
752761
@level_override ||= {}
753762
end
754763

test/logger/test_logger.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,4 +399,19 @@ def test_does_not_instantiate_log_device_for_File_NULL
399399
l = Logger.new(File::NULL)
400400
assert_nil(l.instance_variable_get(:@logdev))
401401
end
402+
403+
def test_subclass_initialize
404+
bad_logger = Class.new(Logger) {def initialize(*); end}.new(IO::NULL)
405+
line = __LINE__ - 1
406+
file = Regexp.quote(__FILE__)
407+
assert_warning(/not initialized properly.*\n#{file}:#{line}:/) do
408+
bad_logger.level
409+
end
410+
411+
good_logger = Class.new(Logger) {def initialize(*); super; end}.new(IO::NULL)
412+
file = Regexp.quote(__FILE__)
413+
assert_warning('') do
414+
good_logger.level
415+
end
416+
end
402417
end

0 commit comments

Comments
 (0)