katakata_irb 0.1.11 → 0.2.0
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/Gemfile +1 -0
- data/katakata_irb.gemspec +1 -0
- data/lib/katakata_irb/completor.rb +143 -219
- data/lib/katakata_irb/scope.rb +179 -74
- data/lib/katakata_irb/type_simulator.rb +774 -779
- data/lib/katakata_irb/types.rb +17 -3
- data/lib/katakata_irb/version.rb +1 -1
- data/lib/katakata_irb.rb +2 -0
- metadata +16 -3
- data/lib/katakata_irb/nesting_parser.rb +0 -257
data/lib/katakata_irb/types.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'rbs/cli'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module KatakataIrb; end
|
5
4
|
module KatakataIrb::Types
|
@@ -12,6 +11,8 @@ module KatakataIrb::Types
|
|
12
11
|
end
|
13
12
|
|
14
13
|
def self.load_rbs_builder
|
14
|
+
require 'rbs'
|
15
|
+
require 'rbs/cli'
|
15
16
|
loader = RBS::CLI::LibraryOptions.new.loader
|
16
17
|
loader.add path: Pathname('sig')
|
17
18
|
RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
|
@@ -91,7 +92,11 @@ module KatakataIrb::Types
|
|
91
92
|
keyreqs = method_type.type.required_keywords
|
92
93
|
keyopts = method_type.type.optional_keywords
|
93
94
|
keyrest = method_type.type.rest_keywords
|
94
|
-
args =
|
95
|
+
args = args_types
|
96
|
+
if kwargs_type&.any? && keyreqs.empty? && keyopts.empty? && keyrest.nil?
|
97
|
+
kw_value_type = UnionType[*kwargs_type.values]
|
98
|
+
args += [InstanceType.new(Hash, K: SYMBOL, V: kw_value_type)]
|
99
|
+
end
|
95
100
|
if has_splat
|
96
101
|
score += 1 if args.count { !(_1 in Splat) } <= reqs.size + opts.size + trailings.size
|
97
102
|
elsif reqs.size + trailings.size <= args.size && (rest || args.size <= reqs.size + opts.size + trailings.size)
|
@@ -323,6 +328,11 @@ module KatakataIrb::Types
|
|
323
328
|
|
324
329
|
BOOLEAN = UnionType[TRUE, FALSE]
|
325
330
|
|
331
|
+
def self.array_of(*types)
|
332
|
+
type = types.size >= 2 ? UnionType[*types] : types.first || OBJECT
|
333
|
+
InstanceType.new Array, Elem: type
|
334
|
+
end
|
335
|
+
|
326
336
|
def self.from_rbs_type(return_type, self_type, extra_vars = {})
|
327
337
|
case return_type
|
328
338
|
when RBS::Types::Bases::Self
|
@@ -403,6 +413,10 @@ module KatakataIrb::Types
|
|
403
413
|
end
|
404
414
|
end
|
405
415
|
|
416
|
+
def self.method_return_bottom?(method)
|
417
|
+
method.type.return_type.is_a? RBS::Types::Bases::Bottom
|
418
|
+
end
|
419
|
+
|
406
420
|
def self.match_free_variables(vars, types, values)
|
407
421
|
accumulator = {}
|
408
422
|
types.zip values do |t, v|
|
data/lib/katakata_irb/version.rb
CHANGED
data/lib/katakata_irb.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: katakata_irb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- tompng
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-10-
|
11
|
+
date: 2023-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: irb
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.3.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: prism
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.13.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.13.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rbs
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -68,7 +82,6 @@ files:
|
|
68
82
|
- katakata_irb.gemspec
|
69
83
|
- lib/katakata_irb.rb
|
70
84
|
- lib/katakata_irb/completor.rb
|
71
|
-
- lib/katakata_irb/nesting_parser.rb
|
72
85
|
- lib/katakata_irb/scope.rb
|
73
86
|
- lib/katakata_irb/type_simulator.rb
|
74
87
|
- lib/katakata_irb/types.rb
|
@@ -1,257 +0,0 @@
|
|
1
|
-
module KatakataIrb::NestingParser
|
2
|
-
ERROR_TOKENS = %i[
|
3
|
-
on_parse_error
|
4
|
-
compile_error
|
5
|
-
on_assign_error
|
6
|
-
on_alias_error
|
7
|
-
on_class_name_error
|
8
|
-
on_param_error
|
9
|
-
]
|
10
|
-
|
11
|
-
def self.tokenize(code)
|
12
|
-
verbose, $VERBOSE = $VERBOSE, nil
|
13
|
-
tokens = Ripper::Lexer.new(code).scan.reject { ERROR_TOKENS.include? _1.event }
|
14
|
-
KatakataIrb::NestingParser.interpolate_ripper_ignored_tokens code, tokens
|
15
|
-
ensure
|
16
|
-
$VERBOSE = verbose
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.interpolate_ripper_ignored_tokens(code, tokens)
|
20
|
-
line_positions = code.lines.reduce([0]) { _1 << _1.last + _2.bytesize }
|
21
|
-
prev_byte_pos = 0
|
22
|
-
interpolated = []
|
23
|
-
prev_line = 1
|
24
|
-
event = :on_ignored_by_ripper
|
25
|
-
tokens.each do |t|
|
26
|
-
line, col = t.pos
|
27
|
-
byte_pos = line_positions[line - 1] + col
|
28
|
-
if prev_byte_pos < byte_pos
|
29
|
-
tok = code.byteslice(prev_byte_pos...byte_pos)
|
30
|
-
pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]]
|
31
|
-
interpolated << Ripper::Lexer::Elem.new(pos, event, tok, 0)
|
32
|
-
prev_line += tok.count("\n")
|
33
|
-
end
|
34
|
-
interpolated << t
|
35
|
-
prev_byte_pos = byte_pos + t.tok.bytesize
|
36
|
-
prev_line += t.tok.count("\n")
|
37
|
-
end
|
38
|
-
if prev_byte_pos < code.bytesize
|
39
|
-
tok = code.byteslice(prev_byte_pos..)
|
40
|
-
pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]]
|
41
|
-
interpolated << Ripper::Lexer::Elem.new(pos, event, tok, 0)
|
42
|
-
end
|
43
|
-
interpolated
|
44
|
-
end
|
45
|
-
|
46
|
-
IGNORE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
|
47
|
-
|
48
|
-
# Scan each token and call the given block with array of token and other information for parsing
|
49
|
-
def self.scan_opens(tokens)
|
50
|
-
opens = []
|
51
|
-
pending_heredocs = []
|
52
|
-
first_token_on_line = true
|
53
|
-
tokens.each do |t|
|
54
|
-
skip = false
|
55
|
-
last_tok, state, args = opens.last
|
56
|
-
case state
|
57
|
-
when :in_unquoted_symbol
|
58
|
-
unless IGNORE_TOKENS.include?(t.event)
|
59
|
-
opens.pop
|
60
|
-
skip = true
|
61
|
-
end
|
62
|
-
when :in_lambda_head
|
63
|
-
opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
|
64
|
-
when :in_method_head
|
65
|
-
unless IGNORE_TOKENS.include?(t.event)
|
66
|
-
next_args = []
|
67
|
-
body = nil
|
68
|
-
if args.include?(:receiver)
|
69
|
-
case t.event
|
70
|
-
when :on_lparen, :on_ivar, :on_gvar, :on_cvar
|
71
|
-
# def (receiver). | def @ivar. | def $gvar. | def @@cvar.
|
72
|
-
next_args << :dot
|
73
|
-
when :on_kw
|
74
|
-
case t.tok
|
75
|
-
when 'self', 'true', 'false', 'nil'
|
76
|
-
# def self(arg) | def self.
|
77
|
-
next_args.push(:arg, :dot)
|
78
|
-
else
|
79
|
-
# def if(arg)
|
80
|
-
skip = true
|
81
|
-
next_args << :arg
|
82
|
-
end
|
83
|
-
when :on_op, :on_backtick
|
84
|
-
# def +(arg)
|
85
|
-
skip = true
|
86
|
-
next_args << :arg
|
87
|
-
when :on_ident, :on_const
|
88
|
-
# def a(arg) | def a.
|
89
|
-
next_args.push(:arg, :dot)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
if args.include?(:dot)
|
93
|
-
# def receiver.name
|
94
|
-
next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::')
|
95
|
-
end
|
96
|
-
if args.include?(:name)
|
97
|
-
if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event)
|
98
|
-
# def name(arg) | def receiver.name(arg)
|
99
|
-
next_args << :arg
|
100
|
-
skip = true
|
101
|
-
end
|
102
|
-
end
|
103
|
-
if args.include?(:arg)
|
104
|
-
case t.event
|
105
|
-
when :on_nl, :on_semicolon
|
106
|
-
# def recever.f;
|
107
|
-
body = :normal
|
108
|
-
when :on_lparen
|
109
|
-
# def recever.f()
|
110
|
-
next_args << :eq
|
111
|
-
else
|
112
|
-
if t.event == :on_op && t.tok == '='
|
113
|
-
# def receiver.f =
|
114
|
-
body = :oneliner
|
115
|
-
else
|
116
|
-
# def recever.f arg
|
117
|
-
next_args << :arg_without_paren
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
if args.include?(:eq)
|
122
|
-
if t.event == :on_op && t.tok == '='
|
123
|
-
body = :oneliner
|
124
|
-
else
|
125
|
-
body = :normal
|
126
|
-
end
|
127
|
-
end
|
128
|
-
if args.include?(:arg_without_paren)
|
129
|
-
if %i[on_semicolon on_nl].include?(t.event)
|
130
|
-
# def f a;
|
131
|
-
body = :normal
|
132
|
-
else
|
133
|
-
# def f a, b
|
134
|
-
next_args << :arg_without_paren
|
135
|
-
end
|
136
|
-
end
|
137
|
-
if body == :oneliner
|
138
|
-
opens.pop
|
139
|
-
elsif body
|
140
|
-
opens[-1] = [last_tok, nil]
|
141
|
-
else
|
142
|
-
opens[-1] = [last_tok, :in_method_head, next_args]
|
143
|
-
end
|
144
|
-
end
|
145
|
-
when :in_for_while_until_condition
|
146
|
-
if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do')
|
147
|
-
skip = true if t.event == :on_kw && t.tok == 'do'
|
148
|
-
opens[-1] = [last_tok, nil]
|
149
|
-
end
|
150
|
-
when :in_block_head
|
151
|
-
if t.event == :on_op && t.tok == '|'
|
152
|
-
opens[-1] = [last_tok, nil]
|
153
|
-
opens << [t, :in_block_args]
|
154
|
-
elsif !IGNORE_TOKENS.include?(t.event)
|
155
|
-
opens[-1] = [last_tok, nil]
|
156
|
-
end
|
157
|
-
when :in_block_args
|
158
|
-
if t.event == :on_op && t.tok == '|' && t.state.allbits?(Ripper::EXPR_BEG)
|
159
|
-
opens.pop
|
160
|
-
skip = true
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
unless skip
|
165
|
-
case t.event
|
166
|
-
when :on_kw
|
167
|
-
case t.tok
|
168
|
-
when 'do'
|
169
|
-
opens << [t, :in_block_head]
|
170
|
-
when 'begin', 'class', 'module', 'case'
|
171
|
-
opens << [t, nil]
|
172
|
-
when 'end'
|
173
|
-
opens.pop
|
174
|
-
when 'def'
|
175
|
-
opens << [t, :in_method_head, [:receiver, :name]]
|
176
|
-
when 'if', 'unless'
|
177
|
-
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
178
|
-
opens << [t, nil]
|
179
|
-
end
|
180
|
-
when 'while', 'until'
|
181
|
-
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
182
|
-
opens << [t, :in_for_while_until_condition]
|
183
|
-
end
|
184
|
-
when 'ensure', 'rescue'
|
185
|
-
unless t.state.allbits?(Ripper::EXPR_LABEL)
|
186
|
-
opens.pop
|
187
|
-
opens << [t, nil]
|
188
|
-
end
|
189
|
-
when 'elsif', 'else', 'when'
|
190
|
-
opens.pop
|
191
|
-
opens << [t, nil]
|
192
|
-
when 'for'
|
193
|
-
opens << [t, :in_for_while_until_condition]
|
194
|
-
when 'in'
|
195
|
-
if last_tok&.event == :on_kw && %w[case in].include?(last_tok.tok) && first_token_on_line
|
196
|
-
opens.pop
|
197
|
-
opens << [t, nil]
|
198
|
-
end
|
199
|
-
end
|
200
|
-
when :on_lbrace
|
201
|
-
if t.state.allbits?(Ripper::EXPR_LABEL)
|
202
|
-
opens << [t, nil]
|
203
|
-
else
|
204
|
-
opens << [t, :in_block_head]
|
205
|
-
end
|
206
|
-
when :on_tlambda
|
207
|
-
opens << [t, :in_lambda_head]
|
208
|
-
when :on_lparen, :on_lbracket, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
|
209
|
-
opens << [t, nil]
|
210
|
-
when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
|
211
|
-
opens.pop
|
212
|
-
when :on_heredoc_beg
|
213
|
-
pending_heredocs << t
|
214
|
-
when :on_heredoc_end
|
215
|
-
opens.pop
|
216
|
-
when :on_backtick
|
217
|
-
opens << [t, nil] if t.state.allbits?(Ripper::EXPR_BEG)
|
218
|
-
when :on_tstring_beg, :on_words_beg, :on_qwords_beg, :on_symbols_beg, :on_qsymbols_beg, :on_regexp_beg
|
219
|
-
opens << [t, nil]
|
220
|
-
when :on_tstring_end, :on_regexp_end, :on_label_end
|
221
|
-
opens.pop
|
222
|
-
when :on_symbeg
|
223
|
-
if t.tok == ':'
|
224
|
-
opens << [t, :in_unquoted_symbol]
|
225
|
-
else
|
226
|
-
opens << [t, nil]
|
227
|
-
end
|
228
|
-
when :on_op
|
229
|
-
case t.tok
|
230
|
-
when '?'
|
231
|
-
# opening of `cond ? value : value``
|
232
|
-
opens << [t, nil]
|
233
|
-
when ':'
|
234
|
-
# closing of `cond ? value : value``
|
235
|
-
opens.pop
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
if t.event == :on_nl || t.event == :on_semicolon
|
240
|
-
first_token_on_line = true
|
241
|
-
elsif t.event != :on_sp
|
242
|
-
first_token_on_line = false
|
243
|
-
end
|
244
|
-
if pending_heredocs.any? && t.tok.include?("\n")
|
245
|
-
pending_heredocs.reverse_each { |t| opens << [t, nil] }
|
246
|
-
pending_heredocs = []
|
247
|
-
end
|
248
|
-
yield t, opens if block_given?
|
249
|
-
end
|
250
|
-
opens.map(&:first) + pending_heredocs.reverse
|
251
|
-
end
|
252
|
-
|
253
|
-
def self.open_tokens(tokens)
|
254
|
-
# scan_opens without block will return a list of open tokens at last token position
|
255
|
-
scan_opens(tokens)
|
256
|
-
end
|
257
|
-
end
|