Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support detailed_message for NoTypeError, InheritModuleError, NoSelfTypeFoundError and NoMixinFoundError #1280

Merged
merged 5 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion lib/rbs/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ class DefinitionError < BaseError; end

module DetailedMessageable
def detailed_message(highlight: false, **)
msg = super

# Support only one line
return msg unless location.start_line == location.end_line

indent = " " * location.start_column
marker = "^" * (location.end_column - location.start_column)

io = StringIO.new
io.puts super
io.puts msg
io.puts
io.print "\e[1m" if highlight
io.puts " #{location.buffer.lines[location.end_line - 1]}"
Expand Down Expand Up @@ -126,6 +131,8 @@ def self.check!(self_ancestor, ancestors:, location:)
end

class NoTypeFoundError < BaseError
include DetailedMessageable

attr_reader :type_name
attr_reader :location

Expand Down Expand Up @@ -163,6 +170,8 @@ def self.check!(type_name, env:, location:)
end

class InheritModuleError < DefinitionError
include DetailedMessageable

attr_reader :super_decl

def initialize(super_decl)
Expand All @@ -171,6 +180,10 @@ def initialize(super_decl)
super "#{Location.to_string(super_decl.location)}: Cannot inherit a module: #{super_decl.name}"
end

def location
@super_decl.location
end

def self.check!(super_decl, env:)
return if env.class_decl?(super_decl.name) || env.class_alias?(super_decl.name)

Expand All @@ -179,6 +192,8 @@ def self.check!(super_decl, env:)
end

class NoSelfTypeFoundError < DefinitionError
include DetailedMessageable

attr_reader :type_name
attr_reader :location

Expand All @@ -197,6 +212,8 @@ def self.check!(self_type, env:)
end

class NoMixinFoundError < DefinitionError
include DetailedMessageable

attr_reader :type_name
attr_reader :member

Expand Down
73 changes: 73 additions & 0 deletions test/rbs/errors_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,77 @@ def test_parse_method_type_with_parsing_error_detailed_message
DETAILED_MESSAGE
end
end

def test_no_type_found_error_with_detailed_message
omit "Exception#detailed_message does not supported" unless Exception.method_defined?(:detailed_message)

_, _, decls = RBS::Parser.parse_signature(<<~SIGNATURE)
class NotFound
end
SIGNATURE
type = decls.first
error = RBS::NoTypeFoundError.new(type_name: type.name, location: type.location)
assert_equal "#{error.message} (RBS::NoTypeFoundError)", error.detailed_message

_, _, decls = RBS::Parser.parse_signature("type foo = NotFound")
type = decls.first.type
error = RBS::NoTypeFoundError.new(type_name: type.name, location: type.location)
assert_equal <<~DETAILED_MESSAGE, error.detailed_message
#{error.message} (RBS::NoTypeFoundError)

type foo = NotFound
^^^^^^^^
DETAILED_MESSAGE
end

def test_inherit_module_error_with_detailed_message
omit "Exception#detailed_message does not supported" unless Exception.method_defined?(:detailed_message)

_, _, decls = RBS::Parser.parse_signature(<<~SIGNATURE)
class Foo < Kernel
end
SIGNATURE
error = RBS::InheritModuleError.new(decls.first.super_class)
assert_equal <<~DETAILED_MESSAGE, error.detailed_message
#{error.message} (RBS::InheritModuleError)

class Foo < Kernel
^^^^^^
DETAILED_MESSAGE
end

def test_no_self_type_found_error_with_detailed_message
omit "Exception#detailed_message does not supported" unless Exception.method_defined?(:detailed_message)

_, _, decls = RBS::Parser.parse_signature(<<~SIGNATURE)
module Foo : NotFound
end
SIGNATURE
self_type_decl = decls.first.self_types.first
error = RBS::NoSelfTypeFoundError.new(type_name: self_type_decl.name, location: self_type_decl.location)
assert_equal <<~DETAILED_MESSAGE, error.detailed_message
#{error.message} (RBS::NoSelfTypeFoundError)

module Foo : NotFound
^^^^^^^^
DETAILED_MESSAGE
end

def test_no_mixin_found_error_with_detailed_message
omit "Exception#detailed_message does not supported" unless Exception.method_defined?(:detailed_message)

_, _, decls = RBS::Parser.parse_signature(<<~SIGNATURE)
module Bar
include NotFound
end
SIGNATURE
member_decl = decls.first.members.first
error = RBS::NoMixinFoundError.new(type_name: member_decl.name, member: member_decl)
assert_equal <<~DETAILED_MESSAGE, error.detailed_message
#{error.message} (RBS::NoMixinFoundError)

include NotFound
^^^^^^^^^^^^^^^^
DETAILED_MESSAGE
end
end