diff options
Diffstat (limited to 'lib/syntax_suggest/core_ext.rb')
-rw-r--r-- | lib/syntax_suggest/core_ext.rb | 89 |
1 files changed, 51 insertions, 38 deletions
diff --git a/lib/syntax_suggest/core_ext.rb b/lib/syntax_suggest/core_ext.rb index 40f5fe1375..c299627bb7 100644 --- a/lib/syntax_suggest/core_ext.rb +++ b/lib/syntax_suggest/core_ext.rb @@ -3,6 +3,10 @@ # Ruby 3.2+ has a cleaner way to hook into Ruby that doesn't use `require` if SyntaxError.method_defined?(:detailed_message) module SyntaxSuggest + # Mini String IO [Private] + # + # Acts like a StringIO with reduced API, but without having to require that + # class. class MiniStringIO def initialize(isatty: $stderr.isatty) @string = +"" @@ -16,52 +20,61 @@ if SyntaxError.method_defined?(:detailed_message) attr_reader :string end - end - - SyntaxError.prepend Module.new { - def detailed_message(highlight: true, syntax_suggest: true, **kwargs) - return super unless syntax_suggest - - require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE) - - message = super - file = if highlight - SyntaxSuggest::PathnameFromMessage.new(super(highlight: false, **kwargs)).call.name - else - SyntaxSuggest::PathnameFromMessage.new(message).call.name - end - - io = SyntaxSuggest::MiniStringIO.new - if file - SyntaxSuggest.call( - io: io, - source: file.read, - filename: file, - terminal: highlight - ) - annotation = io.string - - annotation + message - else - message - end - rescue => e - if ENV["SYNTAX_SUGGEST_DEBUG"] - $stderr.warn(e.message) - $stderr.warn(e.backtrace) - end - - # Ignore internal errors - message + # SyntaxSuggest.module_for_detailed_message [Private] + # + # Used to monkeypatch SyntaxError via Module.prepend + def self.module_for_detailed_message + Module.new { + def detailed_message(highlight: true, syntax_suggest: true, **kwargs) + return super unless syntax_suggest + + require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE) + + message = super + + if path + file = Pathname.new(path) + io = SyntaxSuggest::MiniStringIO.new + + SyntaxSuggest.call( + io: io, + source: file.read, + filename: file, + terminal: highlight + ) + annotation = io.string + + annotation += "\n" unless annotation.end_with?("\n") + + annotation + message + else + message + end + rescue => e + if ENV["SYNTAX_SUGGEST_DEBUG"] + $stderr.warn(e.message) + $stderr.warn(e.backtrace) + end + + # Ignore internal errors + message + end + } end - } + end + + SyntaxError.prepend(SyntaxSuggest.module_for_detailed_message) else autoload :Pathname, "pathname" + #-- # Monkey patch kernel to ensure that all `require` calls call the same # method + #++ module Kernel + # :stopdoc: + module_function alias_method :syntax_suggest_original_require, :require |