[ruby/json] Fix duplicated key warning location

Followup: https://github.com/ruby/json/pull/818

Now the warning should point at the `JSON.parse` caller, and not
inside the json gem itself.

cd51557387
This commit is contained in:
Jean Boussier 2025-07-27 14:31:40 +02:00 committed by Hiroshi SHIBATA
parent b4ef5da70b
commit d0020d58f4
3 changed files with 27 additions and 19 deletions

View file

@ -48,7 +48,7 @@ module JSON
end end
end end
# TODO: exctract :create_additions support to another gem for version 3.0 # TODO: extract :create_additions support to another gem for version 3.0
def create_additions_proc(opts) def create_additions_proc(opts)
if opts[:symbolize_names] if opts[:symbolize_names]
raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction" raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction"
@ -87,31 +87,32 @@ module JSON
opts opts
end end
GEM_ROOT = File.expand_path("../../../", __FILE__) + "/"
def create_additions_warning def create_additions_warning
message = "JSON.load implicit support for `create_additions: true` is deprecated " \ JSON.deprecation_warning "JSON.load implicit support for `create_additions: true` is deprecated " \
"and will be removed in 3.0, use JSON.unsafe_load or explicitly " \ "and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
"pass `create_additions: true`" "pass `create_additions: true`"
uplevel = 4
caller_locations(uplevel, 10).each do |frame|
if frame.path.nil? || frame.path.start_with?(GEM_ROOT) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
uplevel += 1
else
break
end
end
if RUBY_VERSION >= "3.0"
warn(message, uplevel: uplevel - 1, category: :deprecated)
else
warn(message, uplevel: uplevel - 1)
end
end end
end end
end end
class << self class << self
def deprecation_warning(message, uplevel = 4) # :nodoc:
gem_root = File.expand_path("../../../", __FILE__) + "/"
caller_locations(uplevel, 10).each do |frame|
if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
uplevel += 1
else
break
end
end
if RUBY_VERSION >= "3.0"
warn(message, uplevel: uplevel - 1, category: :deprecated)
else
warn(message, uplevel: uplevel - 1)
end
end
# :call-seq: # :call-seq:
# JSON[object] -> new_array or new_string # JSON[object] -> new_array or new_string
# #

View file

@ -422,7 +422,8 @@ static void emit_parse_warning(const char *message, JSON_ParserState *state)
long line, column; long line, column;
cursor_position(state, &line, &column); cursor_position(state, &line, &column);
rb_warn("%s at line %ld column %ld", message, line, column); VALUE warning = rb_sprintf("%s at line %ld column %ld", message, line, column);
rb_funcall(mJSON, rb_intern("deprecation_warning"), 1, warning);
} }
#define PARSE_ERROR_FRAGMENT_LEN 32 #define PARSE_ERROR_FRAGMENT_LEN 32

View file

@ -346,6 +346,12 @@ class JSONParserTest < Test::Unit::TestCase
assert_equal expected_sym, parse('{"a": 1, "a": 2}', symbolize_names: true) assert_equal expected_sym, parse('{"a": 1, "a": 2}', symbolize_names: true)
end end
if RUBY_ENGINE == 'RUBY_ENGINE'
assert_deprecated_warning(/#{File.basename(__FILE__)}\:#{__LINE__ + 1}/) do
assert_equal expected, parse('{"a": 1, "a": 2}')
end
end
unless RUBY_ENGINE == 'jruby' unless RUBY_ENGINE == 'jruby'
assert_raise(ParserError) do assert_raise(ParserError) do
fake_key = Object.new fake_key = Object.new