Skip to content

Commit 6c703f8

Browse files
committed
Update for StringNode fix and NumberedParametersNode
1 parent d9c100f commit 6c703f8

3 files changed

Lines changed: 21 additions & 28 deletions

File tree

lib/repl_type_completor.rb

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,18 @@ 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..)
7778
case call_node.name
7879
when :require
79-
[:require, content]
80+
[:require, target_node.content]
8081
when :require_relative
81-
[:require_relative, content]
82+
[:require_relative, target_node.content]
8283
end
8384
when Prism::SymbolNode
8485
return unless !target_node.closing || target_node.empty?
@@ -127,14 +128,8 @@ def analyze_code(code, binding = Object::TOPLEVEL_BINDING)
127128
end
128129

129130
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
131+
# Skip because NumberedParametersNode#location gives location of whole block
132+
return if node.is_a? Prism::NumberedParametersNode
138133

139134
node.compact_child_nodes.each do |n|
140135
match = find_target(n, position)

lib/repl_type_completor/type_analyzer.rb

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,15 @@ def evaluate_call_node(node, scope)
254254
elsif node.block.is_a? Prism::BlockNode
255255
call_block_proc = ->(block_args, block_self_type) do
256256
scope.conditional do |s|
257-
numbered_parameters = node.block.locals.grep(/\A_[1-9]/).map(&:to_s)
258257
params_table = node.block.locals.to_h { [_1.to_s, Types::NIL] }
259258
table = { **params_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil }
260259
block_scope = Scope.new s, table, self_type: block_self_type, trace_ivar: !block_self_type
261260
# TODO kwargs
262-
if node.block.parameters&.parameters
263-
# node.block.parameters is Prism::BlockParametersNode
261+
case node.block.parameters
262+
when Prism::NumberedParametersNode
263+
assign_numbered_parameters node.block.parameters.maximum, block_scope, block_args, {}
264+
when Prism::BlockParametersNode
264265
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, {}
267266
end
268267
result = node.block.body ? evaluate(node.block.body, block_scope) : Types::NIL
269268
block_scope.merge_jumps
@@ -946,16 +945,13 @@ def assign_parameters(node, scope, args, kwargs)
946945
end
947946
end
948947

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
948+
def assign_numbered_parameters(maximum, scope, args, _kwargs)
949+
if maximum == 1
953950
scope['_1'] = args.first || Types::NIL
954951
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
952+
args = sized_splat(args.first, :to_ary, maximum) if args.size == 1
953+
maximum.times do |index|
954+
scope["_#{index + 1}"] = args[index] || Types::NIL
959955
end
960956
end
961957
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

0 commit comments

Comments
 (0)