Skip to content

Commit

Permalink
Merge syntax_suggest master
Browse files Browse the repository at this point in the history
  • Loading branch information
hsbt committed Dec 9, 2022
1 parent 9557c8e commit 0677bbe
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 52 deletions.
89 changes: 45 additions & 44 deletions lib/syntax_suggest/core_ext.rb
Expand Up @@ -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 = +""
Expand All @@ -16,52 +20,49 @@ def puts(value = $/, **)

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 respond_to?(:path)
path
elsif highlight
# This branch will be removed when the next Ruby 3.2 preview is released with
# support for SyntaxError#path
SyntaxSuggest::PathnameFromMessage.new(super(highlight: false, **kwargs)).call.name
else
SyntaxSuggest::PathnameFromMessage.new(message).call.name
end

if file
file = Pathname.new(file)
io = SyntaxSuggest::MiniStringIO.new

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.record_dir [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 + 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"

Expand Down
12 changes: 10 additions & 2 deletions spec/syntax_suggest/integration/ruby_command_line_spec.rb
Expand Up @@ -76,9 +76,17 @@ module SyntaxSuggest
end
end

it "annotates a syntax error in Ruby 3.2+ when require is not used" do
pending("Support for SyntaxError#detailed_message monkeypatch needed https://gist.github.com/schneems/09f45cc23b9a8c46e9af6acbb6e6840d?permalink_comment_id=4172585#gistcomment-4172585")
it "gem can be tested when executing on Ruby with default gem included" do
skip if ruby_core?
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

out = `ruby -I#{lib_dir} -rsyntax_suggest -e "puts SyntaxError.instance_method(:detailed_message).source_location" 2>&1`

expect($?.success?).to be_truthy
expect(out).to include(lib_dir.join("syntax_suggest").join("core_ext.rb").to_s).once
end

it "annotates a syntax error in Ruby 3.2+ when require is not used" do
skip if ruby_core?
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

Expand Down
30 changes: 24 additions & 6 deletions spec/syntax_suggest/unit/api_spec.rb
Expand Up @@ -65,11 +65,20 @@ def fake_error.message
it "respects highlight API" do
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

error = SyntaxError.new("#{fixtures_dir.join("this_project_extra_def.rb.txt")}:1 ")
core_ext_file = lib_dir.join("syntax_suggest").join("core_ext.rb")
require_relative core_ext_file

skip if error.respond_to?(:path)
error_klass = Class.new do
def path
fixtures_dir.join("this_project_extra_def.rb.txt")
end

require "syntax_suggest/core_ext"
def detailed_message(**kwargs)
"error"
end
end
error_klass.prepend(SyntaxSuggest.module_for_detailed_message)
error = error_klass.new

expect(error.detailed_message(highlight: true)).to include(SyntaxSuggest::DisplayCodeWithLineNumbers::TERMINAL_HIGHLIGHT)
expect(error.detailed_message(highlight: false)).to_not include(SyntaxSuggest::DisplayCodeWithLineNumbers::TERMINAL_HIGHLIGHT)
Expand All @@ -78,11 +87,20 @@ def fake_error.message
it "can be disabled via falsey kwarg" do
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

error = SyntaxError.new("#{fixtures_dir.join("this_project_extra_def.rb.txt")}:1 ")
core_ext_file = lib_dir.join("syntax_suggest").join("core_ext.rb")
require_relative core_ext_file

skip if error.respond_to?(:path)
error_klass = Class.new do
def path
fixtures_dir.join("this_project_extra_def.rb.txt")
end

require "syntax_suggest/core_ext"
def detailed_message(**kwargs)
"error"
end
end
error_klass.prepend(SyntaxSuggest.module_for_detailed_message)
error = error_klass.new

expect(error.detailed_message(syntax_suggest: true)).to_not eq(error.detailed_message(syntax_suggest: false))
end
Expand Down

0 comments on commit 0677bbe

Please sign in to comment.