From 7c28272255edcd654cc69d877b029cc7ebbacc4b Mon Sep 17 00:00:00 2001 From: Alexander Momchilov Date: Tue, 18 Jun 2024 16:48:52 -0400 Subject: [PATCH] Rewrite attributes into methods --- lib/tapioca/commands/abstract_gem.rb | 10 +++ spec/tapioca/cli/gem_spec.rb | 112 +++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) diff --git a/lib/tapioca/commands/abstract_gem.rb b/lib/tapioca/commands/abstract_gem.rb index c4b66916b..a4c52747d 100644 --- a/lib/tapioca/commands/abstract_gem.rb +++ b/lib/tapioca/commands/abstract_gem.rb @@ -291,6 +291,16 @@ def merge_with_exported_rbi(gem, file) tree = gem.exported_rbi_tree + begin + tree.replace_attributes_with_methods! + rescue RBI::UnexpectedMultipleSigsError => e + $stderr.puts(<<~MSG) + WARNING: Attributes cannot have more than one sig. + + #{e.node.string.chomp} + MSG + end + unless tree.conflicts.empty? say_error("\n\n RBIs exported by `#{gem.name}` contain conflicts and can't be used:", :yellow) diff --git a/spec/tapioca/cli/gem_spec.rb b/spec/tapioca/cli/gem_spec.rb index 78049afd9..00d99b322 100644 --- a/spec/tapioca/cli/gem_spec.rb +++ b/spec/tapioca/cli/gem_spec.rb @@ -499,6 +499,118 @@ def foo; end assert_success_status(result) end + + it "must generate a gem RBI and rewrites attributes from exported gem RBIs into methods" do + foo = mock_gem("foo", "0.0.1") do + + write!("lib/foo.rb", <<~RBI) + class Foo + attr_reader :i + end + RBI + + write!("rbi/foo.rbi", <<~RBI) + class Foo + sig { returns(Integer) } + attr_reader :i + end + RBI + end + + @project.require_mock_gem(foo) + @project.bundle_install! + + result = @project.tapioca("gem foo") + + assert_stdout_includes(result, "create sorbet/rbi/gems/foo@0.0.1.rbi") + puts @project.read("sorbet/rbi/gems/foo@0.0.1.rbi") + assert_project_file_includes("sorbet/rbi/gems/foo@0.0.1.rbi", <<~RBI.chomp) + class Foo + sig { returns(Integer) } + def i; end + end + RBI + assert_empty_stderr(result) + assert_success_status(result) + end + + it "must generate a gem RBI that merges methods and attributes" do + foo = mock_gem("foo", "0.0.1") do + + write!("lib/foo.rb", <<~RBI) + class Foo + extend T::Sig + + sig { returns(Integer) } + attr_reader :i + + def s; end + end + RBI + + write!("rbi/foo.rbi", <<~RBI) + class Foo + attr_reader :i + + sig { returns(String) } + attr_reader :s + end + RBI + end + + @project.require_mock_gem(foo) + @project.bundle_install! + + result = @project.tapioca("gem foo") + + assert_stdout_includes(result, "create sorbet/rbi/gems/foo@0.0.1.rbi") + puts result.err + puts @project.read("sorbet/rbi/gems/foo@0.0.1.rbi") + assert_project_file_includes("sorbet/rbi/gems/foo@0.0.1.rbi", <<~RBI.chomp) + class Foo + sig { returns(Integer) } + def i; end + + sig { returns(String) } + def s; end + end + RBI + assert_empty_stderr(result) + assert_success_status(result) + end + + it "logs an error message if an attribute has multiple sigs" do + foo = mock_gem("foo", "0.0.1") do + write!("lib/foo.rb", <<~RBI) + class Foo + end + RBI + + write!("rbi/foo.rbi", <<~RBI) + class Foo + sig { returns(Integer) } + sig { returns(String) } + attr_reader :i + end + RBI + end + + @project.require_mock_gem(foo) + @project.bundle_install! + + result = @project.tapioca("gem foo") + + assert_stdout_includes(result, "create sorbet/rbi/gems/foo@0.0.1.rbi") + + assert_stderr_includes(result, <<~MSG) + WARNING: Attributes cannot have more than one sig. + + sig { returns(Integer) } + sig { returns(String) } + attr_reader :i + MSG + end + it "must remove outdated RBIs" do @project.require_mock_gem(mock_gem("foo", "0.0.1")) @project.require_mock_gem(mock_gem("bar", "0.3.0"))