repl_type_completor 0.1.7 → 0.1.8

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: 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