Skip to content
Draft
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
8 changes: 4 additions & 4 deletions lib/solargraph/pin/method.rb
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,7 @@ def typify api_map
type = see_reference(api_map) || typify_from_super(api_map)
logger.debug { "Method#typify(self=#{self}) - type=#{type&.rooted_tags.inspect}" }
unless type.nil?
# @sg-ignore Need to add nil check here
qualified = type.qualify(api_map, *closure.gates)
qualified = type.qualify(api_map, *gates)
logger.debug { "Method#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
return qualified
end
Expand Down Expand Up @@ -611,13 +610,14 @@ def method_namespace
end

# @param api_map [ApiMap]
# @return [ComplexType, nil]
# @return [ComplexType, ComplexType::UniqueType, nil]
def typify_from_super api_map
stack = rest_of_stack api_map
return nil if stack.empty?
stack.each do |pin|
# @sg-ignore Need to add nil check here
return pin.return_type unless pin.return_type.undefined?
next if pin.return_type.undefined?
return pin.typify(api_map)
end
nil
end
Expand Down
12 changes: 9 additions & 3 deletions lib/solargraph/source/chain/call.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,15 @@ def resolve api_map, name_pin, locals
binder = binder.without_nil if nullable?
# @sg-ignore Need to handle duck-typed method calls on union types
pin_groups = binder.each_unique_type.map do |context|
ns_tag = context.namespace == '' ? '' : context.namespace_type.tag
stack = api_map.get_method_stack(ns_tag, word, scope: context.scope)
[stack.first].compact
if context.duck_type? && context.name[1..] == word
# explicit: false skips arity checking; the duck type
# only tells us the method exists, not its signature
[Pin::DuckMethod.new(name: word, source: :chain, explicit: false)]
else
ns_tag = context.namespace == '' ? '' : context.namespace_type.tag
stack = api_map.get_method_stack(ns_tag, word, scope: context.scope)
[stack.first].compact
end
end
pin_groups = [] if !api_map.loose_unions && pin_groups.any?(&:empty?)
pins = pin_groups.flatten.uniq(&:path)
Expand Down
13 changes: 13 additions & 0 deletions spec/type_checker/levels/alpha_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,19 @@ def bing
expect(checker.problems.map(&:message)).to eq([])
end

it 'resolves calls to a duck type param\'s own declared method' do
checker = type_checker(%(
class Foo
# @param baz [#read_body]
# @return [void]
def bar(baz)
baz.read_body
end
end
))
expect(checker.problems).to be_empty
end

it 'resolves self correctly in arguments (second case)' do
checker = type_checker(%(
class Blah
Expand Down
Loading