Skip to content

Add support for literal tuples #826

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
7 changes: 4 additions & 3 deletions lib/solargraph/source/chain/array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ def resolve api_map, name_pin, locals
child_types = @children.map do |child|
child.infer(api_map, name_pin, locals)
end

type = if child_types.uniq.length == 1 && child_types.first.defined?
type = if child_types.length == 0 || child_types.any?(&:undefined?)
ComplexType::UniqueType.new('Array', rooted: true)
elsif child_types.uniq.length == 1 && child_types.first.defined?
ComplexType::UniqueType.new('Array', [], child_types.uniq, rooted: true, parameters_type: :list)
else
ComplexType::UniqueType.new('Array', rooted: true)
ComplexType::UniqueType.new('Array', [], child_types, rooted: true, parameters_type: :fixed)
end
[Pin::ProxyType.anonymous(type)]
end
Expand Down
4 changes: 2 additions & 2 deletions spec/source/source_chainer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ class Inner2
expect(type.tag).to eq('Array<String>')
end

it 'infers general array type when types in literal differ' do
it 'infers tuple type when types in literal differ' do
source = Solargraph::Source.load_string(%(
['a', 123]
), 'test.rb')
Expand All @@ -292,7 +292,7 @@ class Inner2

chain = Solargraph::Source::SourceChainer.chain(source, Solargraph::Position.new(1, 16))
type = chain.infer(api_map, Solargraph::Pin::ROOT_PIN, api_map.source_map('test.rb').locals)
expect(type.tag).to eq('Array')
expect(type.tag).to eq('Array(String, Integer)')
end

it 'infers specific array type when types in literal identical' do
Expand Down
48 changes: 35 additions & 13 deletions spec/source_map/clip_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1950,7 +1950,7 @@ def foo
xit 'identifies tuple types' do
source = Solargraph::Source.load_string(%(
# @type [Array(String, Integer)]
a = 123
a = foo
b = a[0]
b
c = a[1]
Expand Down Expand Up @@ -1987,7 +1987,7 @@ def foo
expect(type.rooted_tags).to eq('::Array<::Integer>')
end

xit 'infers tuple types from diverse literal arrays' do
it 'infers tuple types from diverse literal arrays' do
source = Solargraph::Source.load_string(%(
a = [123, 'foo']
a
Expand All @@ -1998,6 +1998,39 @@ def foo
expect(type.to_s).to eq('Array(Integer, String)')
end

it 'infers shallow literal diverse arrays into tuples' do
source = Solargraph::Source.load_string(%(
h = ['foo', 1]
h
), 'test.rb')
api_map = Solargraph::ApiMap.new.map(source)
clip = api_map.clip_at('test.rb', [2, 6])
type = clip.infer
expect(type.to_s).to eq('Array(String, Integer)')
end

it 'infers array of identical diverse arrays into tuples' do
source = Solargraph::Source.load_string(%(
h = [['foo', 1], ['bar', 2]]
h
), 'test.rb')
api_map = Solargraph::ApiMap.new.map(source)
clip = api_map.clip_at('test.rb', [2, 6])
type = clip.infer
expect(type.to_s).to eq('Array<Array(String, Integer)>')
end

it 'infers literal diverse array of diverse arrays into tuple of tuples' do
source = Solargraph::Source.load_string(%(
h = [['foo', 1], ['bar', :baz]]
h
), 'test.rb')
api_map = Solargraph::ApiMap.new.map(source)
clip = api_map.clip_at('test.rb', [2, 6])
type = clip.infer
expect(type.to_s).to eq('Array(Array(String, Integer), Array(String, Symbol))')
end

it 'resolves block parameter types from Hash#each' do
source = Solargraph::Source.load_string(%(
# @type [Hash{String => Integer}]
Expand Down Expand Up @@ -2044,17 +2077,6 @@ def foo
expect(type.to_s).to eq('Integer')
end

xit 'infers literal heterogeneous arrays into tuples' do
source = Solargraph::Source.load_string(%(
h = [['foo', 1], ['bar', 2]]
h
), 'test.rb')
api_map = Solargraph::ApiMap.new.map(source)
clip = api_map.clip_at('test.rb', [2, 6])
type = clip.infer
expect(type.to_s).to eq('Array<Array(String, Integer)>')
end

it 'excludes Kernel singleton methods from chained methods' do
source = Solargraph::Source.load_string('[].put', 'test.rb')
api_map = Solargraph::ApiMap.new.map(source)
Expand Down