katakata_irb 0.1.4 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,27 +4,62 @@ require 'rbs/cli'
4
4
  module KatakataIrb; end
5
5
  module KatakataIrb::Types
6
6
  def self.rbs_builder
7
- @rbs_builder ||= RBS::DefinitionBuilder.new(
8
- env: RBS::Environment.from_loader(RBS::CLI::LibraryOptions.new.loader).resolve_type_names
9
- )
7
+ @rbs_builder ||= load_rbs_builder
8
+ end
9
+
10
+ def self.load_rbs_builder
11
+ loader = RBS::CLI::LibraryOptions.new.loader
12
+ loader.add path: Pathname('sig')
13
+ RBS::DefinitionBuilder.new env: RBS::Environment.from_loader(loader).resolve_type_names
14
+ rescue => e
15
+ puts "\nKatakataIRB failed to initialize RBS::DefinitionBuild\n#{e}"
16
+ Object.new
10
17
  end
11
18
 
12
19
  Splat = Struct.new :item
13
20
 
21
+ MODULE_NAME_METHOD = Module.instance_method(:name)
22
+
23
+ def self.class_name_of(klass)
24
+ klass = klass.superclass if klass.singleton_class?
25
+ MODULE_NAME_METHOD.bind_call klass
26
+ end
27
+
14
28
  def self.rbs_search_method(klass, method_name, singleton)
15
29
  klass.ancestors.each do |ancestor|
16
- next unless ancestor.name
17
- type_name = RBS::TypeName(ancestor.name).absolute!
30
+ name = class_name_of ancestor
31
+ next unless name
32
+ type_name = RBS::TypeName(name).absolute!
18
33
  definition = (singleton ? rbs_builder.build_singleton(type_name) : rbs_builder.build_instance(type_name)) rescue nil
19
- method = definition&.methods&.[](method_name)
34
+ method = definition.methods[method_name] if definition
20
35
  return method if method
21
36
  end
22
37
  nil
23
38
  end
24
39
 
40
+ def self.method_return_type(type, method_name)
41
+ receivers = type.types.map do |t|
42
+ case t
43
+ in ProcType
44
+ [t, Proc, false]
45
+ in SingletonType
46
+ [t, t.module_or_class, true]
47
+ in InstanceType
48
+ [t, t.klass, false]
49
+ end
50
+ end
51
+ types = receivers.flat_map do |receiver_type, klass, singleton|
52
+ method = rbs_search_method klass, method_name, singleton
53
+ next [] unless method
54
+ method.method_types.map do |method|
55
+ from_rbs_type(method.type.return_type, receiver_type, {})
56
+ end
57
+ end
58
+ UnionType[*types]
59
+ end
60
+
25
61
  def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block)
26
- types = (type in UnionType) ? type.types : [type]
27
- receivers = types.map do |t|
62
+ receivers = type.types.map do |t|
28
63
  case t
29
64
  in ProcType
30
65
  [t, Proc, false]
@@ -60,8 +95,15 @@ module KatakataIrb::Types
60
95
  given << UnionType[*centers.drop(opts.size)]
61
96
  expected << rest.type
62
97
  end
63
- score += given.zip(expected).count do |t, e|
64
- intersect? t, from_rbs_type(e, receiver_type)
98
+ score += given.zip(expected).sum do |t, e|
99
+ e = from_rbs_type e, receiver_type
100
+ if intersect? t, e
101
+ 1
102
+ elsif (intersect?(STRING, e) && t.methods.include?(:to_str)) || (intersect?(INTEGER, e) && t.methods.include?(:to_int)) || (intersect?(ARRAY, e) && t.methods.include?(:to_ary))
103
+ 0.5
104
+ else
105
+ 0
106
+ end
65
107
  end
66
108
  end
67
109
  [[method_type, given || [], expected || []], score]
@@ -83,14 +125,24 @@ module KatakataIrb::Types
83
125
  intersect.call(InstanceType, &:klass)
84
126
  end
85
127
 
86
- def self.type_from_object(object, max_level: 4)
128
+ def self.type_from_object(object)
129
+ case object
130
+ when Array, Hash, Module
131
+ type_from_object_recursive(object, max_level: 4)
132
+ else
133
+ klass = object.singleton_class rescue object.class
134
+ InstanceType.new klass
135
+ end
136
+ end
137
+
138
+ def self.type_from_object_recursive(object, max_level:)
87
139
  max_level -= 1
88
140
  sample_size = 1000
89
141
  case object
90
142
  when Array
91
143
  values = object.size > sample_size ? object.sample(sample_size) : object
92
144
  if max_level > 0
93
- InstanceType.new Array, { Elem: UnionType[*values.map { type_from_object(_1, max_level: max_level) }] }
145
+ InstanceType.new Array, { Elem: UnionType[*values.map { type_from_object_recursive(_1, max_level: max_level) }] }
94
146
  else
95
147
  InstanceType.new Array, { Elem: UnionType[*values.map(&:class).uniq.map { InstanceType.new _1 }] }
96
148
  end
@@ -98,8 +150,8 @@ module KatakataIrb::Types
98
150
  keys = object.size > sample_size ? object.keys.sample(sample_size) : object.keys
99
151
  values = object.size > sample_size ? object.values.sample(sample_size) : object.values
100
152
  if max_level > 0
101
- key_types = keys.map { type_from_object(_1, max_level: max_level) }
102
- value_types = values.map { type_from_object(_1, max_level: max_level) }
153
+ key_types = keys.map { type_from_object_recursive(_1, max_level: max_level) }
154
+ value_types = values.map { type_from_object_recursive(_1, max_level: max_level) }
103
155
  InstanceType.new Hash, { K: UnionType[*key_types], V: UnionType[*value_types] }
104
156
  else
105
157
  key_types = keys.map(&:class).uniq.map { InstanceType.new _1 }
@@ -123,6 +175,11 @@ module KatakataIrb::Types
123
175
  def all_methods() = methods | Kernel.methods
124
176
  def constants() = @module_or_class.constants
125
177
  def types() = [self]
178
+ def nillable?() = false
179
+ def nonnillable() = self
180
+ def inspect
181
+ "#{module_or_class}.itself"
182
+ end
126
183
  end
127
184
 
128
185
  class InstanceType
@@ -136,6 +193,21 @@ module KatakataIrb::Types
136
193
  def all_methods() = @klass.instance_methods | @klass.private_instance_methods
137
194
  def constants() = []
138
195
  def types() = [self]
196
+ def nillable?() = (@klass == NilClass)
197
+ def nonnillable() = self
198
+ def inspect
199
+ case klass
200
+ when NilClass
201
+ 'nil'
202
+ when TrueClass
203
+ 'true'
204
+ when FalseClass
205
+ 'false'
206
+ else
207
+ params_string = "[#{params.map { "#{_1}: #{_2.inspect}" }.join(', ')}]" unless params.empty?
208
+ "#{klass.name}#{params_string}"
209
+ end
210
+ end
139
211
  end
140
212
 
141
213
  class ProcType
@@ -150,11 +222,14 @@ module KatakataIrb::Types
150
222
  def all_methods() = Proc.instance_methods | Proc.private_instance_methods
151
223
  def constants() = []
152
224
  def types() = [self]
225
+ def nillable?() = (@klass == NilClass)
226
+ def nonnillable() = self
227
+ def inspect() = 'Proc'
153
228
  end
154
229
 
155
230
  NIL = InstanceType.new NilClass
156
231
  OBJECT = InstanceType.new Object
157
- TRUE = InstanceType.new FalseClass
232
+ TRUE = InstanceType.new TrueClass
158
233
  FALSE = InstanceType.new FalseClass
159
234
  SYMBOL = InstanceType.new Symbol
160
235
  STRING = InstanceType.new String
@@ -203,6 +278,14 @@ module KatakataIrb::Types
203
278
  UnionType[*types.map(&block)]
204
279
  end
205
280
 
281
+ def nillable?
282
+ types.any?(&:nillable?)
283
+ end
284
+
285
+ def nonnillable
286
+ UnionType[*types.reject { _1.is_a?(InstanceType) && _1.klass == NilClass }]
287
+ end
288
+
206
289
  def self.[](*types)
207
290
  type = new(*types)
208
291
  if type.types.empty?
@@ -217,15 +300,18 @@ module KatakataIrb::Types
217
300
  def methods() = @types.flat_map(&:methods).uniq
218
301
  def all_methods() = @types.flat_map(&:all_methods).uniq
219
302
  def constants() = @types.flat_map(&:constants).uniq
303
+ def inspect() = @types.map(&:inspect).join(' | ')
220
304
  end
221
305
 
306
+ BOOLEAN = UnionType[TRUE, FALSE]
307
+
222
308
  def self.from_rbs_type(return_type, self_type, extra_vars = {})
223
309
  case return_type
224
310
  when RBS::Types::Bases::Self
225
311
  self_type
226
- when RBS::Types::Bases::Void, RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
312
+ when RBS::Types::Bases::Bottom, RBS::Types::Bases::Nil
227
313
  NIL
228
- when RBS::Types::Bases::Any
314
+ when RBS::Types::Bases::Any, RBS::Types::Bases::Void
229
315
  OBJECT
230
316
  when RBS::Types::Bases::Class
231
317
  self_type.transform do |type|
@@ -238,7 +324,7 @@ module KatakataIrb::Types
238
324
  end
239
325
  UnionType[*types]
240
326
  when RBS::Types::Bases::Bool
241
- UnionType[TRUE, FALSE]
327
+ BOOLEAN
242
328
  when RBS::Types::Bases::Instance
243
329
  self_type.transform do |type|
244
330
  case type
@@ -286,7 +372,7 @@ module KatakataIrb::Types
286
372
  when :int
287
373
  INTEGER
288
374
  when :boolish
289
- UnionType[TRUE, FALSE]
375
+ BOOLEAN
290
376
  when :string
291
377
  STRING
292
378
  else
@@ -332,6 +418,25 @@ module KatakataIrb::Types
332
418
  end
333
419
  in [RBS::Types::Record, InstanceType] if value.klass == Hash
334
420
  # TODO
421
+ in [RBS::Types::Interface,]
422
+ definition = rbs_builder.build_interface rbs_type.name
423
+ convert = {}
424
+ definition.type_params.zip(rbs_type.args).each do |from, arg|
425
+ convert[from] = arg.name if arg.is_a? RBS::Types::Variable
426
+ end
427
+ return if convert.empty?
428
+ ac = {}
429
+ definition.methods.each do |method_name, method|
430
+ return_type = method_return_type value, method_name
431
+ method.defs.each do |method_def|
432
+ interface_return_type = method_def.type.type.return_type
433
+ _match_free_variable convert, interface_return_type, return_type, ac
434
+ end
435
+ end
436
+ convert.each do |from, to|
437
+ values = ac[from]
438
+ (accumulator[to] ||= []).concat values if values
439
+ end
335
440
  else
336
441
  end
337
442
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KatakataIrb
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.6"
5
5
  end
data/sig/katakata_irb.rbs CHANGED
@@ -1,4 +1,7 @@
1
1
  module KatakataIrb
2
2
  VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
3
+ module Completor
4
+ def self.analyze: (code: String, binding?: Binding) -> Array[Symbol | Object | String | true | false]?
5
+ def self.setup: () -> void
6
+ end
4
7
  end
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.4
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - tompng
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-26 00:00:00.000000000 Z
11
+ date: 2023-04-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: irb
@@ -56,6 +56,7 @@ files:
56
56
  - lib/katakata_irb.rb
57
57
  - lib/katakata_irb/completor.rb
58
58
  - lib/katakata_irb/nesting_parser.rb
59
+ - lib/katakata_irb/scope.rb
59
60
  - lib/katakata_irb/type_simulator.rb
60
61
  - lib/katakata_irb/types.rb
61
62
  - lib/katakata_irb/version.rb
@@ -81,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
81
82
  - !ruby/object:Gem::Version
82
83
  version: '0'
83
84
  requirements: []
84
- rubygems_version: 3.4.5
85
+ rubygems_version: 3.4.6
85
86
  signing_key:
86
87
  specification_version: 4
87
88
  summary: IRB with Typed Completion