From f8557b137727ab5b9daaae1e786b75b7024531e6 Mon Sep 17 00:00:00 2001 From: Samuel Giles Date: Sat, 11 Mar 2023 22:39:15 +0000 Subject: [PATCH] Add basic Sorbet signatures --- CHANGELOG.md | 1 + lib/rspec/sorbet/doubles.rb | 29 ++++++++++++++++++++------- sorbet/config | 2 ++ sorbet/rbi/gems/pry-byebug@3.10.1.rbi | 2 +- spec/lib/rspec/sorbet_spec.rb | 2 +- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b60356..d1723d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - Rubocop offenses resolved +- Sorbet signatures added to `RSpec::Sorbet::Doubles` ## 1.9.1 diff --git a/lib/rspec/sorbet/doubles.rb b/lib/rspec/sorbet/doubles.rb index 059c732..2f7e467 100644 --- a/lib/rspec/sorbet/doubles.rb +++ b/lib/rspec/sorbet/doubles.rb @@ -1,4 +1,4 @@ -# typed: false +# typed: strict # frozen_string_literal: true require "sorbet-runtime" @@ -6,12 +6,21 @@ 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) @@ -24,15 +33,17 @@ def allow_doubles! # rubocop:disable Layout/LineLength INLINE_DOUBLE_REGEX = - /T.(?:let|cast): Expected type (?:T.(?any|nilable|class_of)\()*(?[a-zA-Z0-9:: ,]*)(\))*, got (?:type .* with value )?#<(?Instance|Class|Object)?Double([\(]|[ ])(?[a-zA-Z0-9:: ,]*)(\))?/.freeze + T.let(/T.(?:let|cast): Expected type (?:T.(?any|nilable|class_of)\()*(?[a-zA-Z0-9:: ,]*)(\))*, got (?:type .* with value )?#<(?Instance|Class|Object)?Double([\(]|[ ])(?[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 @@ -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" @@ -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 diff --git a/sorbet/config b/sorbet/config index c6f6b76..9781c74 100644 --- a/sorbet/config +++ b/sorbet/config @@ -2,3 +2,5 @@ . --ignore vendor +--disable-watchman +--enable-experimental-requires-ancestor diff --git a/sorbet/rbi/gems/pry-byebug@3.10.1.rbi b/sorbet/rbi/gems/pry-byebug@3.10.1.rbi index 8a37490..baa002d 100644 --- a/sorbet/rbi/gems/pry-byebug@3.10.1.rbi +++ b/sorbet/rbi/gems/pry-byebug@3.10.1.rbi @@ -1,4 +1,4 @@ -# typed: true +# typed: ignore # DO NOT EDIT MANUALLY # This is an autogenerated file for types exported from the `pry-byebug` gem. diff --git a/spec/lib/rspec/sorbet_spec.rb b/spec/lib/rspec/sorbet_spec.rb index f737dbc..e4fd650 100644 --- a/spec/lib/rspec/sorbet_spec.rb +++ b/spec/lib/rspec/sorbet_spec.rb @@ -1,4 +1,4 @@ -# typed: ignore +# typed: false # frozen_string_literal: true require "sorbet-runtime"