katakata_irb 0.2.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/katakata_irb.gemspec +1 -1
- data/lib/katakata_irb/completor.rb +46 -22
- data/lib/katakata_irb/scope.rb +53 -15
- data/lib/katakata_irb/type_analyzer.rb +1172 -0
- data/lib/katakata_irb/types.rb +11 -36
- data/lib/katakata_irb/version.rb +1 -1
- metadata +5 -5
- data/lib/katakata_irb/type_simulator.rb +0 -990
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad93f43d988f169816f4e842bdb70eda5a866574664f6afb5c015ae60b2f2d3b
|
4
|
+
data.tar.gz: 700e29af39db9a73fb71f0f2e76cf4d87bcf801e31fddaef3514416e6d3699e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d53414d13852cd4d88a92b841fcd20d85a19efd7cb2dd15faac245e0cd944f10e12e5176ca6b03aa82ca3bd66981c56a0a6ad228a73f9e149b1a4ee9077c4f39
|
7
|
+
data.tar.gz: 734aa26486a262b1feaf059290d7526fb061a71cd584c8ec4fa4fdbeb3f8a2b1d29b9e5dd64549e33d87e9987e736aeb1be0ae366033af9533914ca38981c4a8
|
data/katakata_irb.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
# Uncomment to register a new dependency of your gem
|
32
32
|
spec.add_dependency 'irb', '>= 1.4.0'
|
33
33
|
spec.add_dependency 'reline', '>= 0.3.0'
|
34
|
-
spec.add_dependency 'prism', '>= 0.
|
34
|
+
spec.add_dependency 'prism', '>= 0.16.0'
|
35
35
|
spec.add_dependency 'rbs'
|
36
36
|
|
37
37
|
# For more information and examples about making a new gem, check out our
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative '
|
4
|
-
require 'rbs'
|
5
|
-
require 'rbs/cli'
|
3
|
+
require_relative 'type_analyzer'
|
6
4
|
require 'irb'
|
7
5
|
require 'prism'
|
8
6
|
|
@@ -77,8 +75,8 @@ module KatakataIrb::Completor
|
|
77
75
|
$VERBOSE = verbose
|
78
76
|
end
|
79
77
|
|
80
|
-
doc_namespace_proc = ->
|
81
|
-
name = input[/[a-zA-Z_0-9]
|
78
|
+
doc_namespace_proc = -> input do
|
79
|
+
name = input[/[a-zA-Z_0-9]*[!?=]?\z/]
|
82
80
|
method_doc = -> type do
|
83
81
|
type = type.types.find { _1.all_methods.include? name.to_sym }
|
84
82
|
if type.is_a? KatakataIrb::Types::SingletonType
|
@@ -96,18 +94,42 @@ module KatakataIrb::Completor
|
|
96
94
|
end
|
97
95
|
end
|
98
96
|
|
97
|
+
value_doc = -> type do
|
98
|
+
return unless type
|
99
|
+
type.types.each do |t|
|
100
|
+
case t
|
101
|
+
when KatakataIrb::Types::SingletonType
|
102
|
+
return KatakataIrb::Types.class_name_of(t.module_or_class)
|
103
|
+
when KatakataIrb::Types::InstanceType
|
104
|
+
return KatakataIrb::Types.class_name_of(t.klass)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
99
110
|
case KatakataIrb::Completor.prev_analyze_result
|
100
111
|
in [:call_or_const, type, _name, _self_call]
|
101
112
|
call_or_const_doc.call type
|
102
113
|
in [:const, type, _name, scope]
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
114
|
+
if type
|
115
|
+
call_or_const_doc.call type
|
116
|
+
else
|
117
|
+
value_doc.call scope[name]
|
118
|
+
end
|
119
|
+
in [:gvar, _name, scope]
|
120
|
+
value_doc.call scope["$#{name}"]
|
121
|
+
in [:ivar, _name, scope]
|
122
|
+
value_doc.call scope["@#{name}"]
|
123
|
+
in [:cvar, _name, scope]
|
124
|
+
value_doc.call scope["@@#{name}"]
|
107
125
|
in [:call, type, _name, _self_call]
|
108
126
|
method_doc.call type
|
109
127
|
in [:lvar_or_method, _name, scope]
|
110
|
-
|
128
|
+
if scope.local_variables.include?(name)
|
129
|
+
value_doc.call scope[name]
|
130
|
+
else
|
131
|
+
method_doc.call scope.self_type
|
132
|
+
end
|
111
133
|
else
|
112
134
|
end
|
113
135
|
end
|
@@ -193,22 +215,25 @@ module KatakataIrb::Completor
|
|
193
215
|
end.join + "nil;\n"
|
194
216
|
code = lvars_code + code
|
195
217
|
ast = Prism.parse(code).value
|
196
|
-
name = code[/(@@|@|\$)?\w
|
218
|
+
name = code[/(@@|@|\$)?\w*[!?=]?\z/]
|
197
219
|
*parents, target_node = find_target ast, code.bytesize - name.bytesize
|
198
220
|
return unless target_node
|
199
221
|
|
200
|
-
calculate_scope = -> { KatakataIrb::
|
201
|
-
calculate_type_scope = ->(node) { KatakataIrb::
|
222
|
+
calculate_scope = -> { KatakataIrb::TypeAnalyzer.calculate_target_type_scope(binding, parents, target_node).last }
|
223
|
+
calculate_type_scope = ->(node) { KatakataIrb::TypeAnalyzer.calculate_target_type_scope binding, [*parents, target_node], node }
|
202
224
|
|
203
|
-
|
204
|
-
|
205
|
-
call_node = parents
|
225
|
+
case target_node
|
226
|
+
when Prism::StringNode, Prism::InterpolatedStringNode
|
227
|
+
call_node, args_node = parents.last(2)
|
228
|
+
return unless call_node.is_a?(Prism::CallNode) && call_node.receiver.nil?
|
206
229
|
return unless args_node.is_a?(Prism::ArgumentsNode) && args_node.arguments.size == 1
|
207
|
-
return unless call_node.is_a?(Prism::CallNode) && call_node.receiver.nil? && (call_node.message == 'require' || call_node.message == 'require_relative')
|
208
|
-
return [call_node.message.to_sym, name.rstrip]
|
209
|
-
end
|
210
230
|
|
211
|
-
|
231
|
+
case call_node.name
|
232
|
+
when :require
|
233
|
+
[:require, name.rstrip]
|
234
|
+
when :require_relative
|
235
|
+
[:require_relative, name.rstrip]
|
236
|
+
end
|
212
237
|
when Prism::SymbolNode
|
213
238
|
if parents.last.is_a? Prism::BlockArgumentNode # method(&:target)
|
214
239
|
receiver_type, _scope = calculate_type_scope.call target_node
|
@@ -263,8 +288,7 @@ module KatakataIrb::Completor
|
|
263
288
|
)
|
264
289
|
return [node] if location&.start_offset == position
|
265
290
|
|
266
|
-
node.
|
267
|
-
next unless n.is_a? Prism::Node
|
291
|
+
node.compact_child_nodes.each do |n|
|
268
292
|
match = find_target(n, position)
|
269
293
|
next unless match
|
270
294
|
match.unshift node
|
data/lib/katakata_irb/scope.rb
CHANGED
@@ -38,6 +38,8 @@ module KatakataIrb
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def get_const(nesting, path, _key = nil)
|
41
|
+
return unless nesting
|
42
|
+
|
41
43
|
result = path.reduce nesting do |mod, name|
|
42
44
|
return nil unless mod.is_a?(Module) && module_own_constant?(mod, name)
|
43
45
|
mod.const_get name
|
@@ -45,18 +47,25 @@ module KatakataIrb
|
|
45
47
|
KatakataIrb::Types.type_from_object result
|
46
48
|
end
|
47
49
|
|
50
|
+
def get_cvar(nesting, path, name, _key = nil)
|
51
|
+
return KatakataIrb::Types::NIL unless nesting
|
52
|
+
|
53
|
+
result = path.reduce nesting do |mod, n|
|
54
|
+
return KatakataIrb::Types::NIL unless mod.is_a?(Module) && module_own_constant?(mod, n)
|
55
|
+
mod.const_get n
|
56
|
+
end
|
57
|
+
value = result.class_variable_get name if result.is_a?(Module) && name.size >= 3 && result.class_variable_defined?(name)
|
58
|
+
Types.type_from_object value
|
59
|
+
end
|
60
|
+
|
48
61
|
def [](name)
|
49
62
|
@cache[name] ||= (
|
50
63
|
fallback = KatakataIrb::Types::NIL
|
51
64
|
case BaseScope.type_by_name name
|
52
|
-
when :cvar
|
53
|
-
BaseScope.type_of(fallback: fallback) { @self_object.class_variable_get name }
|
54
65
|
when :ivar
|
55
66
|
BaseScope.type_of(fallback: fallback) { @self_object.instance_variable_get name }
|
56
67
|
when :lvar
|
57
68
|
BaseScope.type_of(fallback: fallback) { @binding.local_variable_get(name) }
|
58
|
-
when :const
|
59
|
-
BaseScope.type_of(fallback: fallback) { @binding.eval name }
|
60
69
|
when :gvar
|
61
70
|
BaseScope.type_of(fallback: fallback) { @binding.eval name if @global_variables.include? name }
|
62
71
|
end
|
@@ -81,6 +90,7 @@ module KatakataIrb
|
|
81
90
|
|
82
91
|
def self.type_by_name(name)
|
83
92
|
if name.start_with? '@@'
|
93
|
+
# "@@cvar" or "@@cvar::[module_id]::[module_path]"
|
84
94
|
:cvar
|
85
95
|
elsif name.start_with? '@'
|
86
96
|
:ivar
|
@@ -88,7 +98,8 @@ module KatakataIrb
|
|
88
98
|
:gvar
|
89
99
|
elsif name.start_with? '%'
|
90
100
|
:internal
|
91
|
-
elsif name[0].downcase != name[0]
|
101
|
+
elsif name[0].downcase != name[0] || name[0].match?(/\d/)
|
102
|
+
# "ConstName" or "[module_id]::[const_path]"
|
92
103
|
:const
|
93
104
|
else
|
94
105
|
:lvar
|
@@ -101,10 +112,9 @@ module KatakataIrb
|
|
101
112
|
|
102
113
|
def self.from_binding(binding, locals) = new(BaseScope.new(binding, binding.eval('self'), locals))
|
103
114
|
|
104
|
-
def initialize(parent, table = {},
|
115
|
+
def initialize(parent, table = {}, trace_ivar: true, trace_lvar: true, self_type: nil, nesting: nil)
|
105
116
|
@parent = parent
|
106
117
|
@level = parent.level + 1
|
107
|
-
@trace_cvar = trace_cvar
|
108
118
|
@trace_ivar = trace_ivar
|
109
119
|
@trace_lvar = trace_lvar
|
110
120
|
@module_nesting = nesting ? [nesting, *parent.module_nesting] : parent.module_nesting
|
@@ -145,15 +155,13 @@ module KatakataIrb
|
|
145
155
|
def trace?(name)
|
146
156
|
return false unless @parent
|
147
157
|
type = BaseScope.type_by_name(name)
|
148
|
-
type == :
|
158
|
+
type == :ivar ? @trace_ivar : type == :lvar ? @trace_lvar : true
|
149
159
|
end
|
150
160
|
|
151
161
|
def level_of(name, var_type)
|
152
162
|
case var_type
|
153
163
|
when :ivar
|
154
164
|
return level unless @trace_ivar
|
155
|
-
when :cvar
|
156
|
-
return level unless @trace_cvar
|
157
165
|
when :gvar
|
158
166
|
return 0
|
159
167
|
end
|
@@ -167,14 +175,27 @@ module KatakataIrb
|
|
167
175
|
value || @parent.get_const(nesting, path, key)
|
168
176
|
end
|
169
177
|
|
178
|
+
def get_cvar(nesting, path, name, key = nil)
|
179
|
+
key ||= [name, nesting.__id__, path].join('::')
|
180
|
+
_l, value = @table[key]
|
181
|
+
value || @parent.get_cvar(nesting, path, name, key)
|
182
|
+
end
|
183
|
+
|
170
184
|
def [](name)
|
171
185
|
type = BaseScope.type_by_name(name)
|
172
186
|
if type == :const
|
187
|
+
return get_const(nil, nil, name) || KatakataIrb::Types::NIL if name.include?('::')
|
188
|
+
|
173
189
|
module_nesting.each do |(nesting, path)|
|
174
190
|
value = get_const nesting, [*path, name]
|
175
191
|
return value if value
|
176
192
|
end
|
177
|
-
KatakataIrb::Types::NIL
|
193
|
+
return KatakataIrb::Types::NIL
|
194
|
+
elsif type == :cvar
|
195
|
+
return get_cvar(nil, nil, nil, name) if name.include?('::')
|
196
|
+
|
197
|
+
nesting, path = module_nesting.first
|
198
|
+
return get_cvar(nesting, path, name)
|
178
199
|
end
|
179
200
|
level, value = @table[name]
|
180
201
|
if level
|
@@ -191,11 +212,28 @@ module KatakataIrb
|
|
191
212
|
@table[key] = [0, value]
|
192
213
|
end
|
193
214
|
|
215
|
+
def set_cvar(nesting, path, name, value)
|
216
|
+
key = [name, nesting.__id__, path].join('::')
|
217
|
+
@table[key] = [0, value]
|
218
|
+
end
|
219
|
+
|
194
220
|
def []=(name, value)
|
195
221
|
type = BaseScope.type_by_name(name)
|
196
222
|
if type == :const
|
197
|
-
|
198
|
-
|
223
|
+
if name.include?('::')
|
224
|
+
@table[name] = [0, value]
|
225
|
+
else
|
226
|
+
parent_module, parent_path = module_nesting.first
|
227
|
+
set_const parent_module, [*parent_path, name], value
|
228
|
+
end
|
229
|
+
return
|
230
|
+
elsif type == :cvar
|
231
|
+
if name.include?('::')
|
232
|
+
@table[name] = [0, value]
|
233
|
+
else
|
234
|
+
parent_module, parent_path = module_nesting.first
|
235
|
+
set_cvar parent_module, parent_path, name, value
|
236
|
+
end
|
199
237
|
return
|
200
238
|
end
|
201
239
|
variable_level = level_of name, type
|
@@ -285,8 +323,8 @@ module KatakataIrb
|
|
285
323
|
end
|
286
324
|
|
287
325
|
def table_class_variables
|
288
|
-
cvars = @table.keys.
|
289
|
-
cvars |= @parent.table_class_variables if @parent.mutable?
|
326
|
+
cvars = @table.keys.filter_map { _1.split('::', 2).first if BaseScope.type_by_name(_1) == :cvar }
|
327
|
+
cvars |= @parent.table_class_variables if @parent.mutable?
|
290
328
|
cvars
|
291
329
|
end
|
292
330
|
|