Skip to content

Commit

Permalink
TypeChecker validates aliased namespaces (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
castwide committed Nov 27, 2021
1 parent e50a6dc commit 949fa3c
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
11 changes: 10 additions & 1 deletion lib/solargraph/type_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def method_return_type_problems_for pin
if declared.undefined?
if pin.return_type.undefined? && rules.require_type_tags?
result.push Problem.new(pin.location, "Missing @return tag for #{pin.path}", pin: pin)
elsif pin.return_type.defined?
elsif pin.return_type.defined? && !resolved_constant?(pin)
result.push Problem.new(pin.location, "Unresolved return type #{pin.return_type} for #{pin.path}", pin: pin)
elsif rules.must_tag_or_infer? && pin.probe(api_map).undefined?
result.push Problem.new(pin.location, "Untyped method #{pin.path} could not be inferred")
Expand All @@ -111,6 +111,15 @@ def method_return_type_problems_for pin
result
end

# @todo This is not optimal. A better solution would probably be to mix
# namespace alias into types at the ApiMap level.
#
# @param pin [Pin::Base]
# @return [Boolean]
def resolved_constant? pin
api_map.get_constants('', pin.binder.tag).any? { |pin| pin.name == pin.return_type.namespace && ['Class', 'Module'].include?(pin.return_type.name) }
end

def virtual_pin? pin
pin.location && source_map.source.comment_at?(pin.location.range.ending)
end
Expand Down
17 changes: 15 additions & 2 deletions spec/type_checker/levels/normal_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ class Foo
def self.make(arg, *args, **kwargs)
new([1, 2], *args, **kwargs)
end
def initialize(timeframe, scope = nil, now: Time.now)
end
end
Expand All @@ -794,7 +794,7 @@ def initialize(timeframe, scope = nil, now: Time.now)
checker = type_checker(%(
def foo(arg1:, arg2:, arg3:, arg4: false)
end
foo(
arg1: val1,
arg2: val2,
Expand All @@ -803,5 +803,18 @@ def foo(arg1:, arg2:, arg3:, arg4: false)
))
expect(checker.problems).to be_empty
end

it 'validates constant aliases for namespaces' do
checker = type_checker(%(
class Foo; end
Bar = Foo
# @return [Bar]
def foo
Bar
end
))
expect(checker.problems).to be_empty
end
end
end

0 comments on commit 949fa3c

Please sign in to comment.