repl_type_completor 0.1.7 → 0.1.8

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: 2e852d359a7203c7d7b6b001dc043cb749427339d7024bc13666baff16908076
4
- data.tar.gz: c9f790626f9cf102b7571c7eb9612da3924b1e8f9d360bc9cd3881f48dc602a5
3
+ metadata.gz: 96985b2dccd9d5437190f365bb6b367a4dd830cbf35c9542825b340f4d833f70
4
+ data.tar.gz: 53d2a4f5ef5d01b2f1626d978a385bc74d44472ff69f04fc9975b2669226a775
5
5
  SHA512:
6
- metadata.gz: 6a60c14cde97df73039ea4be3572d7e53fbff6848229ec2f127ab1537d46ec2fecdcaf360bcb63460bb3e44237f08f4d962c0677b30f9aafdb575126b33efd84
7
- data.tar.gz: 64a1113147f6d0a3a90958a2f9a106cd9d04a8678ee10103d54000b7c7b754584feb63382fbaf77534955ade2a8400ad19d76f696ad7d7faa9bb18cd0789e89c
6
+ metadata.gz: 61535de8984acd5d7bc82b0c93e41dac60b5e43dcf4606666f0c7df491e685c39a983cf5dfac80e368ce20e77e2211242db9e172596dfa1111f67fb9a17bdb47
7
+ data.tar.gz: 54c7e6900a693254db6e2d462a9b14f0cef5e514581227c2c39b1d13841fea88591f4504037b02edfe6aa1971d3ebdb9e678d735a277d98cebb6df7d372f00fb
@@ -64,7 +64,7 @@ module ReplTypeCompletor
64
64
  in [:gvar, name, scope]
65
65
  scope.global_variables
66
66
  in [:symbol, name]
67
- Symbol.all_symbols.map { _1.inspect[1..] }
67
+ filter_symbol_candidates(Symbol.all_symbols, name, limit: 100)
68
68
  in [:call, name, type, self_call]
69
69
  (self_call ? type.all_methods : type.methods).map(&:to_s) - HIDDEN_METHODS
70
70
  in [:lvar_or_method, name, scope]
@@ -116,6 +116,25 @@ module ReplTypeCompletor
116
116
 
117
117
  private
118
118
 
119
+ def filter_symbol_candidates(symbols, prefix, limit:)
120
+ sym_prefix = ":#{prefix}"
121
+ candidates = symbols.filter_map do |s|
122
+ next unless s.start_with?(prefix) # Fast and inaccurate check before calling inspect
123
+
124
+ inspect = s.inspect
125
+ inspect[1..] if inspect.start_with?(sym_prefix) # Reject `:"a b"` when completing `:a`
126
+ rescue EncodingError
127
+ # ignore
128
+ end
129
+
130
+ if candidates.size > limit
131
+ # min(n) + max(n) is faster than sort and slice
132
+ candidates.min(limit - limit / 2) + candidates.max(limit / 2).reverse
133
+ else
134
+ candidates.sort
135
+ end
136
+ end
137
+
119
138
  def method_doc(type, name)
120
139
  type = type.types.find { _1.all_methods.include? name.to_sym }
121
140
  case type
@@ -229,6 +229,11 @@ module ReplTypeCompletor
229
229
  alias evaluate_class_variable_read_node evaluate_reference_read
230
230
  alias evaluate_instance_variable_read_node evaluate_reference_read
231
231
 
232
+ def evaluate_it_local_variable_read_node(_node, scope)
233
+ # `it` is not a normal local variable. It can be overridden like `tap{p it; it=1}`.
234
+ # Use the name `_1` instead of `it` to avoid conflict.
235
+ scope['_1'] || Types::NIL
236
+ end
232
237
 
233
238
  def evaluate_call_node(node, scope)
234
239
  receiver_type = node.receiver ? evaluate(node.receiver, scope) : scope.self_type
@@ -262,6 +267,8 @@ module ReplTypeCompletor
262
267
  assign_numbered_parameters node.block.parameters.maximum, block_scope, block_args, {}
263
268
  when Prism::BlockParametersNode
264
269
  assign_parameters node.block.parameters.parameters, block_scope, block_args, {}
270
+ when Prism::ItParametersNode
271
+ scope['_1'] = block_args.first || Types::NIL
265
272
  end
266
273
  result = node.block.body ? evaluate(node.block.body, block_scope) : Types::NIL
267
274
  block_scope.merge_jumps
@@ -425,9 +432,14 @@ module ReplTypeCompletor
425
432
 
426
433
  def evaluate_lambda_node(node, scope)
427
434
  local_table = node.locals.to_h { [_1.to_s, Types::OBJECT] }
435
+
436
+ # `it` is not added to local_table because it is not a normal local variable.
437
+ # We need to explicitly add it to the scope.
438
+ local_table['_1'] = Types::OBJECT if node.parameters.is_a?(Prism::ItParametersNode)
439
+
428
440
  block_scope = Scope.new scope, { **local_table, Scope::BREAK_RESULT => nil, Scope::NEXT_RESULT => nil, Scope::RETURN_RESULT => nil }
429
441
  block_scope.conditional do |s|
430
- assign_parameters node.parameters.parameters, s, [], {} if node.parameters&.parameters
442
+ assign_parameters node.parameters.parameters, s, [], {} if node.parameters.is_a?(Prism::ParametersNode) && node.parameters.parameters
431
443
  evaluate node.body, s if node.body
432
444
  end
433
445
  block_scope.merge_jumps
@@ -1133,7 +1145,7 @@ module ReplTypeCompletor
1133
1145
  receiver_vars = receiver.is_a?(Types::InstanceType) ? receiver.params : {}
1134
1146
  free_vars = method.type.free_variables - receiver_vars.keys.to_set
1135
1147
  vars = receiver_vars.merge Types.match_free_variables(free_vars, method_params, given_params)
1136
- if block && method.block
1148
+ if block && method.block && method.block.type.respond_to?(:required_positionals)
1137
1149
  params_type = method.block.type.required_positionals.map do |func_param|
1138
1150
  Types.from_rbs_type func_param.type, receiver, vars
1139
1151
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'rbs'
4
+ require 'rubygems'
4
5
  require 'rbs/cli'
5
6
  require_relative 'methods'
6
7
 
@@ -25,8 +26,27 @@ module ReplTypeCompletor
25
26
  def self.load_rbs_builder
26
27
  @load_started = true
27
28
  loader = RBS::CLI::LibraryOptions.new.loader
28
- loader.add path: Pathname('sig')
29
- @rbs_builder = RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
29
+ sig_path = Pathname('sig')
30
+ loader.add path: sig_path
31
+ expanded_sig_path = sig_path.expand_path.to_s
32
+
33
+ unless File.exist?('rbs_collection.yaml')
34
+ # Load rbs signature from gems. This is a fallback when rbs_collection.yaml is not available.
35
+ Gem.loaded_specs.values.each do |spec|
36
+ gem_sig_path = File.expand_path("#{spec.gem_dir}/sig")
37
+ loader.add(library: spec.name, version: spec.version) if Dir.exist?(gem_sig_path) && expanded_sig_path != gem_sig_path
38
+ end
39
+ end
40
+
41
+ # Hack to make this thread priority lower, not to block the main thread.
42
+ thread_pass_counter = 0
43
+ tracepoint = TracePoint.new(:call) do
44
+ Thread.pass if ((thread_pass_counter += 1) % 10).zero?
45
+ end
46
+ tracepoint.enable do
47
+ env = RBS::Environment.from_loader(loader)
48
+ @rbs_builder = RBS::DefinitionBuilder.new env: env.resolve_type_names
49
+ end
30
50
  rescue LoadError, StandardError => e
31
51
  @rbs_load_error = e
32
52
  nil
@@ -83,7 +103,9 @@ module ReplTypeCompletor
83
103
  methods_with_score = receivers.flat_map do |receiver_type, klass, singleton|
84
104
  method = rbs_search_method klass, method_name, singleton
85
105
  next [] unless method
86
- method.method_types.map do |method_type|
106
+ method.method_types.filter_map do |method_type|
107
+ next unless method_type.type.respond_to?(:required_positionals)
108
+
87
109
  score = 0
88
110
  score += 2 if !!method_type.block == has_block
89
111
  reqs = method_type.type.required_positionals
@@ -317,6 +339,8 @@ module ReplTypeCompletor
317
339
  self_type.transform do |type|
318
340
  if type.is_a?(SingletonType) && type.module_or_class.is_a?(Class)
319
341
  InstanceType.new type.module_or_class
342
+ elsif type.is_a?(InstanceType)
343
+ InstanceType.new type.klass
320
344
  else
321
345
  OBJECT
322
346
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReplTypeCompletor
4
- VERSION = "0.1.7"
4
+ VERSION = "0.1.8"
5
5
  end
@@ -101,6 +101,8 @@ module ReplTypeCompletor
101
101
  [op == '::' ? :call_or_const : :call, name, receiver_type, self_call]
102
102
  when Prism::LocalVariableReadNode, Prism::LocalVariableTargetNode
103
103
  [:lvar_or_method, target_node.name.to_s, calculate_scope.call]
104
+ when Prism::ItLocalVariableReadNode
105
+ [:lvar_or_method, 'it', calculate_scope.call]
104
106
  when Prism::ConstantPathNode, Prism::ConstantPathTargetNode
105
107
  name = target_node.name.to_s
106
108
  if target_node.parent # A::B
@@ -122,8 +124,8 @@ module ReplTypeCompletor
122
124
  end
123
125
 
124
126
  def find_target(node, position)
125
- # Skip because NumberedParametersNode#location gives location of whole block
126
- return if node.is_a? Prism::NumberedParametersNode
127
+ # Skip because location of these nodes gives location of whole block
128
+ return if node.is_a?(Prism::NumberedParametersNode) || node.is_a?(Prism::ItParametersNode)
127
129
 
128
130
  node.compact_child_nodes.each do |n|
129
131
  match = find_target(n, position)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: repl_type_completor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - tompng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-30 00:00:00.000000000 Z
11
+ date: 2024-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prism