Conversation
Adds `# typed: true` to all 753 spec files that previously had no Sorbet sigil, in preparation for enabling Sorbet's experimental RSpec mode.
Adds `--enable-experimental-rspec` to the Sorbet config so that Sorbet type-checks RSpec example groups with awareness of the DSL structure (describe/context/it/let/before/etc.). Also adds explicit includes on `RSpec::Core::ExampleGroup` in upstream.rbi so Sorbet resolves `RSpec::Matchers`, `RSpec::SharedContext`, and `RSpec::Mocks::ExampleMethods` methods within example group bodies.
These gems were previously excluded from tapioca gem RBI generation. Removing the exclusions and generating their RBIs gives Sorbet the type information needed to resolve rspec/rspec-mocks constants and methods under the new experimental RSpec mode.
Adds a tapioca DSL compiler that scans test files for custom RSpec matcher definitions and generates RBI stubs for them on `RSpec::Matchers`. Handles all four definition styles: - RSpec::Matchers.define :name do |args| - (RSpec::Matchers.)?define_negated_matcher :name, :base - (RSpec::Matchers.)?alias_matcher :new, :old - matcher :name do |args| (inside describe/context/shared_context) Because example groups include `RSpec::Matchers`, adding stubs there makes custom matchers visible to Sorbet's experimental RSpec type-checker. The generated RBI reduces "Method does not exist" errors by ~560.
`RSpec::Matchers::MatcherDelegator` forwards unknown calls to its wrapped `base_matcher` via `method_missing`. Sorbet cannot follow that delegation, so aliased/negated wrappers of `output` (e.g. `not_to_output`) appear to lack `to_stdout`, `to_stderr`, and their `_from_any_process` variants. Declaring those four methods on `MatcherDelegator` in upstream.rbi — with `T.self_type` as the return type to preserve chainability — eliminates the "Method to_stderr does not exist on AliasedNegatedMatcher" errors (-129).
|
"Looks" good when 🟢. I'd suggest you keep these all |
…ioca Instead of manually shim-ing individual methods (e.g. to_stdout/to_stderr) onto RSpec::Matchers::MatcherDelegator, a tapioca DSL compiler now enumerates every public method defined on a concrete RSpec::Matchers::BuiltIn subclass (excluding those already on BaseMatcher or MatcherDelegator) and declares them on MatcherDelegator. This is more precise than a blanket T.untyped escape-hatch: only methods that genuinely exist on some built-in matcher are permitted on delegators (to_stdout/to_stderr from Output, by/from/to from Change, with/argument from RespondTo, etc.). Calls to methods that exist on no built-in matcher still raise a 7003 error. Removes the manual upstream.rbi shim added in the previous commit.
|
@MikeMcQuaid This is just a scratch PR for me to track the progress in resolving major categories of rspec/sorbet compatibility (and possibly to link back to when upstreaming work to e.g. sorbet or tapioca). I think it would actually be counterproductive to start flipping the |
|
@dduugg cool works for me! |
Summary
--enable-experimental-rspecmode so example groups are type-checked with RSpec DSL awareness# typed: true(from untyped) as a prerequisiterspecandrspec-mocks(previously excluded)RSpec::Matchersstubs, reducing "Method does not exist" errors by ~560Commits
test: promote all spec files to # typed: true— blanket sigil promotion on all 753 spec filessorbet: enable experimental RSpec mode— adds--enable-experimental-rspecto sorbet config and explicitRSpec::Core::ExampleGroupincludes in upstream.rbisorbet: generate tapioca gem RBIs for rspec and rspec-mocks— removes the exclusions and regenerates those gem RBIssorbet: add tapioca DSL compiler for custom RSpec matchers— scans test files fordefine/alias_matcher/define_negated_matcher/matchercalls and generates typed stubsError count
brew typecheckerrors: 5,990 → 5,432 after this PR (−558). The remaining errors are unrelated to custom matchers (built-in dynamic predicate matchers, include/module-helper resolution, etc.).🤖 Generated with Claude Code