katakata_irb 0.1.9 → 0.1.10

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce4d7b2e5ebfc546ddb501c43c13c62b166a55dc34a215a460d560b946ad4f02
4
- data.tar.gz: f23396dc9804a798d109342d063943da759139fd849fd828f85d51f71089d5e7
3
+ metadata.gz: 297457c829dac09ddee68c1cc5365acfcc2583e0282fb1070ebae8fa138523ba
4
+ data.tar.gz: a45663afa386d4093814a3ea2a49c98cb03e90004e2a42c0dc723f4686500a51
5
5
  SHA512:
6
- metadata.gz: 5e44f1dbab26c56949e89053a0309ad9f3195a8f545ea95b546a541c547b55b86a69afb3944bdbfeb5e498a62105cb2f54630e559b32188b2532cfa4625ee765
7
- data.tar.gz: 9beaaf9996eba51111cabc5a1ba4082f94657ecdeb06b3cf1c0859c346822d772134673d190639b874caacf3f220c19d8ac8ad150c2c98f85129e658a58a2b95
6
+ metadata.gz: e66cd04bba34272f585adb1a6dde686a49d064604a48b1c0d14093474857b30537f6b05dd965eaf7ae822b174e373122479c05a643cc951fe4ecea3009a625c6
7
+ data.tar.gz: 4cb475b48b8e73db73340a1a11c97b087f99d2d6159e235d93a8845e4a718e9b18deb4e693d86059ba98bdbecbf41f24c13cb70d969fdd6d18f9cb171c76478b
@@ -10,6 +10,7 @@ module KatakataIrb::Completor
10
10
  singleton_class.attr_accessor :prev_analyze_result
11
11
 
12
12
  def self.setup
13
+ KatakataIrb::Types.preload_in_thread
13
14
  completion_proc = ->(target, preposing = nil, postposing = nil) do
14
15
  code = "#{preposing}#{target}"
15
16
  irb_context = IRB.conf[:MAIN_CONTEXT]
@@ -61,7 +62,7 @@ module KatakataIrb::Completor
61
62
  end
62
63
 
63
64
  IRB::InputCompletor.singleton_class.prepend Module.new{
64
- def retrieve_completion_data(input, _bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
65
+ def retrieve_completion_data(input, doc_namespace: false, **)
65
66
  return super unless doc_namespace
66
67
  name = input[/[a-zA-Z_0-9]+[!?=]?\z/]
67
68
  method_doc = -> type do
@@ -100,32 +101,39 @@ module KatakataIrb::Completor
100
101
  setup_type_dialog
101
102
  end
102
103
 
104
+ def self.type_dialog_content
105
+ receiver_type = (
106
+ case KatakataIrb::Completor.prev_analyze_result
107
+ in [:call_or_const, type, name, _self_call] if name.empty?
108
+ type
109
+ in [:call, type, name, _self_call] if name.empty?
110
+ type
111
+ else
112
+ return
113
+ end
114
+ )
115
+ if KatakataIrb::Types.rbs_builder.nil? && !KatakataIrb::Types.rbs_load_error
116
+ return [' Loading ', ' RBS... ']
117
+ end
118
+ types = receiver_type.types
119
+ contents = types.filter_map do |type|
120
+ case type
121
+ when KatakataIrb::Types::InstanceType
122
+ type.inspect_without_params
123
+ else
124
+ type.inspect
125
+ end
126
+ end.uniq
127
+ contents if contents.any?
128
+ end
129
+
103
130
  def self.setup_type_dialog
104
131
  type_dialog_proc = -> {
105
132
  return if just_cursor_moving && completion_journey_data
106
133
  cursor_pos_to_render, _result, pointer, autocomplete_dialog = context.last(4)
107
134
  return unless cursor_pos_to_render && autocomplete_dialog&.width && pointer.nil?
108
- receiver_type = (
109
- case KatakataIrb::Completor.prev_analyze_result
110
- in [:call_or_const, type, name, _self_call] if name.empty?
111
- type
112
- in [:call, type, name, _self_call] if name.empty?
113
- type
114
- else
115
- return
116
- end
117
- )
118
- return unless receiver_type
119
- types = type.types
120
- contents = types.filter_map do |type|
121
- case type
122
- when KatakataIrb::Types::InstanceType
123
- type.inspect_without_params
124
- else
125
- type.inspect
126
- end
127
- end.uniq
128
- return if contents.empty?
135
+ contents = KatakataIrb::Completor.type_dialog_content
136
+ return unless contents&.any?
129
137
 
130
138
  width = contents.map { Reline::Unicode.calculate_width _1 }.max
131
139
  x = cursor_pos_to_render.x + autocomplete_dialog.width
@@ -145,12 +153,11 @@ module KatakataIrb::Completor
145
153
  "#{name}="
146
154
  end.join + "nil;\n"
147
155
  code = lvars_code + code
148
- tokens = RubyLex.ripper_lex_without_warning code
149
- tokens = KatakataIrb::NestingParser.interpolate_ripper_ignored_tokens code, tokens
150
- last_opens = KatakataIrb::NestingParser.parse(tokens)
156
+ tokens = KatakataIrb::NestingParser.tokenize code
157
+ last_opens = KatakataIrb::NestingParser.open_tokens(tokens)
151
158
  closings = last_opens.map do |t|
152
159
  case t.tok
153
- when /\A%.[<>]\z/
160
+ when /\A%.?[<>]\z/
154
161
  $/ + '>'
155
162
  when '{', '#{', /\A%.?[{}]\z/
156
163
  $/ + '}'
@@ -271,9 +278,15 @@ module KatakataIrb::Completor
271
278
  [:ivar, name, calculate_scope.call.self_type] if icvar_available
272
279
  in [:var_ref, [:@cvar,]]
273
280
  [:cvar, name, calculate_scope.call.self_type] if icvar_available
274
- in [:call, receiver, [:@period,] | [:@op, '&.',] | :'::' => dot, [:@ident | :@const,]]
281
+ in [:call, receiver, [:@op, '::',] | :'::', [:@ident | :@const,]]
282
+ self_call = (receiver in [:var_ref, [:@kw, 'self',]])
283
+ [:call_or_const, calculate_receiver.call(receiver), name, self_call]
284
+ in [:call, receiver, [:@period,], [:@ident | :@const,]]
285
+ self_call = (receiver in [:var_ref, [:@kw, 'self',]])
286
+ [:call, calculate_receiver.call(receiver), name, self_call]
287
+ in [:call, receiver, [:@op, '&.',], [:@ident | :@const,]]
275
288
  self_call = (receiver in [:var_ref, [:@kw, 'self',]])
276
- [dot == :'::' ? :call_or_const : :call, calculate_receiver.call(receiver), name, self_call]
289
+ [:call, calculate_receiver.call(receiver).nonnillable, name, self_call]
277
290
  in [:const_path_ref, receiver, [:@const,]]
278
291
  [:const, calculate_receiver.call(receiver), name]
279
292
  in [:top_const_ref, [:@const,]]
@@ -1,4 +1,18 @@
1
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
+ tokens = Ripper::Lexer.new(code).scan.reject { ERROR_TOKENS.include? _1.event }
13
+ KatakataIrb::NestingParser.interpolate_ripper_ignored_tokens code, tokens
14
+ end
15
+
2
16
  def self.interpolate_ripper_ignored_tokens(code, tokens)
3
17
  line_positions = code.lines.reduce([0]) { _1 << _1.last + _2.bytesize }
4
18
  prev_byte_pos = 0
@@ -26,9 +40,10 @@ module KatakataIrb::NestingParser
26
40
  interpolated
27
41
  end
28
42
 
29
- IGNOREABLE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
43
+ IGNORE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
30
44
 
31
- def self.parse(tokens)
45
+ # Scan each token and call the given block with array of token and other information for parsing
46
+ def self.scan_opens(tokens)
32
47
  opens = []
33
48
  pending_heredocs = []
34
49
  first_token_on_line = true
@@ -37,14 +52,14 @@ module KatakataIrb::NestingParser
37
52
  last_tok, state, args = opens.last
38
53
  case state
39
54
  when :in_unquoted_symbol
40
- unless t.event == :on_sp
55
+ unless IGNORE_TOKENS.include?(t.event)
41
56
  opens.pop
42
57
  skip = true
43
58
  end
44
59
  when :in_lambda_head
45
60
  opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
46
61
  when :in_method_head
47
- unless IGNOREABLE_TOKENS.include?(t.event)
62
+ unless IGNORE_TOKENS.include?(t.event)
48
63
  next_args = []
49
64
  body = nil
50
65
  if args.include?(:receiver)
@@ -133,7 +148,7 @@ module KatakataIrb::NestingParser
133
148
  if t.event == :on_op && t.tok == '|'
134
149
  opens[-1] = [last_tok, nil]
135
150
  opens << [t, :in_block_args]
136
- elsif !IGNOREABLE_TOKENS.include?(t.event)
151
+ elsif !IGNORE_TOKENS.include?(t.event)
137
152
  opens[-1] = [last_tok, nil]
138
153
  end
139
154
  when :in_block_args
@@ -201,6 +216,12 @@ module KatakataIrb::NestingParser
201
216
  opens << [t, nil]
202
217
  when :on_tstring_end, :on_regexp_end, :on_label_end
203
218
  opens.pop
219
+ when :on_symbeg
220
+ if t.tok == ':'
221
+ opens << [t, :in_unquoted_symbol]
222
+ else
223
+ opens << [t, nil]
224
+ end
204
225
  when :on_op
205
226
  case t.tok
206
227
  when '?'
@@ -210,12 +231,6 @@ module KatakataIrb::NestingParser
210
231
  # closing of `cond ? value : value``
211
232
  opens.pop
212
233
  end
213
- when :on_symbeg
214
- if t.tok == ':'
215
- opens << [t, :in_unquoted_symbol]
216
- else
217
- opens << [t, nil]
218
- end
219
234
  end
220
235
  end
221
236
  if t.event == :on_nl || t.event == :on_semicolon
@@ -232,29 +247,8 @@ module KatakataIrb::NestingParser
232
247
  opens.map(&:first) + pending_heredocs.reverse
233
248
  end
234
249
 
235
- def self.parse_line(tokens)
236
- line_tokens = []
237
- prev_opens = []
238
- min_depth = 0
239
- output = []
240
- last_opens = parse(tokens) do |t, opens|
241
- depth = t == opens.last&.first ? opens.size - 1 : opens.size
242
- min_depth = depth if depth < min_depth
243
- if t.tok.include?("\n")
244
- t.tok.each_line do |line|
245
- line_tokens << [t, line]
246
- next if line[-1] != "\n"
247
- next_opens = opens.map(&:first)
248
- output << [line_tokens, prev_opens, next_opens, min_depth]
249
- prev_opens = next_opens
250
- min_depth = prev_opens.size
251
- line_tokens = []
252
- end
253
- else
254
- line_tokens << [t, t.tok]
255
- end
256
- end
257
- output << [line_tokens, prev_opens, last_opens, min_depth] if line_tokens.any?
258
- output
250
+ def self.open_tokens(tokens)
251
+ # scan_opens without block will return a list of open tokens at last token position
252
+ scan_opens(tokens)
259
253
  end
260
254
  end
@@ -769,9 +769,9 @@ class KatakataIrb::TypeSimulator
769
769
  case sexp
770
770
  in [:fcall | :vcall, [:@ident | :@const | :@kw | :@op, method,]] # hoge
771
771
  [nil, method, [], [], nil, false]
772
- in [:call, receiver, [:@period,] | [:@op, '&.',] | :'::' => dot, :call]
772
+ in [:call, receiver, [:@period,] | [:@op, '&.',] | [:@op, '::',] | :'::' => dot, :call]
773
773
  [receiver, :call, [], [], nil, optional[dot]]
774
- in [:call, receiver, [:@period,] | [:@op, '&.',] | :'::' => dot, method]
774
+ in [:call, receiver, [:@period,] | [:@op, '&.',] | [:@op, '::',] | :'::' => dot, method]
775
775
  method => [:@ident | :@const | :@kw | :@op, method,] unless method == :call
776
776
  [receiver, method, [], [], nil, optional[dot]]
777
777
  in [:command, [:@ident | :@const | :@kw | :@op, method,], args] # hoge 1, 2
@@ -3,8 +3,12 @@ require 'rbs/cli'
3
3
 
4
4
  module KatakataIrb; end
5
5
  module KatakataIrb::Types
6
- def self.rbs_builder
7
- @rbs_builder ||= load_rbs_builder
6
+ singleton_class.attr_reader :rbs_builder, :rbs_load_error
7
+
8
+ def self.preload_in_thread
9
+ @loader_thread ||= Thread.new do
10
+ @rbs_builder = load_rbs_builder
11
+ end
8
12
  end
9
13
 
10
14
  def self.load_rbs_builder
@@ -12,8 +16,10 @@ module KatakataIrb::Types
12
16
  loader.add path: Pathname('sig')
13
17
  RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
14
18
  rescue => e
15
- puts "\r\nKatakataIRB failed to initialize RBS::DefinitionBuilder\r\n#{e}\r\n"
16
- Object.new
19
+ @rbs_load_error = e
20
+ puts "\r\nKatakataIRB failed to initialize RBS::DefinitionBuilder: #{e.class}\r\n"
21
+ puts "See `KatakataIrb::Types.rbs_load_error` for more details.\r\n"
22
+ nil
17
23
  end
18
24
 
19
25
  Splat = Struct.new :item
@@ -59,6 +65,8 @@ module KatakataIrb::Types
59
65
  end
60
66
 
61
67
  def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block)
68
+ return [] unless rbs_builder
69
+
62
70
  receivers = type.types.map do |t|
63
71
  case t
64
72
  in ProcType
@@ -397,8 +405,8 @@ module KatakataIrb::Types
397
405
 
398
406
  def self.match_free_variables(vars, types, values)
399
407
  accumulator = {}
400
- types.zip(values).each do |t, v|
401
- _match_free_variable(vars, t, v, accumulator)
408
+ types.zip values do |t, v|
409
+ _match_free_variable(vars, t, v, accumulator) if v
402
410
  end
403
411
  accumulator.transform_values { UnionType[*_1] }
404
412
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KatakataIrb
4
- VERSION = "0.1.9"
4
+ VERSION = "0.1.10"
5
5
  end
data/lib/katakata_irb.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'katakata_irb/version'
2
2
  require 'katakata_irb/completor'
3
+ require 'katakata_irb/types'
3
4
 
4
5
  module KatakataIrb
5
6
  class << self
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.9
4
+ version: 0.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - tompng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-19 00:00:00.000000000 Z
11
+ date: 2023-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: irb
@@ -95,7 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  requirements: []
98
- rubygems_version: 3.4.6
98
+ rubygems_version: 3.4.10
99
99
  signing_key:
100
100
  specification_version: 4
101
101
  summary: IRB with Typed Completion