katakata_irb 0.1.9 → 0.1.10

Sign up to get free protection for your applications and to get access to all the features.
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