88module ReplTypeCompletor
99 module Types
1010 OBJECT_TO_TYPE_SAMPLE_SIZE = 50
11+ EXPANSION_NESTING_LIMIT = 3
1112
1213 singleton_class . attr_reader :rbs_builder , :rbs_load_error
1314
@@ -75,6 +76,11 @@ def self.rbs_absolute_type_name(name)
7576 def self . rbs_search_method ( klass , method_name , singleton )
7677 return unless rbs_builder
7778
79+ if klass . is_a? InterfaceType
80+ definition = klass . definition
81+ return definition && definition . methods [ method_name ]
82+ end
83+
7884 klass . ancestors . each do |ancestor |
7985 next unless ( name = Methods ::MODULE_NAME_METHOD . bind_call ( ancestor ) )
8086
@@ -93,6 +99,8 @@ def self.method_return_type(type, method_name)
9399 [ t , t . module_or_class , true ]
94100 in InstanceType
95101 [ t , t . klass , false ]
102+ in InterfaceType
103+ [ t , t , false ]
96104 end
97105 end
98106 types = receivers . flat_map do |receiver_type , klass , singleton |
@@ -115,6 +123,8 @@ def self.accessor_method_return_type(type, method_name)
115123 t . module_or_class
116124 in InstanceType
117125 t . instances
126+ in InterfaceType
127+ nil
118128 end
119129 end . flatten
120130 instances = instances . sample ( OBJECT_TO_TYPE_SAMPLE_SIZE ) if instances . size > OBJECT_TO_TYPE_SAMPLE_SIZE
@@ -136,6 +146,8 @@ def self.rbs_methods(type, method_name, args_types, kwargs_type, has_block)
136146 [ t , t . module_or_class , true ]
137147 in InstanceType
138148 [ t , t . klass , false ]
149+ in InterfaceType
150+ [ t , t , false ]
139151 end
140152 end
141153 has_splat = args_types . include? ( nil )
@@ -193,7 +205,14 @@ def self.intersect?(a, b)
193205 end
194206
195207 aa , bb = [ atypes , btypes ] . map { |types | ( types [ InstanceType ] || [ ] ) . map ( &:klass ) }
196- ( aa . flat_map ( &:ancestors ) & bb ) . any?
208+ return true if ( aa . flat_map ( &:ancestors ) & bb ) . any?
209+
210+ [ [ atypes [ InterfaceType ] , b ] , [ btypes [ InterfaceType ] , a ] ] . any? do |interfaces , other |
211+ interfaces &.any? do |interface |
212+ methods = interface . methods
213+ !methods . empty? && other . types . any? { |t | ( methods - t . methods ) . empty? }
214+ end
215+ end
197216 end
198217
199218 def self . type_from_object ( object )
@@ -340,6 +359,38 @@ def inspect_without_params
340359 end
341360 end
342361
362+ class InterfaceType
363+ attr_reader :name , :args
364+
365+ def initialize ( name , args = [ ] )
366+ @name = name
367+ @args = args
368+ end
369+
370+ def definition
371+ return @definition if defined? ( @definition )
372+
373+ @definition = ( Types . rbs_builder &.build_interface ( @name ) rescue nil )
374+ end
375+
376+ def transform ( ) = yield ( self )
377+ def methods ( ) = definition ? definition . methods . keys : [ ]
378+ def all_methods ( ) = methods
379+
380+ def named_params
381+ definition ? definition . type_params . zip ( @args ) . to_h . compact : { }
382+ end
383+
384+ def constants ( ) = [ ]
385+ def types ( ) = [ self ]
386+ def nillable? ( ) = false
387+ def nonnillable ( ) = self
388+
389+ def inspect
390+ args . empty? ? name . name . to_s : "#{ name . name } [#{ args . map ( &:inspect ) . join ( ', ' ) } ]"
391+ end
392+ end
393+
343394 NIL = InstanceType . new NilClass
344395 OBJECT = InstanceType . new Object
345396 TRUE = InstanceType . new TrueClass
@@ -364,6 +415,7 @@ class UnionType
364415 def initialize ( *types )
365416 @types = [ ]
366417 singleton_types = [ ]
418+ interface_types = { }
367419 instance_types = { }
368420 collect = -> type do
369421 case type
@@ -377,10 +429,12 @@ def initialize(*types)
377429 end
378430 in SingletonType
379431 singleton_types << type
432+ in InterfaceType
433+ interface_types [ [ type . name , type . args ] ] ||= type
380434 end
381435 end
382436 types . each ( &collect )
383- @types = singleton_types . uniq + instance_types . map do |klass , ( params , instances ) |
437+ @types = singleton_types . uniq + interface_types . values + instance_types . map do |klass , ( params , instances ) |
384438 params = params . map { |v | UnionType [ *v ] }
385439 InstanceType . new ( klass , params , instances )
386440 end
@@ -422,7 +476,15 @@ def self.array_of(*types)
422476 InstanceType . new ( Array , [ type ] )
423477 end
424478
425- def self . from_rbs_type ( return_type , self_type , extra_vars = { } )
479+ # Alias may validly recurse through type args (`type json = Integer | Array[json]`)
480+ # and can expand exponentially (`type b = a | [a]` chains), so expansion is depth limited.
481+ def self . expand_alias_type ( rbs_type , nesting )
482+ return if nesting >= EXPANSION_NESTING_LIMIT
483+
484+ rbs_builder . expand_alias2 rbs_type . name , rbs_type . args rescue nil
485+ end
486+
487+ def self . from_rbs_type ( return_type , self_type , extra_vars = { } , nesting = 0 )
426488 case return_type
427489 when RBS ::Types ::Bases ::Self
428490 self_type
@@ -434,12 +496,13 @@ def self.from_rbs_type(return_type, self_type, extra_vars = {})
434496 self_type . transform do |type |
435497 case type
436498 in SingletonType
437- InstanceType . new ( self_type . module_or_class . is_a? ( Class ) ? Class : Module )
499+ InstanceType . new ( type . module_or_class . is_a? ( Class ) ? Class : Module )
438500 in InstanceType
439501 SingletonType . new type . klass
502+ in InterfaceType
503+ CLASS
440504 end
441505 end
442- UnionType [ *types ]
443506 when RBS ::Types ::Bases ::Bool
444507 BOOLEAN
445508 when RBS ::Types ::Bases ::Instance
@@ -454,11 +517,11 @@ def self.from_rbs_type(return_type, self_type, extra_vars = {})
454517 end
455518 when RBS ::Types ::Union , RBS ::Types ::Intersection
456519 # Intersection is unsupported. fallback to union type
457- UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars } ]
520+ UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars , nesting } ]
458521 when RBS ::Types ::Proc
459522 PROC
460523 when RBS ::Types ::Tuple
461- elem = UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars } ]
524+ elem = UnionType [ *return_type . types . map { from_rbs_type _1 , self_type , extra_vars , nesting } ]
462525 InstanceType . new ( Array , [ elem ] )
463526 when RBS ::Types ::Record
464527 InstanceType . new ( Hash , [ SYMBOL , OBJECT ] )
@@ -467,37 +530,28 @@ def self.from_rbs_type(return_type, self_type, extra_vars = {})
467530 when RBS ::Types ::Variable
468531 if extra_vars . key? return_type . name
469532 extra_vars [ return_type . name ]
470- elsif self_type . is_a? InstanceType
533+ elsif self_type . is_a? ( InstanceType ) || self_type . is_a? ( InterfaceType )
471534 self_type . named_params [ return_type . name ] || OBJECT
472535 elsif self_type . is_a? UnionType
473536 types = self_type . types . filter_map do |t |
474- t . named_params [ return_type . name ] if t . is_a? InstanceType
537+ t . named_params [ return_type . name ] if t . is_a? ( InstanceType ) || t . is_a? ( InterfaceType )
475538 end
476539 UnionType [ *types ]
477540 else
478541 OBJECT
479542 end
480543 when RBS ::Types ::Optional
481- UnionType [ from_rbs_type ( return_type . type , self_type , extra_vars ) , NIL ]
544+ UnionType [ from_rbs_type ( return_type . type , self_type , extra_vars , nesting ) , NIL ]
482545 when RBS ::Types ::Alias
483- case return_type . name . name
484- when :int
485- INTEGER
486- when :boolish
487- BOOLEAN
488- when :string
489- STRING
490- else
491- # TODO: ???
492- OBJECT
493- end
546+ expanded = expand_alias_type ( return_type , nesting )
547+ expanded ? from_rbs_type ( expanded , self_type , extra_vars , nesting + 1 ) : OBJECT
494548 when RBS ::Types ::Interface
495- # unimplemented
496- OBJECT
549+ args = return_type . args . map { from_rbs_type _1 , self_type , extra_vars , nesting }
550+ InterfaceType . new return_type . name , args
497551 when RBS ::Types ::ClassInstance
498552 klass = return_type . name . to_namespace . path . reduce ( Object ) { _1 . const_get _2 }
499553 if return_type . args
500- params = return_type . args . map { from_rbs_type _1 , self_type , extra_vars }
554+ params = return_type . args . map { from_rbs_type _1 , self_type , extra_vars , nesting }
501555 end
502556 InstanceType . new ( klass , params || [ ] )
503557 else
@@ -517,24 +571,24 @@ def self.match_free_variables(vars, types, values)
517571 accumulator . transform_values { UnionType [ *_1 ] }
518572 end
519573
520- def self . _match_free_variable ( vars , rbs_type , value , accumulator )
574+ def self . _match_free_variable ( vars , rbs_type , value , accumulator , nesting = 0 )
521575 case [ rbs_type , value ]
522576 in [ RBS ::Types ::Variable ,]
523577 ( accumulator [ rbs_type . name ] ||= [ ] ) << value if vars . include? rbs_type . name
524578 in [ RBS ::Types ::ClassInstance , InstanceType ]
525579 names = rbs_builder . build_singleton ( rbs_type . name ) . type_params
526580 names . zip ( rbs_type . args ) . each do |name , arg |
527581 v = value . named_params [ name ]
528- _match_free_variable vars , arg , v , accumulator if v
582+ _match_free_variable vars , arg , v , accumulator , nesting if v
529583 end
530584 in [ RBS ::Types ::Tuple , InstanceType ] if value . klass == Array
531585 v = value . params [ 0 ]
532586 rbs_type . types . each do |t |
533- _match_free_variable vars , t , v , accumulator
587+ _match_free_variable vars , t , v , accumulator , nesting
534588 end
535589 in [ RBS ::Types ::Record , InstanceType ] if value . klass == Hash
536590 # TODO
537- in [ RBS ::Types ::Interface ,]
591+ in [ RBS ::Types ::Interface ,] if nesting < EXPANSION_NESTING_LIMIT
538592 definition = rbs_builder . build_interface rbs_type . name
539593 convert = { }
540594 definition . type_params . zip ( rbs_type . args ) . each do |from , arg |
@@ -546,13 +600,20 @@ def self._match_free_variable(vars, rbs_type, value, accumulator)
546600 return_type = method_return_type value , method_name
547601 method . defs . each do |method_def |
548602 interface_return_type = method_def . type . type . return_type
549- _match_free_variable convert , interface_return_type , return_type , ac
603+ _match_free_variable convert , interface_return_type , return_type , ac , nesting + 1
550604 end
551605 end
552606 convert . each do |from , to |
553607 values = ac [ from ]
554608 ( accumulator [ to ] ||= [ ] ) . concat values if values
555609 end
610+ in [ RBS ::Types ::Union ,]
611+ rbs_type . types . each do |t |
612+ _match_free_variable vars , t , value , accumulator , nesting
613+ end
614+ in [ RBS ::Types ::Alias ,]
615+ expanded = expand_alias_type ( rbs_type , nesting )
616+ _match_free_variable vars , expanded , value , accumulator , nesting + 1 if expanded
556617 else
557618 end
558619 end
0 commit comments