katakata_irb 0.1.12 → 0.2.1

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.
@@ -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,10 +11,12 @@ 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
18
- rescue => e
19
+ rescue LoadError, StandardError => e
19
20
  @rbs_load_error = e
20
21
  puts "\r\nKatakataIRB failed to initialize RBS::DefinitionBuilder: #{e.class}\r\n"
21
22
  puts "See `KatakataIrb::Types.rbs_load_error` for more details.\r\n"
@@ -34,7 +35,7 @@ module KatakataIrb::Types
34
35
  def self.rbs_search_method(klass, method_name, singleton)
35
36
  klass.ancestors.each do |ancestor|
36
37
  name = class_name_of ancestor
37
- next unless name
38
+ next unless name && rbs_builder
38
39
  type_name = RBS::TypeName(name).absolute!
39
40
  definition = (singleton ? rbs_builder.build_singleton(type_name) : rbs_builder.build_instance(type_name)) rescue nil
40
41
  method = definition.methods[method_name] if definition
@@ -77,7 +78,7 @@ module KatakataIrb::Types
77
78
  [t, t.klass, false]
78
79
  end
79
80
  end
80
- has_splat = args_types.any? { _1 in Splat }
81
+ has_splat = args_types.any? { _1.is_a? Splat }
81
82
  methods_with_score = receivers.flat_map do |receiver_type, klass, singleton|
82
83
  method = rbs_search_method klass, method_name, singleton
83
84
  next [] unless method
@@ -91,9 +92,13 @@ 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
- score += 1 if args.count { !(_1 in Splat) } <= reqs.size + opts.size + trailings.size
101
+ score += 1 if args.count { !(_1.is_a? 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)
98
103
  score += 2
99
104
  centers = args[reqs.size...-trailings.size]
@@ -202,7 +207,7 @@ module KatakataIrb::Types
202
207
  def nonnillable() = self
203
208
  def rbs_methods
204
209
  name = KatakataIrb::Types.class_name_of(@klass)
205
- return {} unless name
210
+ return {} unless name && KatakataIrb::Types.rbs_builder
206
211
 
207
212
  type_name = RBS::TypeName(name).absolute!
208
213
  KatakataIrb::Types.rbs_builder.build_instance(type_name).methods rescue {}
@@ -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
@@ -365,11 +375,11 @@ module KatakataIrb::Types
365
375
  when RBS::Types::Variable
366
376
  if extra_vars.key? return_type.name
367
377
  extra_vars[return_type.name]
368
- elsif self_type in InstanceType
378
+ elsif self_type.is_a? InstanceType
369
379
  self_type.params[return_type.name] || OBJECT
370
- elsif self_type in UnionType
380
+ elsif self_type.is_a? UnionType
371
381
  types = self_type.types.filter_map do |t|
372
- t.params[return_type.name] if t in InstanceType
382
+ t.params[return_type.name] if t.is_a? InstanceType
373
383
  end
374
384
  UnionType[*types]
375
385
  else
@@ -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.12"
4
+ VERSION = "0.2.1"
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.12
4
+ version: 0.2.1
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-14 00:00:00.000000000 Z
11
+ date: 2023-10-18 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.14.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.14.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rbs
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -68,9 +82,8 @@ 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
- - lib/katakata_irb/type_simulator.rb
86
+ - lib/katakata_irb/type_analyzer.rb
74
87
  - lib/katakata_irb/types.rb
75
88
  - lib/katakata_irb/version.rb
76
89
  - sig/katakata_irb.rbs
@@ -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