Skip to content

Commit

Permalink
Merge pull request #25 from samuelgiles/sorbet
Browse files Browse the repository at this point in the history
Add basic Sorbet signatures
  • Loading branch information
samuelgiles authored Mar 11, 2023
2 parents c376fb3 + f8557b1 commit 4d0e647
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

- Rubocop offenses resolved
- Sorbet signatures added to `RSpec::Sorbet::Doubles`

## 1.9.1

Expand Down
29 changes: 22 additions & 7 deletions lib/rspec/sorbet/doubles.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
# typed: false
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"

module RSpec
module Sorbet
module Doubles
extend T::Sig
extend T::Helpers

requires_ancestor { Kernel }

sig { void }
def allow_doubles!
T::Configuration.inline_type_error_handler = proc do |error|
inline_type_error_handler(error)
end

@existing_handler = T::Configuration.instance_variable_get(:@call_validation_error_handler)
@existing_handler = T.let(
T::Configuration.instance_variable_get(:@call_validation_error_handler),
T.nilable(T.proc.params(signature: T.untyped, opts: T::Hash[T.untyped, T.untyped]).void),
)

T::Configuration.call_validation_error_handler = proc do |signature, opts|
call_validation_error_handler(signature, opts)
Expand All @@ -24,15 +33,17 @@ def allow_doubles!

# rubocop:disable Layout/LineLength
INLINE_DOUBLE_REGEX =
/T.(?:let|cast): Expected type (?:T.(?<t_method>any|nilable|class_of)\()*(?<expected_types>[a-zA-Z0-9:: ,]*)(\))*, got (?:type .* with value )?#<(?<double_type>Instance|Class|Object)?Double([\(]|[ ])(?<doubled_type>[a-zA-Z0-9:: ,]*)(\))?/.freeze
T.let(/T.(?:let|cast): Expected type (?:T.(?<t_method>any|nilable|class_of)\()*(?<expected_types>[a-zA-Z0-9:: ,]*)(\))*, got (?:type .* with value )?#<(?<double_type>Instance|Class|Object)?Double([\(]|[ ])(?<doubled_type>[a-zA-Z0-9:: ,]*)(\))?/.freeze, Regexp)
# rubocop:enable Layout/LineLength

sig { params(signature: T.untyped, opts: T.untyped).void }
def handle_call_validation_error(signature, opts)
raise TypeError, opts[:pretty_message] unless @existing_handler

@existing_handler.call(signature, opts)
end

sig { params(error: Exception).void }
def inline_type_error_handler(error)
case error
when TypeError
Expand All @@ -42,13 +53,13 @@ def inline_type_error_handler(error)
raise error unless (match = message.match(INLINE_DOUBLE_REGEX))

t_method = match[:t_method]
expected_types = match[:expected_types].split(",").map do |expected_type|
expected_types = T.must(match[:expected_types]).split(",").map do |expected_type|
Object.const_get(expected_type.strip)
end
double_type = match[:double_type]
return if double_type.nil?

doubled_type = Object.const_get(match[:doubled_type])
doubled_type = Object.const_get(T.must(match[:doubled_type]))

if double_type == "Class"
raise error if t_method != "class_of"
Expand All @@ -68,24 +79,28 @@ def inline_type_error_handler(error)
end
end

sig { params(message: String).returns(T::Boolean) }
def unable_to_check_type_for_message?(message)
double_message_with_ellipsis?(message) ||
typed_array_message?(message)
end

VERIFYING_DOUBLE_OR_DOUBLE =
/(RSpec::Mocks::(Instance|Class|Object)VerifyingDouble|(Instance|Class|Object)?Double)/.freeze
T.let(/(RSpec::Mocks::(Instance|Class|Object)VerifyingDouble|(Instance|Class|Object)?Double)/.freeze, Regexp)

sig { params(message: String).returns(T::Boolean) }
def double_message_with_ellipsis?(message)
message.include?("...") && message.match?(VERIFYING_DOUBLE_OR_DOUBLE)
end

TYPED_ARRAY_MESSAGE = /got T::Array/.freeze
TYPED_ARRAY_MESSAGE = T.let(/got T::Array/.freeze, Regexp)

sig { params(message: String).returns(T::Boolean) }
def typed_array_message?(message)
message.match?(TYPED_ARRAY_MESSAGE)
end

sig { params(signature: T.untyped, opts: T::Hash[T.untyped, T.untyped]).void }
def call_validation_error_handler(signature, opts)
should_raise = true

Expand Down
2 changes: 2 additions & 0 deletions sorbet/config
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@
.
--ignore
vendor
--disable-watchman
--enable-experimental-requires-ancestor
2 changes: 1 addition & 1 deletion sorbet/rbi/gems/[email protected]

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion spec/lib/rspec/sorbet_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# typed: ignore
# typed: false
# frozen_string_literal: true

require "sorbet-runtime"
Expand Down

0 comments on commit 4d0e647

Please sign in to comment.