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

Returns a new instance of Type.

Signature:

  • -> void



1000
1001
1002
# File 'lib/rbi/type.rb', line 1000

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.

Signature:

  • (Type type1, Type type2, *Type types) -> Type



936
937
938
# File 'lib/rbi/type.rb', line 936

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.

Signature:

  • (Type type1, Type type2, *Type types) -> Type



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

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

.anythingObject

Builds a type that represents T.anything.

Signature:

  • -> Anything



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

def anything
  Anything.new
end

.attached_classObject

Builds a type that represents T.attached_class.

Signature:

  • -> AttachedClass



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

def attached_class
  AttachedClass.new
end

.booleanObject

Builds a type that represents T::Boolean.

Signature:

  • -> Boolean



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

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).

Signature:

  • (Simple type, ?Type? type_parameter) -> ClassOf



917
918
919
# File 'lib/rbi/type.rb', line 917

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[String] or T::Hash[Symbol, Integer].

Signature:

  • (String name, *(Type | Array[Type]) params) -> Generic



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

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.

Signature:

  • (Type type) -> Type



926
927
928
929
# File 'lib/rbi/type.rb', line 926

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

.noreturnObject

Builds a type that represents T.noreturn.

Signature:

  • -> NoReturn



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

def noreturn
  NoReturn.new
end

.parse_node(node) ⇒ Object

Signature:

  • (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

Signature:

  • (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.

Signature:

  • -> Proc



987
988
989
# File 'lib/rbi/type.rb', line 987

def proc
  Proc.new
end

.self_typeObject

Builds a type that represents T.self_type.

Signature:

  • -> SelfType



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

def self_type
  SelfType.new
end

.shape(types = {}) ⇒ Object

Builds a type that represents a shape type like {name: String, age: Integer}.

Signature:

  • (?Hash[(String | Symbol), Type] types) -> Shape



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

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.

Signature:

  • (String name) -> Simple

Raises:

  • (NameError)


850
851
852
853
854
855
# File 'lib/rbi/type.rb', line 850

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[Foo].

Signature:

  • (Type type) -> Class



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

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[Foo].

Signature:

  • (Type type) -> Module



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

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

.tuple(*types) ⇒ Object

Builds a type that represents a tuple type like [String, Integer].

Signature:

  • (*(Type | Array[Type]) types) -> Tuple



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

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

.type_alias(name, aliased_type) ⇒ Object

Builds a type that represents a type alias like MyTypeAlias.

Signature:

  • (String name, Type aliased_type) -> TypeAlias



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

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).

Signature:

  • (Symbol name) -> TypeParameter



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

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

.untypedObject

Builds a type that represents T.untyped.

Signature:

  • -> Untyped



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

def untyped
  Untyped.new
end

.voidObject

Builds a type that represents void.

Signature:

  • -> Void



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

def void
  Void.new
end

Instance Method Details

#==(other) ⇒ Object

This method is abstract.

Signature:

  • (BasicObject) -> bool

Raises:

  • (NotImplementedError)


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

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

#eql?(other) ⇒ Boolean

Signature:

  • (BasicObject other) -> bool

Returns:



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

def eql?(other)
  self == other
end

#hashObject

Signature:

  • -> Integer



1080
1081
1082
# File 'lib/rbi/type.rb', line 1080

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.

type = RBI::Type.simple("String")
type.to_rbi # => "String"
type.nilable.to_rbi # => "::T.nilable(String)"
type.nilable.nilable.to_rbi # => "::T.nilable(String)"

Signature:

  • -> Type



1014
1015
1016
# File 'lib/rbi/type.rb', line 1014

def nilable
  Type.nilable(self)
end

#nilable?Boolean

Returns whether the type is nilable.

Signature:

  • -> bool

Returns:



1041
1042
1043
# File 'lib/rbi/type.rb', line 1041

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.

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"

Signature:

  • -> Type



1029
1030
1031
1032
1033
1034
1035
1036
1037
# File 'lib/rbi/type.rb', line 1029

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.

Signature:

  • -> Type

Raises:

  • (NotImplementedError)


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

def normalize = raise NotImplementedError, "Abstract method called"

#rbs_stringObject

Signature:

  • -> String



1276
1277
1278
1279
1280
# File 'lib/rbi/rbs_printer.rb', line 1276

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.

Signature:

  • -> Type

Raises:

  • (NotImplementedError)


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

def simplify = raise NotImplementedError, "Abstract method called"

#to_rbiObject

This method is abstract.

Signature:

  • -> String

Raises:

  • (NotImplementedError)


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

def to_rbi = raise NotImplementedError, "Abstract method called"

#to_sObject

Signature:

  • -> String



1090
1091
1092
# File 'lib/rbi/type.rb', line 1090

def to_s
  to_rbi
end