diff --git a/lib/rbs/definition_builder.rb b/lib/rbs/definition_builder.rb index 44f572141..4aa7f845e 100644 --- a/lib/rbs/definition_builder.rb +++ b/lib/rbs/definition_builder.rb @@ -753,12 +753,14 @@ def expand_alias(type_name) end def expand_alias1(type_name) + type_name = env.normalize_type_name(type_name) entry = env.type_alias_decls[type_name] or raise "Unknown alias name: #{type_name}" as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) } expand_alias2(type_name, as) end def expand_alias2(type_name, args) + type_name = env.normalize_type_name(type_name) entry = env.type_alias_decls[type_name] or raise "Unknown alias name: #{type_name}" ensure_namespace!(type_name.namespace, location: entry.decl.location) @@ -811,9 +813,8 @@ def validate_type_presence(type) end def validate_type_name(name, location) - name = name.absolute! - - return if env.type_name?(name) + name = name.absolute! unless name.absolute? + return if env.type_name?(env.normalize_type_name(name)) raise NoTypeFoundError.new(type_name: name, location: location) end diff --git a/lib/rbs/environment.rb b/lib/rbs/environment.rb index 691f75c56..32c865cdb 100644 --- a/lib/rbs/environment.rb +++ b/lib/rbs/environment.rb @@ -275,53 +275,96 @@ def constant_entry(type_name) class_entry(type_name) || module_entry(type_name) || constant_decls[type_name] end + def normalize_type_name?(name) + if name.class? + normalize_module_name?(name) + else + unless name.namespace.empty? + parent = name.namespace.to_type_name + parent = normalize_module_name?(parent) + return parent unless parent + + TypeName.new(namespace: parent.to_namespace, name: name.name) + else + name + end + end + end + + def normalize_type_name!(name) + result = normalize_type_name?(name) + + case result + when TypeName + result + when false + raise "Type name `#{name}` cannot be normalized because it's a cyclic definition" + when nil + raise "Type name `#{name}` cannot be normalized because of unknown type name in the path" + end + end + + def normalized_type_name?(type_name) + case + when type_name.interface? + interface_decls.key?(type_name) + when type_name.class? + class_decls.key?(type_name) + when type_name.alias? + type_alias_decls.key?(type_name) + else + false + end + end + + def normalized_type_name!(name) + normalized_type_name?(name) or raise "Normalized type name is expected but given `#{name}`, which is normalized to `#{normalize_type_name?(name)}`" + name + end + + def normalize_type_name(name) + normalize_type_name?(name) || name + end + def normalize_module_name(name) normalize_module_name?(name) or name end def normalize_module_name?(name) raise "Class/module name is expected: #{name}" unless name.class? - name = name.absolute! if name.relative! + name = name.absolute! unless name.absolute? if @normalize_module_name_cache.key?(name) return @normalize_module_name_cache[name] end + unless name.namespace.empty? + parent = name.namespace.to_type_name + if normalized_parent = normalize_module_name?(parent) + type_name = TypeName.new(namespace: normalized_parent.to_namespace, name: name.name) + else + @normalize_module_name_cache[name] = nil + return + end + else + type_name = name + end + @normalize_module_name_cache[name] = false - entry = constant_entry(name) - case entry - when ClassEntry, ModuleEntry - @normalize_module_name_cache[name] = entry.name - entry.name + entry = constant_entry(type_name) - when ClassAliasEntry, ModuleAliasEntry - old_name = entry.decl.old_name - if old_name.namespace.empty? - @normalize_module_name_cache[name] = normalize_module_name?(old_name) + normalized_type_name = + case entry + when ClassEntry, ModuleEntry + type_name + when ClassAliasEntry, ModuleAliasEntry + normalize_module_name?(entry.decl.old_name) else - parent = old_name.namespace.to_type_name - - if normalized_parent = normalize_module_name?(parent) - @normalize_module_name_cache[name] = - if normalized_parent == parent - normalize_module_name?(old_name) - else - normalize_module_name?( - TypeName.new(name: old_name.name, namespace: normalized_parent.to_namespace) - ) - end - else - @normalize_module_name_cache[name] = nil - end + nil end - when ConstantEntry - raise "#{name} is a constant name" - - else - @normalize_module_name_cache[name] = nil - end + @normalize_module_name_cache[name] = normalized_type_name end def insert_decl(decl, outer:, namespace:) diff --git a/lib/rbs/errors.rb b/lib/rbs/errors.rb index dfdc95732..84cba18cc 100644 --- a/lib/rbs/errors.rb +++ b/lib/rbs/errors.rb @@ -192,7 +192,8 @@ def location end def self.check!(super_decl, env:) - return if env.class_decl?(super_decl.name) || env.class_alias?(super_decl.name) + super_name = env.normalize_type_name(super_decl.name) + return if env.class_decl?(super_name) || env.class_alias?(super_name) raise new(super_decl) end @@ -212,9 +213,8 @@ def initialize(type_name:, location:) end def self.check!(self_type, env:) - type_name = self_type.name - - (env.module_name?(type_name) || env.interface_name?(type_name)) or raise new(type_name: type_name, location: self_type.location) + self_name = env.normalize_type_name(self_type.name) + (env.module_name?(self_name) || env.interface_name?(self_name)) or raise new(type_name: self_type.name, location: self_type.location) end end diff --git a/lib/rbs/resolver/type_name_resolver.rb b/lib/rbs/resolver/type_name_resolver.rb index 5e3a348ab..8b71f4b2e 100644 --- a/lib/rbs/resolver/type_name_resolver.rb +++ b/lib/rbs/resolver/type_name_resolver.rb @@ -5,10 +5,12 @@ module Resolver class TypeNameResolver attr_reader :all_names attr_reader :cache + attr_reader :env def initialize(env) @all_names = Set[] @cache = {} + @env = env all_names.merge(env.class_decls.keys) all_names.merge(env.interface_decls.keys) @@ -35,7 +37,10 @@ def resolve(type_name, context:) if head if tail - has_name?(tail.with_prefix(head.to_namespace)) + absolute_name = tail.with_prefix(head.to_namespace) + if env.normalize_type_name?(absolute_name) + absolute_name + end else head end diff --git a/lib/rbs/type_alias_dependency.rb b/lib/rbs/type_alias_dependency.rb index 0e1ef6175..7930c2165 100644 --- a/lib/rbs/type_alias_dependency.rb +++ b/lib/rbs/type_alias_dependency.rb @@ -20,7 +20,7 @@ def circular_definition?(alias_name) # Construct transitive closure, if not constructed already transitive_closure() unless @dependencies - # Check for recursive type alias + alias_name = env.normalize_type_name!(alias_name) @dependencies[alias_name][alias_name] end @@ -49,6 +49,16 @@ def transitive_closure end end + def direct_dependencies_of(name) + name = env.normalize_type_name!(name) + @direct_dependencies[name] + end + + def dependencies_of(name) + name = env.normalize_type_name!(name) + @dependencies[name].each_key.to_set + end + private # Constructs directed graph recursively @@ -61,7 +71,7 @@ def direct_dependency(type, result = Set[]) end when RBS::Types::Alias # Append type name if the type is an alias - result << type.name + result << env.normalize_type_name(type.name) end result diff --git a/lib/rbs/type_alias_regularity.rb b/lib/rbs/type_alias_regularity.rb index a6af16bc8..a891432ec 100644 --- a/lib/rbs/type_alias_regularity.rb +++ b/lib/rbs/type_alias_regularity.rb @@ -37,10 +37,12 @@ def validate end def validate_alias_type(alias_type, names, types) - if names.include?(alias_type.name) - if ex_type = types[alias_type.name] + alias_name = env.normalize_type_name?(alias_type.name) or return + + if names.include?(alias_name) + if ex_type = types[alias_name] unless compatible_args?(ex_type.args, alias_type.args) - diagnostics[alias_type.name] ||= + diagnostics[alias_name] ||= Diagnostic.new(type_name: alias_type.name, nonregular_type: alias_type) end @@ -49,7 +51,7 @@ def validate_alias_type(alias_type, names, types) types[alias_type.name] = alias_type end - expanded = builder.expand_alias2(alias_type.name, alias_type.args) + expanded = builder.expand_alias2(alias_name, alias_type.args) each_alias_type(expanded) do |at| validate_alias_type(at, names, types) end @@ -75,22 +77,27 @@ def compatible_args?(args1, args2) end def nonregular?(type_name) - diagnostics[type_name] + diagnostics[env.normalize_type_name!(type_name)] end def each_mutual_alias_defs(&block) - # @type var each_node: TSort::_EachNode[TypeName] - each_node = __skip__ = -> (&block) do + # @type var each_node: ^() { (TypeName) -> void } -> void + each_node = -> (&block) do env.type_alias_decls.each_value do |decl| - block[decl.name] + if normalized = env.normalize_type_name?(decl.name) + block[normalized] + end end end - # @type var each_child: TSort::_EachChild[TypeName] - each_child = __skip__ = -> (name, &block) do + + # @type var each_child: ^(TypeName) { (TypeName) -> void } -> void + each_child = -> (name, &block) do if env.type_alias_decls.key?(name) type = builder.expand_alias1(name) each_alias_type(type) do |ty| - block[ty.name] + if normalized = env.normalize_type_name?(ty.name) + block[normalized] + end end end end diff --git a/lib/rbs/validator.rb b/lib/rbs/validator.rb index f17af0fa9..833836ae8 100644 --- a/lib/rbs/validator.rb +++ b/lib/rbs/validator.rb @@ -12,9 +12,9 @@ def initialize(env:, resolver:) @definition_builder = DefinitionBuilder.new(env: env) end - def absolute_type(type, context:) + def absolute_type(type, context:, &block) type.map_type_name do |type_name, _, type| - resolver.resolve(type_name, context: context) || yield(type) + resolver.resolve(type_name, context: context) || (block ? yield(type) : type_name) end end @@ -22,33 +22,34 @@ def absolute_type(type, context:) def validate_type(type, context:) case type when Types::ClassInstance, Types::Interface, Types::Alias - # @type var type: Types::ClassInstance | Types::Interface | Types::Alias - if type.name.namespace.relative? - type = _ = absolute_type(type, context: context) do |_| - NoTypeFoundError.check!(type.name.absolute!, env: env, location: type.location) - end - end + type = absolute_type(type, context: context) #: Types::ClassInstance | Types::Interface | Types::Alias definition_builder.validate_type_name(type.name, type.location) - type_params = case type - when Types::ClassInstance - entry = env.normalized_module_class_entry(type.name) or raise - entry.type_params - when Types::Interface - env.interface_decls[type.name].decl.type_params - when Types::Alias - env.type_alias_decls[type.name].decl.type_params - end - - InvalidTypeApplicationError.check!( - type_name: type.name, - args: type.args, - params: type_params.each.map(&:name), - location: type.location - ) + normalized_type_name = env.normalize_type_name?(type.name) + + if normalized_type_name + type_params = + case type + when Types::ClassInstance + entry = env.class_decls[normalized_type_name] or raise + entry.type_params + when Types::Interface + env.interface_decls[normalized_type_name].decl.type_params + when Types::Alias + env.type_alias_decls[normalized_type_name].decl.type_params + end + + InvalidTypeApplicationError.check!( + type_name: type.name, + args: type.args, + params: type_params.each.map(&:name), + location: type.location + ) + end when Types::ClassSingleton + type = absolute_type(type, context: context) #: Types::ClassSingleton definition_builder.validate_type_presence(type) end @@ -115,14 +116,14 @@ def validate_method_definition(method_def, type_name:) end def validate_type_params(params, type_name: , method_name: nil, location:) - # @type var each_node: TSort::_EachNode[Symbol] - each_node = __skip__ = -> (&block) do + # @type var each_node: ^() { (Symbol) -> void } -> void + each_node = -> (&block) do params.each do |param| block[param.name] end end - # @type var each_child: TSort::_EachChild[Symbol] - each_child = __skip__ = -> (name, &block) do + # @type var each_child: ^(Symbol) { (Symbol) -> void } -> void + each_child = -> (name, &block) do if param = params.find {|p| p.name == name } if b = param.upper_bound b.free_variables.each do |tv| diff --git a/lib/rbs/variance_calculator.rb b/lib/rbs/variance_calculator.rb index 2a42c5b14..ba033ea84 100644 --- a/lib/rbs/variance_calculator.rb +++ b/lib/rbs/variance_calculator.rb @@ -108,8 +108,11 @@ def in_inherit(name:, args:, variables:) end def in_type_alias(name:) + env.normalized_type_name!(name) + decl = env.type_alias_decls[name].decl or raise variables = decl.type_params.each.map(&:name) + Result.new(variables: variables).tap do |result| type(decl.type, result: result, context: :covariant) end @@ -129,30 +132,30 @@ def type(type, result:, context:) end end when Types::ClassInstance, Types::Interface, Types::Alias - NoTypeFoundError.check!(type.name, - env: env, - location: type.location) - - type_params = case type - when Types::ClassInstance - env.class_decls[env.normalize_module_name(type.name)].type_params - when Types::Interface - env.interface_decls[type.name].decl.type_params - when Types::Alias - env.type_alias_decls[type.name].decl.type_params - end - - type.args.each.with_index do |ty, i| - if var = type_params[i] - case var.variance - when :invariant - type(ty, result: result, context: :invariant) - when :covariant - type(ty, result: result, context: context) - when :contravariant - type(ty, result: result, context: negate(context)) + if type_name = env.normalize_type_name?(type.name) + type_params = case type + when Types::ClassInstance + env.class_decls[type_name].type_params + when Types::Interface + env.interface_decls[type_name].decl.type_params + when Types::Alias + env.type_alias_decls[type_name].decl.type_params + end + + type.args.each.with_index do |ty, i| + if var = type_params[i] + case var.variance + when :invariant + type(ty, result: result, context: :invariant) + when :covariant + type(ty, result: result, context: context) + when :contravariant + type(ty, result: result, context: negate(context)) + end end end + else + raise NoTypeFoundError.new(type_name: type.name, location: type.location) end when Types::Proc function(type.type, result: result, context: context) diff --git a/sig/definition_builder.rbs b/sig/definition_builder.rbs index e2b6f3e53..cc177b9e0 100644 --- a/sig/definition_builder.rbs +++ b/sig/definition_builder.rbs @@ -71,12 +71,16 @@ module RBS # Assumes the type names are already resolved. # Raises NoTypeFoundError in case of failure. # + # Normalizes type names in the given type automatically. + # def validate_type_presence: (Types::t) -> void # Validates presence of an absolute type name # # Raises NoTypeFoundError in case of error. # + # Normalizes the given type name automatically. + # def validate_type_name: (TypeName, Location[untyped, untyped]?) -> void # Returns a new DefinitionBuilder with updated Environment, AncestorBuilder, and exceptions diff --git a/sig/environment.rbs b/sig/environment.rbs index 66ec574ef..cb8555c82 100644 --- a/sig/environment.rbs +++ b/sig/environment.rbs @@ -224,6 +224,33 @@ module RBS # def normalize_module_name: (TypeName) -> TypeName + # Returns a normalized module/class name or a type name with a normalized namespace + # + # * Calls `#absolute!` for relative module names + # * Returns `nil` if the typename cannot be found + # * Returns `false` if the name is cyclic + # + def normalize_type_name?: (TypeName) -> (TypeName | nil | false) + + # Normalize the type name or raises an error + # + def normalize_type_name!: (TypeName) -> TypeName + + # Returns a normalized module/class name or a type name with a normalized namespace + # + # * Calls `#absolute!` for relative module names + # * Returns the typename itself if the name cannot be normalized + # + def normalize_type_name: (TypeName) -> TypeName + + # Returns `true` if given type name is normalized + # + def normalized_type_name?: (TypeName) -> bool + + # Returns the given type name if it's normalized, or raises + # + def normalized_type_name!: (TypeName) -> TypeName + # Runs generics type params validation over each class definitions def validate_type_params: () -> void diff --git a/sig/errors.rbs b/sig/errors.rbs index 6e430c316..ed8fc9a89 100644 --- a/sig/errors.rbs +++ b/sig/errors.rbs @@ -82,7 +82,7 @@ module RBS class NoTypeFoundError < DefinitionError include DetailedMessageable - + attr_reader type_name: TypeName attr_reader location: Location[untyped, untyped]? @@ -108,6 +108,8 @@ module RBS def initialize: (type_name: TypeName, location: Location[untyped, untyped]?) -> void + # The type name in `self` is automatically normalized + # def self.check!: (AST::Declarations::Module::Self, env: Environment) -> void end @@ -177,7 +179,7 @@ module RBS def type_name: () -> TypeName def qualified_method_name: () -> String - + def location: () -> AST::Members::Mixin::loc? end @@ -212,7 +214,7 @@ module RBS attr_reader members: Array[AST::Members::MethodDefinition] def initialize: (type_name: TypeName, method_name: Symbol, kind: :instance | :singleton, members: Array[AST::Members::MethodDefinition]) -> void - + def location: () -> AST::Members::MethodDefinition::loc? end @@ -284,6 +286,10 @@ module RBS def location: () -> Location[untyped, untyped]? + # Confirms if `super` inherits specifies a class + # + # Automatically normalize the name of super. + # def self.check!: (AST::Declarations::Class::Super, env: Environment) -> void end @@ -352,7 +358,7 @@ module RBS attr_reader alias_entry: Environment::ModuleAliasEntry | Environment::ClassAliasEntry def initialize: (Environment::ModuleAliasEntry | Environment::ClassAliasEntry) -> void - + def location: () -> AST::Declarations::AliasDecl::loc? end end diff --git a/sig/resolver/type_name_resolver.rbs b/sig/resolver/type_name_resolver.rbs index 650c1914d..96d156ea9 100644 --- a/sig/resolver/type_name_resolver.rbs +++ b/sig/resolver/type_name_resolver.rbs @@ -17,6 +17,8 @@ module RBS private + attr_reader env: Environment + attr_reader all_names: Set[TypeName] attr_reader cache: Hash[query, TypeName?] diff --git a/sig/type_alias_dependency.rbs b/sig/type_alias_dependency.rbs index a8cf3ec5b..45595c3be 100644 --- a/sig/type_alias_dependency.rbs +++ b/sig/type_alias_dependency.rbs @@ -1,14 +1,45 @@ module RBS + # TypeAliasDependency calculates the dependnecies between type aliases + # + # The dependencies are normalized automatically. + # class TypeAliasDependency attr_reader env: Environment + # A hash table from type alias name to it's direct dependencies + # + # The source type name and dependencies are normalized. + # attr_reader direct_dependencies: Hash[TypeName, Set[TypeName]] + + # A hash table from type alias name to a hash name with keys of transitive dependnecies + # + # The source type name and dependencies are normalized. + # attr_reader dependencies: Hash[TypeName, Hash[TypeName, bool]] def initialize: (env: Environment) -> void + # Returns `true` if given type alias is circular + # + # Normalized given type name automatically. + # def circular_definition?: (TypeName alias_name) -> bool + # Returns the set of direct dependencies from the given type name + # + # Given type name will be normalized automatically. + # Returns normalized type names. + # + def direct_dependencies_of: (TypeName) -> Set[TypeName] + + # Returns the set of dependencies from the given type name + # + # Given type name will be normalized automatically. + # Returns normalized type names. + # + def dependencies_of: (TypeName) -> Set[TypeName] + def build_dependencies: () -> void def transitive_closure: () -> void diff --git a/sig/type_alias_regularity.rbs b/sig/type_alias_regularity.rbs index ab4e0f748..26b759e56 100644 --- a/sig/type_alias_regularity.rbs +++ b/sig/type_alias_regularity.rbs @@ -36,6 +36,9 @@ module RBS 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. @@ -70,6 +73,8 @@ module RBS # 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 @@ -87,6 +92,7 @@ module RBS 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 diff --git a/sig/validator.rbs b/sig/validator.rbs index 42813054f..358a963d4 100644 --- a/sig/validator.rbs +++ b/sig/validator.rbs @@ -46,7 +46,7 @@ module RBS # # - The right hand side can be normalized # - No mixing alias declaration between class and modules - # + # def validate_class_alias: (entry: Environment::ClassAliasEntry | Environment::ModuleAliasEntry) -> void private @@ -54,6 +54,6 @@ module RBS # Resolves relative type names to absolute type names in given context. # Yields the type when the type name resolution using `#resolver` fails. # - def absolute_type: (Types::t, context: Resolver::context) { (Types::t) -> TypeName } -> Types::t + def absolute_type: (Types::t, context: Resolver::context) ?{ (Types::t) -> TypeName } -> Types::t end end diff --git a/sig/variance_calculator.rbs b/sig/variance_calculator.rbs index a6fe009fc..3294fd538 100644 --- a/sig/variance_calculator.rbs +++ b/sig/variance_calculator.rbs @@ -72,6 +72,8 @@ module RBS def in_inherit: (name: TypeName, args: Array[Types::t], variables: Array[Symbol]) -> Result + # The type name must be normalized + # def in_type_alias: (name: TypeName) -> Result private diff --git a/test/rbs/definition_builder_test.rb b/test/rbs/definition_builder_test.rb index b6f42ae7d..465fb8dfc 100644 --- a/test/rbs/definition_builder_test.rb +++ b/test/rbs/definition_builder_test.rb @@ -2593,4 +2593,74 @@ def self.f: () -> String | ... end end end + + def test_module_alias__superclass + SignatureManager.new do |manager| + manager.add_file("foo.rbs", <<-EOF) +module Foo + class Bar + end +end + +module Baz = Foo + +class Hoge < Baz::Bar +end + EOF + + manager.build do |env| + root = nil + + builder = DefinitionBuilder.new(env: env) + + builder.build_instance(type_name("::Hoge")) + builder.build_singleton(type_name("::Hoge")) + end + end + end + + def test_module_alias__mixin + SignatureManager.new do |manager| + manager.add_file("foo.rbs", <<-EOF) +module Foo +end + +module Bar = Foo + +class Baz + include Bar + include Bar +end + EOF + + manager.build do |env| + root = nil + + builder = DefinitionBuilder.new(env: env) + + builder.build_instance(type_name("::Baz")) + builder.build_singleton(type_name("::Baz")) + end + end + end + + def test_module_alias__module_self + SignatureManager.new do |manager| + manager.add_file("foo.rbs", <<-EOF) +class Foo = Integer + +module Bar : Foo +end + EOF + + manager.build do |env| + root = nil + + builder = DefinitionBuilder.new(env: env) + + builder.build_instance(type_name("::Bar")) + builder.build_singleton(type_name("::Bar")) + end + end + end end diff --git a/test/rbs/resolver/type_name_resolver_test.rb b/test/rbs/resolver/type_name_resolver_test.rb index 40d47aea6..c7bac502f 100644 --- a/test/rbs/resolver/type_name_resolver_test.rb +++ b/test/rbs/resolver/type_name_resolver_test.rb @@ -128,4 +128,24 @@ class MyObject end end end + + def test_module_alias + SignatureManager.new do |manager| + manager.files[Pathname("foo.rbs")] = < Integer +EOF + manager.build do |env| + builder = DefinitionBuilder.new(env: env) + calculator = VarianceCalculator.new(builder: builder) + + calculator.in_type_alias(name: TypeName("::Foo::foo")) + calculator.in_type_alias(name: TypeName("::Foo::bar")) + end + end + end end diff --git a/test/validator_test.rb b/test/validator_test.rb index 50e872673..fd8e2acaf 100644 --- a/test/validator_test.rb +++ b/test/validator_test.rb @@ -276,4 +276,95 @@ class Baz = Baz end end end + + def test_validate_type__presence__module_alias_instance + SignatureManager.new do |manager| + manager.add_file("foo.rbs", <<-EOF) +module Foo +end + +module Bar = Foo + +class Foo::Baz = Integer + +type foo = Bar::Baz + EOF + + manager.build do |env| + root = nil + + resolver = RBS::Resolver::TypeNameResolver.new(env) + validator = RBS::Validator.new(env: env, resolver: resolver) + + validator.validate_type(parse_type("Bar::Baz"), context: root) + end + end + end + + def test_validate_type__presence__module_alias_singleton + SignatureManager.new do |manager| + manager.add_file("foo.rbs", <<-EOF) +module Foo +end + +module Bar = Foo + +class Foo::Baz = Integer + EOF + + manager.build do |env| + root = nil + + resolver = RBS::Resolver::TypeNameResolver.new(env) + validator = RBS::Validator.new(env: env, resolver: resolver) + + validator.validate_type(parse_type("singleton(Bar::Baz)"), context: root) + end + end + end + + def test_validate_type__ality_module_alias + SignatureManager.new do |manager| + manager.add_file("foo.rbs", <<-EOF) +module Foo + type list[T] = nil | [T, list[T]] +end + +module Bar = Foo + EOF + + manager.build do |env| + root = nil + + resolver = RBS::Resolver::TypeNameResolver.new(env) + validator = RBS::Validator.new(env: env, resolver: resolver) + + validator.validate_type(parse_type("Bar::list[Bar]"), context: root) + end + end + end + + def test_validate_type_alias__1 + SignatureManager.new do |manager| + manager.add_file("foo.rbs", <<-EOF) +module Foo +end + +module Bar = Foo + +class Baz = Numeric + +type Foo::list[T < Baz] = nil | [T, Bar::list[T]] + EOF + + manager.build do |env| + root = nil + + resolver = RBS::Resolver::TypeNameResolver.new(env) + validator = RBS::Validator.new(env: env, resolver: resolver) + + validator.validate_type_alias(entry: env.type_alias_decls[TypeName("::Foo::list")]) + end + end + end end