module RBS # `TypeAliasRegularity` validates if a type alias is regular or not. # # Generic and recursive type alias cannot be polymorphic in their definitions. # # ```rbs # type foo[T] = Integer # | foo[T]? # Allowed. The type argument of `foo` doesn't change. # # type bar[T] = Integer # | foo[T] # | foo[Array[T]] # Allowed. There are two type arguments `T` and `Array[T]` of `foo`, but it's not definition of `foo`. # # type baz[T] = Integer # | baz[Array[T]] # Error. Recursive definition of `baz` has different type argument from the definition. # ``` # # The `#nonregular?` method can be used to test if given type name is regular or not. # # ```rb # validator = RBS::TypeAliasRegularity.validate(env: env) # # validator.nonregular?(TypeName("::foo")) # => nil # validator.nonregular?(TypeName("::bar")) # => nil # validator.nonregular?(TypeName("::baz")) # => TypeAliasRegularity::Diagnostic # ``` # # A special case is when the type argument is `untyped`. # # ```rbs # type foo[T] = Integer | foo[untyped] # This is allowed. # ``` # class TypeAliasRegularity attr_reader env: Environment attr_reader builder: DefinitionBuilder # Diagnostics of each type aliases. # The type names are normalized. # attr_reader diagnostics: Hash[TypeName, Diagnostic] # `Diagnostic` represents an non-regular type alias declaration error. # It consists of the name of the alias type and a type on which the nonregularity is detected. # # ```rbs # type t[T] = Integer | t[T?] # ``` # # The type `t` is nonregular because it contains `t[T?]` on it's right hand side. # # ``` # diagnostic = validator.nonregular?(TypeName("::t")) # diagnostic.type_name # => TypeName("::t") # diagnostic.nonregular_type # => t[T?] # ``` # class Diagnostic attr_reader type_name: TypeName attr_reader nonregular_type: Types::Alias def initialize: (type_name: TypeName, nonregular_type: Types::Alias) -> void end # Returns new instance which already run `#validate`. # def self.validate: (env: Environment) -> TypeAliasRegularity def initialize: (env: Environment) -> void # Returns `Diagnostic` instance if the alias type is nonregular. # Regurns `nil` if the alias type is regular. # # Normalizes the given type name automatically. # def nonregular?: (TypeName) -> Diagnostic? def validate: () -> void private def validate_alias_type: (Types::Alias, Set[TypeName], Hash[TypeName, Types::Alias]) -> void # Returns alias type for given type name, if the alias is generic. # Returns nil if the type alias is not generic. # def build_alias_type: (TypeName) -> Types::Alias? def compatible_args?: (Array[Types::t], Array[Types::t]) -> boolish def each_alias_type: (Types::t) { (Types::Alias) -> void } -> void # Yields set of normalized type names def each_mutual_alias_defs: () { (Set[TypeName]) -> void } -> void end end