katakata_irb 0.1.11 → 0.2.0
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/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
|