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.
@@ -1,5 +1,4 @@
1
- require 'rbs'
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 = (kwargs_type && keyreqs.empty? && keyopts.empty? && keyrest.nil?) ? args_types + [kwargs_type] : args_types
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|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KatakataIrb
4
- VERSION = "0.1.11"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/katakata_irb.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'katakata_irb/version'
2
4
  require 'katakata_irb/completor'
3
5
  require 'katakata_irb/types'
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.1.11
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-12 00:00:00.000000000 Z
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