Skip to content

Commit c1566ce

Browse files
committed
Add TypeCompletion test
1 parent d40f9e2 commit c1566ce

File tree

6 files changed

+971
-2
lines changed

6 files changed

+971
-2
lines changed

Gemfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,7 @@ gem "rake"
1717
gem "test-unit"
1818
gem "test-unit-ruby-core"
1919
gem "debug", github: "ruby/debug"
20+
if RUBY_VERSION >= "3.0.0"
21+
gem "rbs"
22+
gem "prism"
23+
end

Rakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ Rake::TestTask.new(:test) do |t|
55
t.libs << "test" << "test/lib"
66
t.libs << "lib"
77
t.ruby_opts << "-rhelper"
8-
t.test_files = FileList["test/irb/test_*.rb"]
8+
t.test_files = FileList["test/irb/test_*.rb", "test/irb/type_completion/test_*.rb"]
99
end
1010

1111
# To make sure they have been correctly setup for Ruby CI.
1212
desc "Run each irb test file in isolation."
1313
task :test_in_isolation do
1414
failed = false
1515

16-
FileList["test/irb/test_*.rb"].each do |test_file|
16+
FileList["test/irb/test_*.rb", "test/irb/type_completion/test_*.rb"].each do |test_file|
1717
ENV["TEST"] = test_file
1818
begin
1919
Rake::Task["test"].execute
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# frozen_string_literal: true
2+
3+
return unless RUBY_VERSION >= '3.0.0'
4+
return if RUBY_ENGINE == 'truffleruby' # needs endless method definition
5+
6+
require 'irb/type_completion/scope'
7+
require 'irb/type_completion/types'
8+
require_relative '../helper'
9+
10+
module TestIRB
11+
class TypeCompletionScopeTest < TestCase
12+
A, B, C, D, E, F, G, H, I, J, K = ('A'..'K').map do |name|
13+
klass = Class.new
14+
klass.define_singleton_method(:inspect) { name }
15+
IRB::TypeCompletion::Types::InstanceType.new(klass)
16+
end
17+
18+
def assert_type(expected_types, type)
19+
assert_equal [*expected_types].map(&:klass).to_set, type.types.map(&:klass).to_set
20+
end
21+
22+
def table(*local_variable_names)
23+
local_variable_names.to_h { [_1, IRB::TypeCompletion::Types::NIL] }
24+
end
25+
26+
def base_scope
27+
IRB::TypeCompletion::BaseScope.new(binding, Object.new, [])
28+
end
29+
30+
def test_lvar
31+
scope = IRB::TypeCompletion::Scope.new base_scope, table('a')
32+
scope['a'] = A
33+
assert_equal A, scope['a']
34+
end
35+
36+
def test_conditional
37+
scope = IRB::TypeCompletion::Scope.new base_scope, table('a')
38+
scope.conditional do |sub_scope|
39+
sub_scope['a'] = A
40+
end
41+
assert_type [A, IRB::TypeCompletion::Types::NIL], scope['a']
42+
end
43+
44+
def test_branch
45+
scope = IRB::TypeCompletion::Scope.new base_scope, table('a', 'b', 'c', 'd')
46+
scope['c'] = A
47+
scope['d'] = B
48+
scope.run_branches(
49+
-> { _1['a'] = _1['c'] = _1['d'] = C },
50+
-> { _1['a'] = _1['b'] = _1['d'] = D },
51+
-> { _1['a'] = _1['b'] = _1['d'] = E },
52+
-> { _1['a'] = _1['b'] = _1['c'] = F; _1.terminate }
53+
)
54+
assert_type [C, D, E], scope['a']
55+
assert_type [IRB::TypeCompletion::Types::NIL, D, E], scope['b']
56+
assert_type [A, C], scope['c']
57+
assert_type [C, D, E], scope['d']
58+
end
59+
60+
def test_scope_local_variables
61+
scope1 = IRB::TypeCompletion::Scope.new base_scope, table('a', 'b')
62+
scope2 = IRB::TypeCompletion::Scope.new scope1, table('b', 'c'), trace_lvar: false
63+
scope3 = IRB::TypeCompletion::Scope.new scope2, table('c', 'd')
64+
scope4 = IRB::TypeCompletion::Scope.new scope2, table('d', 'e')
65+
assert_empty base_scope.local_variables
66+
assert_equal %w[a b], scope1.local_variables.sort
67+
assert_equal %w[b c], scope2.local_variables.sort
68+
assert_equal %w[b c d], scope3.local_variables.sort
69+
assert_equal %w[b c d e], scope4.local_variables.sort
70+
end
71+
72+
def test_nested_scope
73+
scope = IRB::TypeCompletion::Scope.new base_scope, table('a', 'b', 'c')
74+
scope['a'] = A
75+
scope['b'] = A
76+
scope['c'] = A
77+
sub_scope = IRB::TypeCompletion::Scope.new scope, { 'c' => B }
78+
assert_type A, sub_scope['a']
79+
80+
assert_type A, sub_scope['b']
81+
assert_type B, sub_scope['c']
82+
sub_scope['a'] = C
83+
sub_scope.conditional { _1['b'] = C }
84+
sub_scope['c'] = C
85+
assert_type C, sub_scope['a']
86+
assert_type [A, C], sub_scope['b']
87+
assert_type C, sub_scope['c']
88+
scope.update sub_scope
89+
assert_type C, scope['a']
90+
assert_type [A, C], scope['b']
91+
assert_type A, scope['c']
92+
end
93+
94+
def test_break
95+
scope = IRB::TypeCompletion::Scope.new base_scope, table('a')
96+
scope['a'] = A
97+
breakable_scope = IRB::TypeCompletion::Scope.new scope, { IRB::TypeCompletion::Scope::BREAK_RESULT => nil }
98+
breakable_scope.conditional do |sub|
99+
sub['a'] = B
100+
assert_type [B], sub['a']
101+
sub.terminate_with IRB::TypeCompletion::Scope::BREAK_RESULT, C
102+
sub['a'] = C
103+
assert_type [C], sub['a']
104+
end
105+
assert_type [A], breakable_scope['a']
106+
breakable_scope[IRB::TypeCompletion::Scope::BREAK_RESULT] = D
107+
breakable_scope.merge_jumps
108+
assert_type [C, D], breakable_scope[IRB::TypeCompletion::Scope::BREAK_RESULT]
109+
scope.update breakable_scope
110+
assert_type [A, B], scope['a']
111+
end
112+
end
113+
end

0 commit comments

Comments
 (0)