Skip to content

Commit b3d0ae4

Browse files
hsbtclaude
andcommitted
Lazy load error_highlight, did_you_mean, and syntax_suggest
Replace eager require with autoload + a one-shot Exception#detailed_message hook. At boot, gem_prelude.rb replaces the empty marker modules (from rb_define_module in ruby.c) with autoload entries. Direct constant access triggers autoload transparently; error display uses the hook. During gem loading, Kernel#require is temporarily restored to the original (pre-monkeypatch) version so that nested requires inside the gems are not intercepted by user monkeypatching. [Feature #21951] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 41978d8 commit b3d0ae4

1 file changed

Lines changed: 40 additions & 15 deletions

File tree

gem_prelude.rb

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,45 @@
88
require 'bundled_gems'
99
end if defined?(Gem)
1010

11-
begin
12-
require 'error_highlight'
13-
rescue LoadError
14-
warn "`error_highlight' was not loaded."
15-
end if defined?(ErrorHighlight)
11+
if defined?(ErrorHighlight) || defined?(DidYouMean) || defined?(SyntaxSuggest)
12+
# Replace empty modules with autoload entries for lazy loading.
13+
# Direct constant access (e.g. DidYouMean::SpellChecker) triggers
14+
# autoload transparently; error display uses the hook below.
15+
if defined?(ErrorHighlight)
16+
Object.send(:remove_const, :ErrorHighlight)
17+
autoload :ErrorHighlight, 'error_highlight'
18+
end
19+
if defined?(DidYouMean)
20+
Object.send(:remove_const, :DidYouMean)
21+
autoload :DidYouMean, 'did_you_mean'
22+
end
23+
if defined?(SyntaxSuggest)
24+
Object.send(:remove_const, :SyntaxSuggest)
25+
autoload :SyntaxSuggest, 'syntax_suggest'
26+
end
1627

17-
begin
18-
require 'did_you_mean'
19-
rescue LoadError
20-
warn "`did_you_mean' was not loaded."
21-
end if defined?(DidYouMean)
28+
module Exception::DetailedMessage # :nodoc:
29+
@require = Kernel.instance_method(:require)
2230

23-
begin
24-
require 'syntax_suggest/core_ext'
25-
rescue LoadError
26-
warn "`syntax_suggest' was not loaded."
27-
end if defined?(SyntaxSuggest)
31+
def detailed_message(...)
32+
gem_above = self.class.instance_method(:detailed_message).owner != Exception::DetailedMessage
33+
34+
# Temporarily restore the original require to bypass any user
35+
# monkeypatching during gem loading (including nested requires).
36+
orig = Exception::DetailedMessage.instance_variable_get(:@require)
37+
patched = Kernel.instance_method(:require)
38+
Kernel.define_method(:require, orig)
39+
begin
40+
require 'error_highlight' rescue LoadError
41+
require 'did_you_mean' rescue LoadError
42+
require 'syntax_suggest' rescue LoadError
43+
ensure
44+
Kernel.define_method(:require, patched)
45+
end
46+
47+
Exception::DetailedMessage.remove_method(:detailed_message)
48+
gem_above ? super : detailed_message(...)
49+
end
50+
end
51+
Exception.prepend(Exception::DetailedMessage)
52+
end

0 commit comments

Comments
 (0)