From e06561317391d76d67a1052b755ce366ba151aa2 Mon Sep 17 00:00:00 2001 From: Takumi Shotoku Date: Wed, 18 Sep 2024 23:08:04 +0900 Subject: [PATCH] Ensure that generics parameters are set in Array and Hash The RBS generated by rbs-inline does not have generics for Array and Hash, so `rbs validate` will fail. ```ruby # example.rb class A FOO = [] BAR = {} end ```` ```console $ rbs-inline --opt-out --output example.rb $ rbs -I sig validate E, [2024-09-18T23:35:08.624066 #79451] ERROR -- rbs: sig/generated/example.rbs:4:7. .4:14: ::Array expects parameters [unchecked out Elem], but given args [] (RBS::InvalidTypeApplicationError) E, [2024-09-18T23:35:08.624103 #79451] ERROR -- rbs: sig/generated/example.rbs:6:7. .6:13: ::Hash expects parameters [unchecked out K, unchecked out V], but given args [] (RBS::InvalidTypeApplicationError) ```` Add untyped generics parameters to avoid validation errors. --- lib/rbs/inline/writer.rb | 24 +++++++++++++++++++++++- sig/generated/rbs/inline/writer.rbs | 7 +++++++ test/rbs/inline/writer_test.rb | 14 ++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/rbs/inline/writer.rb b/lib/rbs/inline/writer.rb index 276c851..391b24e 100644 --- a/lib/rbs/inline/writer.rb +++ b/lib/rbs/inline/writer.rb @@ -180,7 +180,7 @@ def translate_constant_decl(decl, rbs) rbs << RBS::AST::Declarations::Constant.new( name: decl.constant_name, - type: decl.type, + type: constant_decl_to_type(decl), comment: comment, location: nil ) @@ -608,6 +608,28 @@ def translate_class_block_decl(block, rbs) comment: comment ) end + + # @rbs decl: AST::Declarations::ConstantDecl + # @rbs return: RBS::Types::t + def constant_decl_to_type(decl) + type = decl.type + return type unless type.is_a?(RBS::Types::ClassInstance) + return type if type.args.any? + + case decl.node.value + when Prism::ArrayNode + RBS::BuiltinNames::Array.instance_type(untyped) + when Prism::HashNode + RBS::BuiltinNames::Hash.instance_type(untyped, untyped) + else + type + end + end + + # @rbs return: RBS::Types::Bases::Any + def untyped + @untyped ||= RBS::Types::Bases::Any.new(location: nil) + end end end end diff --git a/sig/generated/rbs/inline/writer.rbs b/sig/generated/rbs/inline/writer.rbs index 0d3ea2b..ab52410 100644 --- a/sig/generated/rbs/inline/writer.rbs +++ b/sig/generated/rbs/inline/writer.rbs @@ -107,6 +107,13 @@ module RBS # @rbs rbs: _Content # @rbs return: void def translate_class_block_decl: (AST::Declarations::BlockDecl block, _Content rbs) -> void + + # @rbs decl: AST::Declarations::ConstantDecl + # @rbs return: RBS::Types::t + def constant_decl_to_type: (AST::Declarations::ConstantDecl decl) -> RBS::Types::t + + # @rbs return: RBS::Types::Bases::Any + def untyped: () -> RBS::Types::Bases::Any end end end diff --git a/test/rbs/inline/writer_test.rb b/test/rbs/inline/writer_test.rb index 5842f53..a8da368 100644 --- a/test/rbs/inline/writer_test.rb +++ b/test/rbs/inline/writer_test.rb @@ -482,6 +482,20 @@ def test_constant_decl RBS end + def test_constant__without_decl + output = translate(<<~RUBY) + TAGS = [] + + OPTIONS = {} + RUBY + + assert_equal <<~RBS, output + TAGS: ::Array[untyped] + + OPTIONS: ::Hash[untyped, untyped] + RBS + end + def test_generic_class_module output = translate(<<~RUBY) # @rbs generic T