Handle payload superclass redefinition errors during gem RBI validation#2653
Handle payload superclass redefinition errors during gem RBI validation#2653zeeshankhan-05 wants to merge 1 commit into
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Hi @KaanOzkan. I appreciate the help with #1834 about using the |
|
I have signed the CLA! |
| if errors.empty? | ||
| payload_superclass_errors = T.let([], T::Array[Spoom::Sorbet::Errors::Error]) | ||
| if auto_strictness | ||
| payload_superclass_res = sorbet( |
There was a problem hiding this comment.
Instead of 2 calls to Sorbet, I think we just need to use --stop-after resolver instead of namer and we can do one call to look at errors. There should also be a early return if there are no errors so that we don't parse the result twice.
| flag = "#{SUPPRESS_PAYLOAD_SUPERCLASS_REDEFINITION_FLAG}=#{constant}" | ||
| config_path = Tapioca::SORBET_CONFIG_FILE | ||
| config = File.exist?(config_path) ? File.read(config_path) : "" | ||
| added = !config.lines(chomp: true).include?(flag) |
There was a problem hiding this comment.
| added = !config.lines(chomp: true).include?(flag) | |
| flag_already_present = !config.lines(chomp: true).include?(flag) |
We can also simplify the branching in the method. For example, you can print in the first conditional instead of creating a separate conditional for printing.
| ) | ||
| payload_superclass_errors = Spoom::Sorbet::Errors::Parser | ||
| .parse_string(payload_superclass_res.err || "") | ||
| .select { |error| error.code == 5012 } |
There was a problem hiding this comment.
5012 errors isn't enough of an indicator for payload superclass mismatch as it's used for any parent/subclass mismatch. You can use error.more directly here instead.
We need a new test for this too:
it "must not add a payload suppression for non-payload superclass redefinitions" do
@project.write!("sorbet/rbi/dsl/non_payload_superclass_conflict.rbi", <<~RBI)
# typed: true
class NonPayloadSuperclassConflict < ::Object
end
RBI
@project.write!("sorbet/rbi/gems/bar@0.3.0.rbi", <<~RBI)
# typed: true
class NonPayloadSuperclassConflict < ::String
end
RBI
result = @project.tapioca("gem foo")
refute_includes(
@project.read("sorbet/config"),
"--suppress-payload-superclass-redefinition-for=NonPayloadSuperclassConflict",
)
assert_empty_stderr(result)
assert_success_status(result)
end
Motivation
Fixes #1834.
When Tapioca validates generated gem RBIs, some definitions can redefine a Sorbet payload class with a different superclass. Sorbet reports this as error
5012and recommends adding--suppress-payload-superclass-redefinition-for=ConstantNametosorbet/config. Tapioca already auto-adjusts RBI strictness for error4010, but it did not handle5012or inform users about the mismatch.Closes #1834
Implementation
--stop-after namervalidation pass for error4010auto-strictness behavior.auto_strictnessis enabled, run a second full Sorbet pass to detect resolver-level error5012(the namer pass alone does not surface this error).--suppress-payload-superclass-redefinition-for=ConstantNametosorbet/configwhen missing.config.lines(chomp: true).include?(flag)) so similar suppressions for other constants do not block the correct entry.sorbet/configcontent when appending (no stripping of trailing whitespace or blank lines).Tests
Added an integration test in the
describe "strictness"block ofspec/tapioca/cli/gem_spec.rb(following maintainer guidance on #1834). The test exercisestapioca gem, verifies the suppression is written tosorbet/config, verifies user-facing output on first and second runs, and confirms idempotency.Ran locally on the clean branch (1 commit ahead of
upstream/main):bin/test spec/tapioca/cli/gem_spec.rb— 67 tests, 494 assertions, 0 failures, 0 errors, 1 skipbin/test spec/tapioca/cli/dsl_spec.rb— 69 tests, 335 assertions, 0 failures, 0 errors, 0 skipsbin/typecheck— passbin/style— passAn earlier full-suite run (
bin/test) completed with 794 tests, 0 failures, 2 errors, and 2 skips. The two errors were unrelatedRubyLsp::Tapioca::AddonURI::InvalidURIErrorfailures caused by spaces in the local directory path; they are not related to this change.