lib/tapioca/compilers/symbol_table/symbol_generator.rb in tapioca-0.4.22 vs lib/tapioca/compilers/symbol_table/symbol_generator.rb in tapioca-0.4.23

- old
+ new

@@ -143,22 +143,28 @@ sig { params(tree: RBI::Tree, name: String, value: BasicObject).void.checked(:never) } def compile_object(tree, name, value) return if symbol_ignored?(name) klass = class_of(value) - klass_name = name_of(klass) + klass_name = if klass == ObjectSpace::WeakMap + # WeakMap is an implicit generic with one type variable + "ObjectSpace::WeakMap[T.untyped]" + elsif T::Generic === klass + generic_name_of(klass) + else + name_of(klass) + end + if klass_name == "T::Private::Types::TypeAlias" tree << RBI::Const.new(name, "T.type_alias { #{T.unsafe(value).aliased_type} }") return end return if klass_name&.start_with?("T::Types::", "T::Private::") type_name = klass_name || "T.untyped" - # TODO: Do this in a more generic and clean way. - type_name = "#{type_name}[T.untyped]" if type_name == "ObjectSpace::WeakMap" tree << RBI::Const.new(name, "T.let(T.unsafe(nil), #{type_name})") end sig { params(tree: RBI::Tree, name: String, constant: Module).void } @@ -770,9 +776,22 @@ name = raw_name_of(constant) return if name.nil? return unless are_equal?(constant, resolve_constant(name, inherit: true)) name = "Struct" if name =~ /^(::)?Struct::[^:]+$/ name + end + + sig { params(constant: T.all(Module, T::Generic)).returns(String) } + def generic_name_of(constant) + type_name = T.must(constant.name) + return type_name if type_name =~ /\[.*\]$/ + + type_variables = Tapioca::GenericTypeRegistry.lookup_type_variables(constant) + return type_name unless type_variables + + type_variable_names = type_variables.map { "T.untyped" }.join(", ") + + "#{type_name}[#{type_variable_names}]" end sig { params(constant: Module).returns(T.nilable(String)) } def name_of_proxy_target(constant) klass = class_of(constant)