Class: RBI::Type Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/rbi/type.rb,
lib/rbi/rbs_printer.rb,
lib/rbi/type_parser.rb,
lib/rbi/type_visitor.rb

Overview

This class is abstract.

The base class for all RBI types.

Defined Under Namespace

Classes: All, Any, Anything, AttachedClass, Boolean, Class, ClassOf, Composite, Error, Generic, Module, Nilable, NoReturn, Proc, SelfType, Shape, Simple, Tuple, TypeAlias, TypeParameter, Untyped, Visitor, Void

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeType

: -> void



993
994
995
# File 'lib/rbi/type.rb', line 993

def initialize
  @nilable = false #: bool
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



929
930
931
# File 'lib/rbi/type.rb', line 929

def all(type1, type2, *types)
  All.new([type1, type2, *types]).simplify
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



938
939
940
# File 'lib/rbi/type.rb', line 938

def any(type1, type2, *types)
  Any.new([type1, type2, *types]).simplify
end

.anythingObject

Builds a type that represents ‘T.anything`. : -> Anything



854
855
856
# File 'lib/rbi/type.rb', line 854

def anything
  Anything.new
end

.attached_classObject

Builds a type that represents ‘T.attached_class`. : -> AttachedClass



860
861
862
# File 'lib/rbi/type.rb', line 860

def attached_class
  AttachedClass.new
end

.booleanObject

Builds a type that represents ‘T::Boolean`. : -> Boolean



866
867
868
# File 'lib/rbi/type.rb', line 866

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



910
911
912
# File 'lib/rbi/type.rb', line 910

def class_of(type, type_parameter = nil)
  ClassOf.new(type, type_parameter)
end

.generic(name, *params) ⇒ Object

Builds a type that represents a generic type like ‘T::Array` or `T::Hash[Symbol, Integer]`. : (String name, *(Type | Array) params) -> Generic



946
947
948
# File 'lib/rbi/type.rb', line 946

def generic(name, *params)
  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



919
920
921
922
# File 'lib/rbi/type.rb', line 919

def nilable(type)
  nilable = Nilable.new(type)
  nilable.simplify
end

.noreturnObject

Builds a type that represents ‘T.noreturn`. : -> NoReturn



872
873
874
# File 'lib/rbi/type.rb', line 872

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
48
49
50
51
# File 'lib/rbi/type_parser.rb', line 26

def parse_node(node)
  case node
  when Prism::ConstantReadNode, Prism::ConstantPathNode
    parse_constant(node)
  when Prism::ConstantWriteNode, Prism::ConstantPathWriteNode
    parse_constant_assignment(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(
      children.first, #: as !nil
    )
  else
    raise Error, "Unexpected node `#{node}`"
  end
end

.parse_string(string) ⇒ Object

: (String string) -> Type

Raises:



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 = node.statements.body.first #: as !nil
  parse_node(node)
end

.procObject

Builds a type that represents a proc type like ‘T.proc.void`. : -> Proc



980
981
982
# File 'lib/rbi/type.rb', line 980

def proc
  Proc.new
end

.self_typeObject

Builds a type that represents ‘T.self_type`. : -> SelfType



878
879
880
# File 'lib/rbi/type.rb', line 878

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



972
973
974
# File 'lib/rbi/type.rb', line 972

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

Raises:

  • (NameError)


843
844
845
846
847
848
# File 'lib/rbi/type.rb', line 843

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



898
899
900
# File 'lib/rbi/type.rb', line 898

def t_class(type)
  Class.new(type)
end

.t_module(type) ⇒ Object

Builds a type that represents the module of another type like ‘T::Module`. : (Type type) -> Module



904
905
906
# File 'lib/rbi/type.rb', line 904

def t_module(type)
  Module.new(type)
end

.tuple(*types) ⇒ Object

Builds a type that represents a tuple type like ‘[String, Integer]`. : (*(Type | Array) types) -> Tuple



966
967
968
# File 'lib/rbi/type.rb', line 966

def tuple(*types)
  Tuple.new(types.flatten)
end

.type_alias(name, aliased_type) ⇒ Object

Builds a type that represents a type alias like ‘MyTypeAlias`. : (String name, Type aliased_type) -> TypeAlias



958
959
960
# File 'lib/rbi/type.rb', line 958

def type_alias(name, aliased_type)
  TypeAlias.new(name, aliased_type)
end

.type_parameter(name) ⇒ Object

Builds a type that represents a type parameter like ‘T.type_parameter(:U)`. : (Symbol name) -> TypeParameter



952
953
954
# File 'lib/rbi/type.rb', line 952

def type_parameter(name)
  TypeParameter.new(name)
end

.untypedObject

Builds a type that represents ‘T.untyped`. : -> Untyped



884
885
886
# File 'lib/rbi/type.rb', line 884

def untyped
  Untyped.new
end

.voidObject

Builds a type that represents ‘void`. : -> Void



890
891
892
# File 'lib/rbi/type.rb', line 890

def void
  Void.new
end

Instance Method Details

#==(other) ⇒ Object

This method is abstract.

: (BasicObject) -> bool

Raises:

  • (NotImplementedError)


1064
# File 'lib/rbi/type.rb', line 1064

def ==(other) = raise NotImplementedError, "Abstract method called"

#eql?(other) ⇒ Boolean

: (BasicObject other) -> bool

Returns:



1067
1068
1069
# File 'lib/rbi/type.rb', line 1067

def eql?(other)
  self == other
end

#hashObject

: -> Integer



1073
1074
1075
# File 'lib/rbi/type.rb', line 1073

def hash
  to_rbi.hash
end

#nilableObject

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



1007
1008
1009
# File 'lib/rbi/type.rb', line 1007

def nilable
  Type.nilable(self)
end

#nilable?Boolean

Returns whether the type is nilable. : -> bool

Returns:



1034
1035
1036
# File 'lib/rbi/type.rb', line 1034

def nilable?
  is_a?(Nilable)
end

#non_nilableObject

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



1022
1023
1024
1025
1026
1027
1028
1029
1030
# File 'lib/rbi/type.rb', line 1022

def non_nilable
  # TODO: Should this logic be moved into a builder method?
  case self
  when Nilable
    type
  else
    self
  end
end

#normalizeObject

This method is abstract.

Returns a normalized version of the type.

Normalized types are meant to be easier to process, not to read. For example, ‘T.any(TrueClass, FalseClass)` instead of `T::Boolean` or `T.any(String, NilClass)` instead of `T.nilable(String)`.

This is the inverse of ‘#simplify`.

: -> Type

Raises:

  • (NotImplementedError)


1048
# File 'lib/rbi/type.rb', line 1048

def normalize = raise NotImplementedError, "Abstract method called"

#rbs_stringObject

: -> String



1261
1262
1263
1264
1265
# File 'lib/rbi/rbs_printer.rb', line 1261

def rbs_string
  p = TypePrinter.new
  p.visit(self)
  p.string
end

#simplifyObject

This method is abstract.

Returns a simplified version of the type.

Simplified types are meant to be easier to read, not to process. For example, ‘T::Boolean` instead of `T.any(TrueClass, FalseClass)` or `T.nilable(String)` instead of `T.any(String, NilClass)`.

This is the inverse of ‘#normalize`.

: -> Type

Raises:

  • (NotImplementedError)


1060
# File 'lib/rbi/type.rb', line 1060

def simplify = raise NotImplementedError, "Abstract method called"

#to_rbiObject

This method is abstract.

: -> String

Raises:

  • (NotImplementedError)


1079
# File 'lib/rbi/type.rb', line 1079

def to_rbi = raise NotImplementedError, "Abstract method called"

#to_sObject

: -> String



1083
1084
1085
# File 'lib/rbi/type.rb', line 1083

def to_s
  to_rbi
end