repl_type_completor 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/README.md +2 -4
- data/lib/repl_type_completor/result.rb +7 -1
- data/lib/repl_type_completor/type_analyzer.rb +26 -29
- data/lib/repl_type_completor/version.rb +1 -1
- data/lib/repl_type_completor.rb +12 -16
- metadata +16 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 201cdeb4768937fdb0d5639e6547ec9d6bcf57ac10ea7eb031059b41dea1ac00
|
4
|
+
data.tar.gz: d4dcf563c39cfe91cbb6a74a155b384eaf61048c09e809b473830075be73df18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 824b42a6ea9408e8be0f10605f25f8435593bf275d4d0e4d024e0c41ffa449212597f79e55a178bf55b70290a51b99baff426aa134eba3a597d3e251ac8f10c4
|
7
|
+
data.tar.gz: 243b30a33e778cf36d9573af2a1c9deb862960d312a49476d9745d0f64031e30b1d632042545ab471b062a49f1ff056e5734f3eeaf69e9eb568304ceb2637636
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -5,15 +5,13 @@ It uses RBS type information, performs static type analytics, uses dynamic runti
|
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
8
|
-
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_PRIOR_TO_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
9
|
-
|
10
8
|
Install the gem and add to the application's Gemfile by executing:
|
11
9
|
|
12
|
-
$ bundle add
|
10
|
+
$ bundle add repl_type_completor
|
13
11
|
|
14
12
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
15
13
|
|
16
|
-
$ gem install
|
14
|
+
$ gem install repl_type_completor
|
17
15
|
|
18
16
|
## Usage
|
19
17
|
|
@@ -4,7 +4,13 @@ require_relative 'require_paths'
|
|
4
4
|
|
5
5
|
module ReplTypeCompletor
|
6
6
|
class Result
|
7
|
-
|
7
|
+
OPERATOR_METHODS = %w[! != !~ % & * ** + +@ - -@ / < << <= <=> == === =~ > >= >> [] []= ^ ` | ~]
|
8
|
+
HIDDEN_METHODS = [
|
9
|
+
# defined by RBS, should be hidden
|
10
|
+
'Namespace', 'TypeName',
|
11
|
+
# operator methods does not need to be completed
|
12
|
+
*OPERATOR_METHODS
|
13
|
+
]
|
8
14
|
RESERVED_WORDS = %w[
|
9
15
|
__ENCODING__ __LINE__ __FILE__
|
10
16
|
BEGIN END
|
@@ -231,7 +231,6 @@ module ReplTypeCompletor
|
|
231
231
|
|
232
232
|
|
233
233
|
def evaluate_call_node(node, scope)
|
234
|
-
is_field_assign = node.name.match?(/[^<>=!\]]=\z/) || (node.name == :[]= && !node.call_operator)
|
235
234
|
receiver_type = node.receiver ? evaluate(node.receiver, scope) : scope.self_type
|
236
235
|
evaluate_method = lambda do |scope|
|
237
236
|
args_types, kwargs_types, block_sym_node, has_block = evaluate_call_node_arguments node, scope
|
@@ -254,16 +253,15 @@ module ReplTypeCompletor
|
|
254
253
|
elsif node.block.is_a? Prism::BlockNode
|
255
254
|
call_block_proc = ->(block_args, block_self_type) do
|
256
255
|
scope.conditional do |s|
|
257
|
-
numbered_parameters = node.block.locals.grep(/\A_[1-9]/).map(&:to_s)
|
258
256
|
params_table = node.block.locals.to_h { [_1.to_s, Types::NIL] }
|
259
257
|
table = { **params_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil }
|
260
258
|
block_scope = Scope.new s, table, self_type: block_self_type, trace_ivar: !block_self_type
|
261
259
|
# TODO kwargs
|
262
|
-
|
263
|
-
|
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
|
264
264
|
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, {}
|
267
265
|
end
|
268
266
|
result = node.block.body ? evaluate(node.block.body, block_scope) : Types::NIL
|
269
267
|
block_scope.merge_jumps
|
@@ -281,7 +279,7 @@ module ReplTypeCompletor
|
|
281
279
|
call_block_proc = ->(_block_args, _self_type) { Types::OBJECT }
|
282
280
|
end
|
283
281
|
result = method_call receiver_type, node.name, args_types, kwargs_types, call_block_proc, scope
|
284
|
-
if
|
282
|
+
if node.attribute_write?
|
285
283
|
args_types.last || Types::NIL
|
286
284
|
else
|
287
285
|
result
|
@@ -583,8 +581,8 @@ module ReplTypeCompletor
|
|
583
581
|
case node.reference
|
584
582
|
when Prism::LocalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::ConstantTargetNode
|
585
583
|
s[node.reference.name.to_s] = error_type
|
586
|
-
when Prism::
|
587
|
-
|
584
|
+
when Prism::CallTargetNode, Prism::IndexTargetNode
|
585
|
+
evaluate_multi_write_receiver node.reference, s, nil
|
588
586
|
end
|
589
587
|
end
|
590
588
|
node.statements ? evaluate(node.statements, s) : Types::NIL
|
@@ -904,7 +902,6 @@ module ReplTypeCompletor
|
|
904
902
|
args = sized_splat(args.first, :to_ary, size) if size >= 2 && args.size == 1
|
905
903
|
reqs = args.shift node.requireds.size
|
906
904
|
if node.rest
|
907
|
-
# node.rest is Prism::RestParameterNode
|
908
905
|
posts = []
|
909
906
|
opts = args.shift node.optionals.size
|
910
907
|
rest = args
|
@@ -925,8 +922,8 @@ module ReplTypeCompletor
|
|
925
922
|
node.posts.zip posts do |n, v|
|
926
923
|
assign_required_parameter n, v, scope
|
927
924
|
end
|
928
|
-
|
929
|
-
|
925
|
+
# Prism::ImplicitRestNode (tap{|a,|}) does not have a name
|
926
|
+
if node.rest.is_a?(Prism::RestParameterNode) && node.rest.name
|
930
927
|
scope[node.rest.name.to_s] = Types.array_of(*rest)
|
931
928
|
end
|
932
929
|
node.keywords.each do |n|
|
@@ -946,16 +943,13 @@ module ReplTypeCompletor
|
|
946
943
|
end
|
947
944
|
end
|
948
945
|
|
949
|
-
def assign_numbered_parameters(
|
950
|
-
|
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
|
953
948
|
scope['_1'] = args.first || Types::NIL
|
954
949
|
else
|
955
|
-
args = sized_splat(args.first, :to_ary,
|
956
|
-
|
957
|
-
index =
|
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
|
959
953
|
end
|
960
954
|
end
|
961
955
|
end
|
@@ -1038,8 +1032,8 @@ module ReplTypeCompletor
|
|
1038
1032
|
case node
|
1039
1033
|
when Prism::MultiTargetNode
|
1040
1034
|
evaluate_multi_write node, value, scope, evaluated_receivers
|
1041
|
-
when Prism::
|
1042
|
-
evaluated_receivers&.[](node.receiver) ||
|
1035
|
+
when Prism::CallTargetNode, Prism::IndexTargetNode
|
1036
|
+
evaluated_receivers&.[](node.receiver) || evaluate_multi_write_receiver(node, scope, nil)
|
1043
1037
|
when Prism::SplatNode
|
1044
1038
|
evaluate_write node.expression, Types.array_of(value), scope, evaluated_receivers if node.expression
|
1045
1039
|
when Prism::LocalVariableTargetNode, Prism::GlobalVariableTargetNode, Prism::InstanceVariableTargetNode, Prism::ClassVariableTargetNode, Prism::ConstantTargetNode
|
@@ -1047,7 +1041,6 @@ module ReplTypeCompletor
|
|
1047
1041
|
when Prism::ConstantPathTargetNode
|
1048
1042
|
receiver = evaluated_receivers&.[](node.parent) || evaluate(node.parent, scope) if node.parent
|
1049
1043
|
const_path_write receiver, node.child.name.to_s, value, scope
|
1050
|
-
value
|
1051
1044
|
end
|
1052
1045
|
end
|
1053
1046
|
|
@@ -1070,20 +1063,24 @@ module ReplTypeCompletor
|
|
1070
1063
|
when Prism::MultiWriteNode, Prism::MultiTargetNode
|
1071
1064
|
targets = [*node.lefts, *node.rest, *node.rights]
|
1072
1065
|
targets.each { evaluate_multi_write_receiver _1, scope, evaluated_receivers }
|
1073
|
-
when Prism::CallNode
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
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
|
1078
1073
|
if node.arguments
|
1079
1074
|
node.arguments.arguments&.each do |arg|
|
1080
1075
|
if arg.is_a? Prism::SplatNode
|
1081
|
-
evaluate arg.expression, scope
|
1076
|
+
evaluate arg.expression, scope if arg.expression
|
1082
1077
|
else
|
1083
1078
|
evaluate arg, scope
|
1084
1079
|
end
|
1085
1080
|
end
|
1086
1081
|
end
|
1082
|
+
evaluate node.block.expression, scope if node.block&.expression
|
1083
|
+
receiver
|
1087
1084
|
when Prism::SplatNode
|
1088
1085
|
evaluate_multi_write_receiver node.expression, scope, evaluated_receivers if node.expression
|
1089
1086
|
end
|
data/lib/repl_type_completor.rb
CHANGED
@@ -68,19 +68,19 @@ module ReplTypeCompletor
|
|
68
68
|
calculate_type_scope = ->(node) { TypeAnalyzer.calculate_target_type_scope binding, [*parents, target_node], node }
|
69
69
|
|
70
70
|
case target_node
|
71
|
-
when Prism::StringNode
|
71
|
+
when Prism::StringNode
|
72
|
+
return unless target_node.closing&.empty?
|
73
|
+
|
72
74
|
call_node, args_node = parents.last(2)
|
73
75
|
return unless call_node.is_a?(Prism::CallNode) && call_node.receiver.nil?
|
74
76
|
return unless args_node.is_a?(Prism::ArgumentsNode) && args_node.arguments.size == 1
|
75
77
|
|
76
|
-
|
77
|
-
|
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]
|
82
80
|
end
|
83
81
|
when Prism::SymbolNode
|
82
|
+
return unless !target_node.closing || target_node.empty?
|
83
|
+
|
84
84
|
name = target_node.value.to_s
|
85
85
|
if parents.last.is_a? Prism::BlockArgumentNode # method(&:target)
|
86
86
|
receiver_type, _scope = calculate_type_scope.call target_node
|
@@ -88,7 +88,9 @@ module ReplTypeCompletor
|
|
88
88
|
else
|
89
89
|
[:symbol, name] unless name.empty?
|
90
90
|
end
|
91
|
-
when Prism::CallNode
|
91
|
+
when Prism::CallNode, Prism::CallTargetNode
|
92
|
+
return if target_node.is_a?(Prism::CallNode) && target_node.opening
|
93
|
+
|
92
94
|
name = target_node.message.to_s
|
93
95
|
return [:lvar_or_method, name, calculate_scope.call] if target_node.receiver.nil?
|
94
96
|
|
@@ -123,14 +125,8 @@ module ReplTypeCompletor
|
|
123
125
|
end
|
124
126
|
|
125
127
|
def find_target(node, position)
|
126
|
-
|
127
|
-
|
128
|
-
# Unclosed quoted string has empty content and empty closing
|
129
|
-
return [node] if node.opening && node.closing&.empty?
|
130
|
-
when Prism::InterpolatedStringNode
|
131
|
-
# Unclosed double quoted string is InterpolatedStringNode with empty parts
|
132
|
-
return [node] if node.parts.empty? && node.opening && node.closing&.empty?
|
133
|
-
end
|
128
|
+
# Skip because NumberedParametersNode#location gives location of whole block
|
129
|
+
return if node.is_a? Prism::NumberedParametersNode
|
134
130
|
|
135
131
|
node.compact_child_nodes.each do |n|
|
136
132
|
match = find_target(n, position)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: repl_type_completor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tompng
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prism
|
@@ -16,14 +16,20 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.
|
19
|
+
version: 0.19.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.20.0
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - ">="
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.
|
29
|
+
version: 0.19.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.20.0
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
34
|
name: rbs
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
@@ -31,6 +37,9 @@ dependencies:
|
|
31
37
|
- - ">="
|
32
38
|
- !ruby/object:Gem::Version
|
33
39
|
version: 2.7.0
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 4.0.0
|
34
43
|
type: :runtime
|
35
44
|
prerelease: false
|
36
45
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -38,6 +47,9 @@ dependencies:
|
|
38
47
|
- - ">="
|
39
48
|
- !ruby/object:Gem::Version
|
40
49
|
version: 2.7.0
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 4.0.0
|
41
53
|
description: Type based completion for REPL.
|
42
54
|
email:
|
43
55
|
- tomoyapenguin@gmail.com
|