Class: RBI::Type
- Inherits:
-
Object
- Object
- RBI::Type
- Extended by:
- T::Helpers, T::Sig
- Defined in:
- lib/rbi/type.rb,
lib/rbi/rbs_printer.rb,
lib/rbi/type_parser.rb,
lib/rbi/type_visitor.rb
Overview
The base class for all RBI types.
Direct Known Subclasses
Anything, AttachedClass, Boolean, Class, ClassOf, Composite, Generic, Nilable, NoReturn, Proc, SelfType, Shape, Simple, Tuple, TypeParameter, Untyped, Void
Defined Under Namespace
Classes: All, Any, Anything, AttachedClass, Boolean, Class, ClassOf, Composite, Error, Generic, Nilable, NoReturn, Proc, SelfType, Shape, Simple, Tuple, TypeParameter, Untyped, Visitor, Void
Class Method Summary collapse
-
.all(type1, type2, *types) ⇒ Object
Builds a type that represents an intersection of multiple types like ‘T.all(String, Integer)`.
-
.any(type1, type2, *types) ⇒ Object
Builds a type that represents a union of multiple types like ‘T.any(String, Integer)`.
-
.anything ⇒ Object
Builds a type that represents ‘T.anything`.
-
.attached_class ⇒ Object
Builds a type that represents ‘T.attached_class`.
-
.boolean ⇒ Object
Builds a type that represents ‘T::Boolean`.
-
.class_of(type, type_parameter = nil) ⇒ Object
Builds a type that represents the singleton class of another type like ‘T.class_of(Foo)`.
-
.generic(name, *params) ⇒ Object
Builds a type that represents a generic type like ‘T::Array` or `T::Hash[Symbol, Integer]`.
-
.nilable(type) ⇒ Object
Builds a type that represents a nilable of another type like ‘T.nilable(String)`.
-
.noreturn ⇒ Object
Builds a type that represents ‘T.noreturn`.
-
.parse_node(node) ⇒ Object
: (Prism::Node node) -> Type.
-
.parse_string(string) ⇒ Object
: (String string) -> Type.
-
.proc ⇒ Object
Builds a type that represents a proc type like ‘T.proc.void`.
-
.self_type ⇒ Object
Builds a type that represents ‘T.self_type`.
-
.shape(types = {}) ⇒ Object
Builds a type that represents a shape type like ‘String, age: Integer`.
-
.simple(name) ⇒ Object
Builds a simple type like ‘String` or `::Foo::Bar`.
-
.t_class(type) ⇒ Object
Builds a type that represents the class of another type like ‘T::Class`.
-
.tuple(*types) ⇒ Object
Builds a type that represents a tuple type like ‘[String, Integer]`.
-
.type_parameter(name) ⇒ Object
Builds a type that represents a type parameter like ‘T.type_parameter(:U)`.
-
.untyped ⇒ Object
Builds a type that represents ‘T.untyped`.
-
.void ⇒ Object
Builds a type that represents ‘void`.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#eql?(other) ⇒ Boolean
: (BasicObject other) -> bool.
-
#hash ⇒ Object
: -> Integer.
-
#initialize ⇒ Type
constructor
: -> void.
-
#nilable ⇒ Object
Returns a new type that is ‘nilable` if it is not already.
-
#nilable? ⇒ Boolean
Returns whether the type is nilable.
-
#non_nilable ⇒ Object
Returns the non-nilable version of the type.
-
#rbs_string ⇒ Object
: -> String.
- #to_rbi ⇒ Object
-
#to_s ⇒ Object
: -> String.
Constructor Details
#initialize ⇒ Type
: -> void
695 696 697 |
# File 'lib/rbi/type.rb', line 695 def initialize @nilable = T.let(false, T::Boolean) end |
Class Method Details
.all(type1, type2, *types) ⇒ Object
Builds a type that represents an intersection of multiple types like ‘T.all(String, Integer)`.
Note that this method transforms types such as ‘T.all(String, String)` into `String`, so it may return something other than a `All`. : (Type type1, Type type2, *Type types) -> Type
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
# File 'lib/rbi/type.rb', line 559 def all(type1, type2, *types) types = [type1, type2, *types] # TODO: should we move this logic to a `flatten!`, `normalize!` or `simplify!` method? flattened = types.flatten.flat_map do |type| case type when All type.types else type end end.uniq if flattened.size == 1 T.must(flattened.first) else raise ArgumentError, "RBI::Type.all should have at least 2 types supplied" if flattened.size < 2 All.new(flattened) end end |
.any(type1, type2, *types) ⇒ Object
Builds a type that represents a union of multiple types like ‘T.any(String, Integer)`.
Note that this method transforms types such as ‘T.any(String, NilClass)` into `T.nilable(String)`, so it may return something other than a `Any`. : (Type type1, Type type2, *Type types) -> Type
586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 |
# File 'lib/rbi/type.rb', line 586 def any(type1, type2, *types) types = [type1, type2, *types] # TODO: should we move this logic to a `flatten!`, `normalize!` or `simplify!` method? flattened = types.flatten.flat_map do |type| case type when Any type.types else type end end is_nilable = T.let(false, T::Boolean) types = flattened.filter_map do |type| case type when Simple if type.name == "NilClass" is_nilable = true nil else type end when Nilable is_nilable = true type.type else type end end.uniq has_true_class = types.any? { |type| type.is_a?(Simple) && type.name == "TrueClass" } has_false_class = types.any? { |type| type.is_a?(Simple) && type.name == "FalseClass" } if has_true_class && has_false_class types = types.reject { |type| type.is_a?(Simple) && (type.name == "TrueClass" || type.name == "FalseClass") } types << boolean end type = case types.size when 0 if is_nilable is_nilable = false simple("NilClass") else raise ArgumentError, "RBI::Type.any should have at least 2 types supplied" end when 1 T.must(types.first) else Any.new(types) end if is_nilable nilable(type) else type end end |
.anything ⇒ Object
Builds a type that represents ‘T.anything`. : -> Anything
484 485 486 |
# File 'lib/rbi/type.rb', line 484 def anything Anything.new end |
.attached_class ⇒ Object
Builds a type that represents ‘T.attached_class`. : -> AttachedClass
490 491 492 |
# File 'lib/rbi/type.rb', line 490 def attached_class AttachedClass.new end |
.boolean ⇒ Object
Builds a type that represents ‘T::Boolean`. : -> Boolean
496 497 498 |
# File 'lib/rbi/type.rb', line 496 def boolean Boolean.new end |
.class_of(type, type_parameter = nil) ⇒ Object
Builds a type that represents the singleton class of another type like ‘T.class_of(Foo)`. : (Simple type, ?Type? type_parameter) -> ClassOf
534 535 536 |
# File 'lib/rbi/type.rb', line 534 def class_of(type, type_parameter = nil) ClassOf.new(type, type_parameter) end |
.generic(name, *params) ⇒ Object
651 652 653 |
# File 'lib/rbi/type.rb', line 651 def generic(name, *params) T.unsafe(Generic).new(name, *params.flatten) end |
.nilable(type) ⇒ Object
Builds a type that represents a nilable of another type like ‘T.nilable(String)`.
Note that this method transforms types such as ‘T.nilable(T.untyped)` into `T.untyped`, so it may return something other than a `RBI::Type::Nilable`. : (Type type) -> Type
543 544 545 546 547 548 549 550 551 552 |
# File 'lib/rbi/type.rb', line 543 def nilable(type) # TODO: should we move this logic to a `flatten!`, `normalize!` or `simplify!` method? return type if type.is_a?(Untyped) if type.nilable? type else Nilable.new(type) end end |
.noreturn ⇒ Object
Builds a type that represents ‘T.noreturn`. : -> NoReturn
502 503 504 |
# File 'lib/rbi/type.rb', line 502 def noreturn NoReturn.new end |
.parse_node(node) ⇒ Object
: (Prism::Node node) -> Type
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/rbi/type_parser.rb', line 26 def parse_node(node) case node when Prism::ConstantReadNode, Prism::ConstantPathNode parse_constant(node) when Prism::CallNode parse_call(node) when Prism::ArrayNode parse_tuple(node) when Prism::HashNode, Prism::KeywordHashNode parse_shape(node) when Prism::ParenthesesNode body = node.body raise Error, "Expected exactly 1 child, got 0" unless body.is_a?(Prism::StatementsNode) children = body.body raise Error, "Expected exactly 1 child, got #{children.size}" unless children.size == 1 parse_node(T.must(children.first)) else raise Error, "Unexpected node `#{node}`" end end |
.parse_string(string) ⇒ Object
: (String string) -> Type
10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/rbi/type_parser.rb', line 10 def parse_string(string) result = Prism.parse(string) unless result.success? raise Error, result.errors.map { |e| "#{e.message}." }.join(" ") end node = result.value raise Error, "Expected a type expression, got `#{node.class}`" unless node.is_a?(Prism::ProgramNode) raise Error, "Expected a type expression, got nothing" if node.statements.body.empty? raise Error, "Expected a single type expression, got `#{node.slice}`" if node.statements.body.size > 1 node = T.must(node.statements.body.first) parse_node(node) end |
.proc ⇒ Object
Builds a type that represents a proc type like ‘T.proc.void`. : -> Proc
679 680 681 |
# File 'lib/rbi/type.rb', line 679 def proc Proc.new end |
.self_type ⇒ Object
Builds a type that represents ‘T.self_type`. : -> SelfType
508 509 510 |
# File 'lib/rbi/type.rb', line 508 def self_type SelfType.new end |
.shape(types = {}) ⇒ Object
Builds a type that represents a shape type like ‘String, age: Integer`. : (?Hash[(String | Symbol), Type] types) -> Shape
671 672 673 |
# File 'lib/rbi/type.rb', line 671 def shape(types = {}) Shape.new(types) end |
.simple(name) ⇒ Object
Builds a simple type like ‘String` or `::Foo::Bar`.
It raises a ‘NameError` if the name is not a valid Ruby class identifier. : (String name) -> Simple
473 474 475 476 477 478 |
# File 'lib/rbi/type.rb', line 473 def simple(name) # TODO: should we allow creating the instance anyway and move this to a `validate!` method? raise NameError, "Invalid type name: `#{name}`" unless valid_identifier?(name) Simple.new(name) end |
.t_class(type) ⇒ Object
Builds a type that represents the class of another type like ‘T::Class`. : (Type type) -> Class
528 529 530 |
# File 'lib/rbi/type.rb', line 528 def t_class(type) Class.new(type) end |
.tuple(*types) ⇒ Object
Builds a type that represents a tuple type like ‘[String, Integer]`. : (*(Type | Array) types) -> Tuple
665 666 667 |
# File 'lib/rbi/type.rb', line 665 def tuple(*types) Tuple.new(types.flatten) end |
.type_parameter(name) ⇒ Object
Builds a type that represents a type parameter like ‘T.type_parameter(:U)`. : (Symbol name) -> TypeParameter
657 658 659 |
# File 'lib/rbi/type.rb', line 657 def type_parameter(name) TypeParameter.new(name) end |
.untyped ⇒ Object
Builds a type that represents ‘T.untyped`. : -> Untyped
514 515 516 |
# File 'lib/rbi/type.rb', line 514 def untyped Untyped.new end |
.void ⇒ Object
Builds a type that represents ‘void`. : -> Void
520 521 522 |
# File 'lib/rbi/type.rb', line 520 def void Void.new end |
Instance Method Details
#==(other) ⇒ Object
741 |
# File 'lib/rbi/type.rb', line 741 def ==(other); end |
#eql?(other) ⇒ Boolean
: (BasicObject other) -> bool
744 745 746 |
# File 'lib/rbi/type.rb', line 744 def eql?(other) self == other end |
#hash ⇒ Object
: -> Integer
750 751 752 |
# File 'lib/rbi/type.rb', line 750 def hash to_rbi.hash end |
#nilable ⇒ Object
Returns a new type that is ‘nilable` if it is not already.
If the type is already nilable, it returns itself. “‘ruby type = RBI::Type.simple(“String”) type.to_rbi # => “String” type.nilable.to_rbi # => “T.nilable(String)” type.nilable.nilable.to_rbi # => “T.nilable(String)” “` : -> Type
709 710 711 |
# File 'lib/rbi/type.rb', line 709 def nilable Type.nilable(self) end |
#nilable? ⇒ Boolean
Returns whether the type is nilable. : -> bool
736 737 738 |
# File 'lib/rbi/type.rb', line 736 def nilable? is_a?(Nilable) end |
#non_nilable ⇒ Object
Returns the non-nilable version of the type. If the type is already non-nilable, it returns itself. If the type is nilable, it returns the inner type.
“‘ruby type = RBI::Type.nilable(RBI::Type.simple(“String”)) type.to_rbi # => “T.nilable(String)” type.non_nilable.to_rbi # => “String” type.non_nilable.non_nilable.to_rbi # => “String” “` : -> Type
724 725 726 727 728 729 730 731 732 |
# File 'lib/rbi/type.rb', line 724 def non_nilable # TODO: Should this logic be moved into a builder method? case self when Nilable type else self end end |
#rbs_string ⇒ Object
: -> String
1136 1137 1138 1139 1140 |
# File 'lib/rbi/rbs_printer.rb', line 1136 def rbs_string p = TypePrinter.new p.visit(self) p.string end |
#to_rbi ⇒ Object
755 |
# File 'lib/rbi/type.rb', line 755 def to_rbi; end |
#to_s ⇒ Object
: -> String
759 760 761 |
# File 'lib/rbi/type.rb', line 759 def to_s to_rbi end |