Skip to content

Commit e88b2ce

Browse files
authored
Merge pull request #4 from ruby/prism_0_19_0
Require prism >= 0.19.0
2 parents d9c100f + a8fd389 commit e88b2ce

File tree

6 files changed

+51
-51
lines changed

6 files changed

+51
-51
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ jobs:
4444
strategy:
4545
fail-fast: false
4646
matrix:
47-
prism: ['0.18.0']
47+
prism: ['latest', '0.19.0']
4848
env:
4949
GEMFILE_PRISM_VERSION: ${{matrix.prism}}
5050
steps:

lib/repl_type_completor.rb

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,15 @@ def analyze_code(code, binding = Object::TOPLEVEL_BINDING)
6868
calculate_type_scope = ->(node) { TypeAnalyzer.calculate_target_type_scope binding, [*parents, target_node], node }
6969

7070
case target_node
71-
when Prism::StringNode, Prism::InterpolatedStringNode
71+
when Prism::StringNode
72+
return unless target_node.closing&.empty?
73+
7274
call_node, args_node = parents.last(2)
7375
return unless call_node.is_a?(Prism::CallNode) && call_node.receiver.nil?
7476
return unless args_node.is_a?(Prism::ArgumentsNode) && args_node.arguments.size == 1
7577

76-
content = code.byteslice(target_node.opening_loc.end_offset..)
77-
case call_node.name
78-
when :require
79-
[:require, content]
80-
when :require_relative
81-
[:require_relative, content]
78+
if call_node.name == :require || call_node.name == :require_relative
79+
[call_node.name, target_node.content]
8280
end
8381
when Prism::SymbolNode
8482
return unless !target_node.closing || target_node.empty?
@@ -90,8 +88,8 @@ def analyze_code(code, binding = Object::TOPLEVEL_BINDING)
9088
else
9189
[:symbol, name] unless name.empty?
9290
end
93-
when Prism::CallNode
94-
return if target_node.opening
91+
when Prism::CallNode, Prism::CallTargetNode
92+
return if target_node.is_a?(Prism::CallNode) && target_node.opening
9593

9694
name = target_node.message.to_s
9795
return [:lvar_or_method, name, calculate_scope.call] if target_node.receiver.nil?
@@ -127,14 +125,8 @@ def analyze_code(code, binding = Object::TOPLEVEL_BINDING)
127125
end
128126

129127
def find_target(node, position)
130-
case node
131-
when Prism::StringNode
132-
# Unclosed quoted string has empty content and empty closing
133-
return [node] if node.opening && node.closing&.empty?
134-
when Prism::InterpolatedStringNode
135-
# Unclosed double quoted string is InterpolatedStringNode with empty parts
136-
return [node] if node.parts.empty? && node.opening && node.closing&.empty?
137-
end
128+
# Skip because NumberedParametersNode#location gives location of whole block
129+
return if node.is_a? Prism::NumberedParametersNode
138130

139131
node.compact_child_nodes.each do |n|
140132
match = find_target(n, position)

lib/repl_type_completor/type_analyzer.rb

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,6 @@ def evaluate_reference_read(node, scope)
231231

232232

233233
def evaluate_call_node(node, scope)
234-
is_field_assign = node.name.match?(/[^<>=!\]]=\z/) || (node.name == :[]= && !node.call_operator)
235234
receiver_type = node.receiver ? evaluate(node.receiver, scope) : scope.self_type
236235
evaluate_method = lambda do |scope|
237236
args_types, kwargs_types, block_sym_node, has_block = evaluate_call_node_arguments node, scope
@@ -254,16 +253,15 @@ def evaluate_call_node(node, scope)
254253
elsif node.block.is_a? Prism::BlockNode
255254
call_block_proc = ->(block_args, block_self_type) do
256255
scope.conditional do |s|
257-
numbered_parameters = node.block.locals.grep(/\A_[1-9]/).map(&:to_s)
258256
params_table = node.block.locals.to_h { [_1.to_s, Types::NIL] }
259257
table = { **params_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil }
260258
block_scope = Scope.new s, table, self_type: block_self_type, trace_ivar: !block_self_type
261259
# TODO kwargs
262-
if node.block.parameters&.parameters
263-
# node.block.parameters is Prism::BlockParametersNode
260+
case node.block.parameters
261+
when Prism::NumberedParametersNode
262+
assign_numbered_parameters node.block.parameters.maximum, block_scope, block_args, {}
263+
when Prism::BlockParametersNode
264264
assign_parameters node.block.parameters.parameters, block_scope, block_args, {}
265-
elsif !numbered_parameters.empty?
266-
assign_numbered_parameters numbered_parameters, block_scope, block_args, {}
267265
end
268266
result = node.block.body ? evaluate(node.block.body, block_scope) : Types::NIL
269267
block_scope.merge_jumps
@@ -281,7 +279,7 @@ def evaluate_call_node(node, scope)
281279
call_block_proc = ->(_block_args, _self_type) { Types::OBJECT }
282280
end
283281
result = method_call receiver_type, node.name, args_types, kwargs_types, call_block_proc, scope
284-
if is_field_assign
282+
if node.attribute_write?
285283
args_types.last || Types::NIL
286284
else
287285
result
@@ -583,8 +581,8 @@ def evaluate_rescue_node(node, scope)
583581
case node.reference
584582
when Prism::LocalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::ConstantTargetNode
585583
s[node.reference.name.to_s] = error_type
586-
when Prism::CallNode
587-
evaluate node.reference, s
584+
when Prism::CallTargetNode, Prism::IndexTargetNode
585+
evaluate_multi_write_receiver node.reference, s, nil
588586
end
589587
end
590588
node.statements ? evaluate(node.statements, s) : Types::NIL
@@ -904,7 +902,6 @@ def assign_parameters(node, scope, args, kwargs)
904902
args = sized_splat(args.first, :to_ary, size) if size >= 2 && args.size == 1
905903
reqs = args.shift node.requireds.size
906904
if node.rest
907-
# node.rest is Prism::RestParameterNode
908905
posts = []
909906
opts = args.shift node.optionals.size
910907
rest = args
@@ -925,8 +922,8 @@ def assign_parameters(node, scope, args, kwargs)
925922
node.posts.zip posts do |n, v|
926923
assign_required_parameter n, v, scope
927924
end
928-
if node.rest&.name
929-
# node.rest is Prism::RestParameterNode
925+
# Prism::ImplicitRestNode (tap{|a,|}) does not have a name
926+
if node.rest.is_a?(Prism::RestParameterNode) && node.rest.name
930927
scope[node.rest.name.to_s] = Types.array_of(*rest)
931928
end
932929
node.keywords.each do |n|
@@ -946,16 +943,13 @@ def assign_parameters(node, scope, args, kwargs)
946943
end
947944
end
948945

949-
def assign_numbered_parameters(numbered_parameters, scope, args, _kwargs)
950-
return if numbered_parameters.empty?
951-
max_num = numbered_parameters.map { _1[1].to_i }.max
952-
if max_num == 1
946+
def assign_numbered_parameters(maximum, scope, args, _kwargs)
947+
if maximum == 1
953948
scope['_1'] = args.first || Types::NIL
954949
else
955-
args = sized_splat(args.first, :to_ary, max_num) if args.size == 1
956-
numbered_parameters.each do |name|
957-
index = name[1].to_i - 1
958-
scope[name] = args[index] || Types::NIL
950+
args = sized_splat(args.first, :to_ary, maximum) if args.size == 1
951+
maximum.times do |index|
952+
scope["_#{index + 1}"] = args[index] || Types::NIL
959953
end
960954
end
961955
end
@@ -1038,16 +1032,15 @@ def evaluate_write(node, value, scope, evaluated_receivers)
10381032
case node
10391033
when Prism::MultiTargetNode
10401034
evaluate_multi_write node, value, scope, evaluated_receivers
1041-
when Prism::CallNode
1042-
evaluated_receivers&.[](node.receiver) || evaluate(node.receiver, scope) if node.receiver
1035+
when Prism::CallTargetNode, Prism::IndexTargetNode
1036+
evaluated_receivers&.[](node.receiver) || evaluate_multi_write_receiver(node, scope, nil)
10431037
when Prism::SplatNode
10441038
evaluate_write node.expression, Types.array_of(value), scope, evaluated_receivers if node.expression
10451039
when Prism::LocalVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::ConstantTargetNode
10461040
scope[node.name.to_s] = value
10471041
when Prism::ConstantPathTargetNode
10481042
receiver = evaluated_receivers&.[](node.parent) || evaluate(node.parent, scope) if node.parent
10491043
const_path_write receiver, node.child.name.to_s, value, scope
1050-
value
10511044
end
10521045
end
10531046

@@ -1070,20 +1063,24 @@ def evaluate_multi_write_receiver(node, scope, evaluated_receivers)
10701063
when Prism::MultiWriteNode, Prism::MultiTargetNode
10711064
targets = [*node.lefts, *node.rest, *node.rights]
10721065
targets.each { evaluate_multi_write_receiver _1, scope, evaluated_receivers }
1073-
when Prism::CallNode
1074-
if node.receiver
1075-
receiver = evaluate(node.receiver, scope)
1076-
evaluated_receivers[node.receiver] = receiver if evaluated_receivers
1077-
end
1066+
when Prism::CallTargetNode, Prism::CallNode
1067+
receiver = evaluate(node.receiver, scope)
1068+
evaluated_receivers[node.receiver] = receiver if evaluated_receivers
1069+
receiver
1070+
when Prism::IndexTargetNode
1071+
receiver = evaluate(node.receiver, scope)
1072+
evaluated_receivers[node.receiver] = receiver if evaluated_receivers
10781073
if node.arguments
10791074
node.arguments.arguments&.each do |arg|
10801075
if arg.is_a? Prism::SplatNode
1081-
evaluate arg.expression, scope
1076+
evaluate arg.expression, scope if arg.expression
10821077
else
10831078
evaluate arg, scope
10841079
end
10851080
end
10861081
end
1082+
evaluate node.block.expression, scope if node.block&.expression
1083+
receiver
10871084
when Prism::SplatNode
10881085
evaluate_multi_write_receiver node.expression, scope, evaluated_receivers if node.expression
10891086
end

repl_type_completor.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,6 @@ Gem::Specification.new do |spec|
2929
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
3030
spec.require_paths = ["lib"]
3131

32-
spec.add_dependency "prism", ">= 0.18.0", "< 0.19.0"
32+
spec.add_dependency "prism", ">= 0.19.0", "< 0.20.0"
3333
spec.add_dependency "rbs", ">= 2.7.0", "< 4.0.0"
3434
end

test/repl_type_completor/test_repl_type_completor.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,18 @@ def assert_doc_namespace(code, namespace, binding: empty_binding)
2929
def test_require
3030
assert_completion("require '", include: 'set')
3131
assert_completion("require 's", include: 'et')
32+
assert_completion('require "', include: 'set')
33+
assert_completion('require "s', include: 'et')
3234
assert_completion("require_relative 'test_", filename: __FILE__, include: 'repl_type_completor')
3335
assert_completion("require_relative '../repl_", filename: __FILE__, include: 'type_completor/test_repl_type_completor')
3436
Dir.chdir File.join(__dir__, '..') do
3537
assert_completion("require_relative 'repl_", filename: nil, include: 'type_completor/test_repl_type_completor')
3638
assert_completion("require_relative 'repl_", filename: '(irb)', include: 'type_completor/test_repl_type_completor')
3739
end
3840

39-
# Incomplete double quote string is InterpolatedStringNode
40-
assert_completion('require "', include: 'set')
41-
assert_completion('require "s', include: 'et')
41+
# Should not complete terminated string
42+
assert_nil ReplTypeCompletor.analyze('require "s"', binding: empty_binding)
43+
assert_nil ReplTypeCompletor.analyze('require ?s', binding: empty_binding)
4244
end
4345

4446
def test_method_block_sym

test/repl_type_completor/test_type_analyze.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,15 @@ def test_massign
333333
assert_call('a, ((b=1).c, d) = 1; b.', include: Integer)
334334
assert_call('a, b[c=1] = 1; c.', include: Integer)
335335
assert_call('a, b[*(c=1)] = 1; c.', include: Integer)
336+
assert_call('a, b[**(c=1)] = 1; c.', include: Integer)
337+
assert_call('a, b[&(c=1)] = 1; c.', include: Integer)
338+
assert_call('a, b[] = 1; a.', include: Integer)
339+
assert_call('def f(*); a, b[*] = 1; a.', include: Integer)
340+
assert_call('def f(&); a, b[&] = 1; a.', include: Integer)
341+
assert_call('def f(**); a, b[**] = 1; a.', include: Integer)
336342
# incomplete massign
337343
assert_analyze_type('a,b', :lvar_or_method, 'b')
344+
assert_call('(a=1).b, a.a', include: Integer)
338345
assert_call('(a=1).b, a.', include: Integer)
339346
assert_call('a=1; *a.', include: Integer)
340347
end
@@ -575,6 +582,7 @@ def test_for
575582
assert_call('for *,(*) in [1,2,3]; 1.', include: Integer)
576583
assert_call('for *i in [1,2,3]; i.sample.', include: Integer)
577584
assert_call('for (a=1).b in [1,2,3]; a.', include: Integer)
585+
assert_call('for a[b=1] in [1,2,3]; b.', include: Integer)
578586
assert_call('for Array::B in [1,2,3]; Array::B.', include: Integer)
579587
assert_call('for A in [1,2,3]; A.', include: Integer)
580588
assert_call('for $a in [1,2,3]; $a.', include: Integer)
@@ -673,6 +681,7 @@ def test_call_parameter
673681

674682
def test_block_args
675683
assert_call('[1,2,3].tap{|a| a.', include: Array)
684+
assert_call('[1,2,3].tap{|a,| a.', include: Integer)
676685
assert_call('[1,2,3].tap{|a,b| a.', include: Integer)
677686
assert_call('[1,2,3].tap{|(a,b)| a.', include: Integer)
678687
assert_call('[1,2,3].tap{|a,*b| b.', include: Array)

0 commit comments

Comments
 (0)