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

Handling goto-definition of .new method #375

Merged
merged 1 commit into from
Apr 21, 2021
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
16 changes: 16 additions & 0 deletions lib/steep/services/goto_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@ def method_locations(name, in_ruby:, in_rbs:, locations:)
type_check.source_files.each do |path, source|
if typing = source.typing
entry = typing.source_index.entry(method: name)

if entry.definitions.empty?
if name.is_a?(SingletonMethodName) && name.method_name == :new
initialize = InstanceMethodName.new(method_name: :initialize, type_name: name.type_name)
entry = typing.source_index.entry(method: initialize)
end
end

entry.definitions.each do |node|
case node.type
when :def
Expand All @@ -272,6 +280,14 @@ def method_locations(name, in_ruby:, in_rbs:, locations:)
index = signature.latest_rbs_index

entry = index.entry(method_name: name)

if entry.declarations.empty?
if name.is_a?(SingletonMethodName) && name.method_name == :new
initialize = InstanceMethodName.new(method_name: :initialize, type_name: name.type_name)
entry = index.entry(method_name: initialize)
end
end

entry.declarations.each do |decl|
case decl
when RBS::AST::Members::MethodDefinition
Expand Down
99 changes: 99 additions & 0 deletions test/goto_service_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -531,4 +531,103 @@ class Customer
end
end
end

def test_new_method_definition
type_check = type_check_service do |changes|
changes[Pathname("sig/a.rbs")] = [ContentChange.string(<<RBS)]
class Foo
def initialize: (String) -> void
end

class Bar
end

class Baz
def self.new: (Integer) -> Baz
end
RBS

changes[Pathname("lib/test.rb")] = [ContentChange.string(<<RBS)]
Foo.new("foo")
Bar.new()
Baz.new(123)
RBS
end

service = Services::GotoService.new(type_check: type_check)

service.definition(path: dir + "lib/test.rb", line: 1, column: 6).tap do |locs|
assert_any!(locs) do |loc|
assert_instance_of RBS::Location, loc
assert_equal "initialize", loc.source
assert_equal 2, loc.start_line
assert_equal Pathname("sig/a.rbs"), loc.buffer.name
end
end

service.definition(path: dir + "lib/test.rb", line: 2, column: 6).tap do |locs|
assert_any!(locs) do |loc|
assert_instance_of RBS::Location, loc
assert_equal "initialize", loc.source
assert_equal Pathname("basic_object.rbs"), Pathname(loc.buffer.name).basename
end
end

service.definition(path: dir + "lib/test.rb", line: 3, column: 6).tap do |locs|
assert_any!(locs) do |loc|
assert_instance_of RBS::Location, loc
assert_equal "new", loc.source
assert_equal 9, loc.start_line
assert_equal Pathname("sig/a.rbs"), loc.buffer.name
end
end
end

def test_new_method_impl
type_check = type_check_service do |changes|
changes[Pathname("sig/a.rbs")] = [ContentChange.string(<<RBS)]
class Foo
def initialize: (String) -> void
end

class Baz
def self.new: (Integer) -> Baz
end
RBS

changes[Pathname("lib/test.rb")] = [ContentChange.string(<<RBS)]
class Foo
def initialize(string)
end
end

class Baz
def self.new(i)
super()
end
end

Foo.new("foo")
Baz.new(123)
RBS
end

service = Services::GotoService.new(type_check: type_check)

service.implementation(path: dir + "lib/test.rb", line: 12, column: 6).tap do |locs|
assert_any!(locs, size: 1) do |loc|
assert_instance_of Parser::Source::Range, loc
assert_equal "initialize", loc.source
assert_equal 2, loc.line
end
end

service.implementation(path: dir + "lib/test.rb", line: 13, column: 6).tap do |locs|
assert_any!(locs, size: 1) do |loc|
assert_instance_of Parser::Source::Range, loc
assert_equal "new", loc.source
assert_equal 7, loc.line
end
end
end
end