katakata_irb 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|