rspec-sorbet-types 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/rspec/sorbet/types/sig.rb +22 -0
- data/lib/rspec/sorbet/types.rb +2 -0
- data/lib/tapioca/dsl/compilers/rspec.rb +177 -0
- data/rbi/rspec-core.rbi +67 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a22cc57159bb8fcf6011e4f526f04da73e7cb0c6a0f8ba2be14b2fda79f1a516
|
4
|
+
data.tar.gz: 7d4cd90ee0792e2b7bd2c8aa64348b8ec2006f57133774d5d6606518a93b3604
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4f8dea02beb1c65684aa54552cbfa96b8d7335d1da3f36c866b6fba677f88e9debe451f836c633e4053700768de559449266599bb42e9974b641f8034744245f
|
7
|
+
data.tar.gz: 80b33d85703d7b9ebdcc0e8f37c8f3ce7718af361413a2491731895fa6c44825634a5a2e17318ed65a3950c77b156d75c3361cc925b82034d3732799a0e962db
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# typed: true
|
2
|
+
|
3
|
+
module RSpec
|
4
|
+
module Sorbet
|
5
|
+
module Types
|
6
|
+
module Sig
|
7
|
+
include Kernel
|
8
|
+
|
9
|
+
def self.extended(sub)
|
10
|
+
super
|
11
|
+
sub.extend(T::Sig)
|
12
|
+
end
|
13
|
+
|
14
|
+
T::Sig::WithoutRuntime.sig { params(decl: T.proc.bind(T::Private::Methods::DeclBuilder).void).void }
|
15
|
+
def rsig(&decl)
|
16
|
+
# It would be better if we could simply use the name "sig", but Sorbet falsely reports that as an overload
|
17
|
+
send(:sig, &decl)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: strict
|
3
|
+
|
4
|
+
require "rspec/core"
|
5
|
+
|
6
|
+
module Tapioca
|
7
|
+
module Dsl
|
8
|
+
module Compilers
|
9
|
+
class RSpec < Compiler
|
10
|
+
extend T::Sig
|
11
|
+
|
12
|
+
ConstantType = type_member { {fixed: T.class_of(::RSpec::Core::ExampleGroup)} }
|
13
|
+
|
14
|
+
class << self
|
15
|
+
extend T::Sig
|
16
|
+
|
17
|
+
sig { override.returns(T::Enumerable[Module]) }
|
18
|
+
def gather_constants
|
19
|
+
all_classes.select { |c| c < ::RSpec::Core::ExampleGroup }
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
sig { void }
|
25
|
+
def require_spec_files!
|
26
|
+
Dir.glob(spec_glob).each do |file|
|
27
|
+
require(file)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
sig { returns(String) }
|
32
|
+
def spec_glob
|
33
|
+
ENV["SORBET_RSPEC_GLOB"] || File.join(".", "spec", "**", "*.rb")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set environment variable, allowing other code to detect that we're compiling
|
38
|
+
ENV["SORBET_RSPEC_TYPES_COMPILING"] = "1"
|
39
|
+
|
40
|
+
# Load all spec files during compiler definition
|
41
|
+
require_spec_files!
|
42
|
+
|
43
|
+
sig { override.void }
|
44
|
+
def decorate
|
45
|
+
klass = root.create_class(T.must(constant.name), superclass_name: T.must(constant.superclass).name)
|
46
|
+
create_includes(klass)
|
47
|
+
create_example_group_submodules(klass)
|
48
|
+
create_singleton_methods(klass)
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
sig { params(klass: RBI::Scope).void }
|
54
|
+
def create_includes(klass)
|
55
|
+
directly_included_modules_for(constant).each do |mod|
|
56
|
+
klass.create_include("::#{mod}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# A method can have a signature even if the method is defined dynamically with define_method
|
61
|
+
# The next call to def or define_method will be the one associated with the signature
|
62
|
+
# However, an exception will be raised if we have two signature declarations in a row
|
63
|
+
# without a method definition.
|
64
|
+
sig { params(method_name: Symbol).returns(String) }
|
65
|
+
def return_type_for_let_declaration(method_name)
|
66
|
+
T::Utils.signature_for_instance_method(constant, method_name)&.return_type&.to_s || "T.untyped"
|
67
|
+
end
|
68
|
+
|
69
|
+
sig { params(klass: RBI::Scope).void }
|
70
|
+
def create_example_group_submodules(klass)
|
71
|
+
modules = directly_included_modules_for(constant).select { |mod| mod.name&.start_with?("RSpec::ExampleGroups::") }
|
72
|
+
modules.each do |mod|
|
73
|
+
scope = root.create_module(T.must(mod.name))
|
74
|
+
direct_public_instance_methods_for(mod).each do |method_name|
|
75
|
+
method_def = mod.instance_method(method_name)
|
76
|
+
return_type = return_type_for_let_declaration(method_name)
|
77
|
+
|
78
|
+
scope.create_method(
|
79
|
+
method_def.name.to_s,
|
80
|
+
parameters: compile_method_parameters_to_rbi(method_def),
|
81
|
+
return_type:,
|
82
|
+
class_method: false
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
sig { params(klass: RBI::Scope).void }
|
89
|
+
def create_singleton_methods(klass)
|
90
|
+
scope = klass.create_class("<< self")
|
91
|
+
scope.create_method(
|
92
|
+
"let",
|
93
|
+
parameters: [
|
94
|
+
create_rest_param("name", type: "T.untyped"),
|
95
|
+
create_block_param("block", type: "T.proc.bind(#{constant.name}).void")
|
96
|
+
]
|
97
|
+
)
|
98
|
+
scope.create_method(
|
99
|
+
"let!",
|
100
|
+
parameters: [
|
101
|
+
create_rest_param("name", type: "T.untyped"),
|
102
|
+
create_block_param("block", type: "T.proc.bind(#{constant.name}).void")
|
103
|
+
]
|
104
|
+
)
|
105
|
+
|
106
|
+
scope.create_method(
|
107
|
+
"before",
|
108
|
+
parameters: [
|
109
|
+
create_rest_param("args", type: "T.untyped"),
|
110
|
+
create_block_param("block", type: "T.proc.bind(#{constant.name}).void")
|
111
|
+
]
|
112
|
+
)
|
113
|
+
|
114
|
+
scope.create_method(
|
115
|
+
"after",
|
116
|
+
parameters: [
|
117
|
+
create_rest_param("args", type: "T.untyped"),
|
118
|
+
create_block_param("block", type: "T.proc.bind(#{constant.name}).void")
|
119
|
+
]
|
120
|
+
)
|
121
|
+
|
122
|
+
scope.create_method(
|
123
|
+
"it",
|
124
|
+
parameters: [
|
125
|
+
create_rest_param("all_args", type: "T.untyped"),
|
126
|
+
create_block_param("block", type: "T.proc.bind(#{constant.name}).void")
|
127
|
+
]
|
128
|
+
)
|
129
|
+
|
130
|
+
scope.create_method(
|
131
|
+
"specify",
|
132
|
+
parameters: [
|
133
|
+
create_rest_param("all_args", type: "T.untyped"),
|
134
|
+
create_block_param("block", type: "T.proc.bind(#{constant.name}).void")
|
135
|
+
]
|
136
|
+
)
|
137
|
+
|
138
|
+
scope.create_method(
|
139
|
+
"subject",
|
140
|
+
parameters: [
|
141
|
+
create_block_param("block", type: "T.proc.bind(#{constant.name}).void")
|
142
|
+
]
|
143
|
+
)
|
144
|
+
|
145
|
+
singleton_class = constant.singleton_class
|
146
|
+
direct_public_instance_methods_for(singleton_class).each do |method_name|
|
147
|
+
create_method_from_def(scope, singleton_class.instance_method(method_name))
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
sig { params(constant: Module).returns(T::Enumerable[Module]) }
|
152
|
+
def directly_included_modules_for(constant)
|
153
|
+
result = constant.included_modules
|
154
|
+
result -= constant.included_modules.map do |included_mod|
|
155
|
+
included_mod.ancestors - [included_mod]
|
156
|
+
end.flatten
|
157
|
+
if constant.is_a?(Class) && constant.superclass
|
158
|
+
result -= T.must(constant.superclass).included_modules
|
159
|
+
end
|
160
|
+
result
|
161
|
+
end
|
162
|
+
|
163
|
+
sig { params(constant: Module).returns(T::Enumerable[Symbol]) }
|
164
|
+
def direct_public_instance_methods_for(constant)
|
165
|
+
result = constant.public_instance_methods
|
166
|
+
constant.included_modules.each do |included_mod|
|
167
|
+
result -= included_mod.public_instance_methods
|
168
|
+
end
|
169
|
+
if constant.is_a?(Class) && constant.superclass
|
170
|
+
result -= T.must(constant.superclass).public_instance_methods
|
171
|
+
end
|
172
|
+
result
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/rbi/rspec-core.rbi
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# typed: strict
|
3
|
+
|
4
|
+
module RSpec
|
5
|
+
class << self
|
6
|
+
sig do
|
7
|
+
params(
|
8
|
+
args: T.untyped,
|
9
|
+
example_group_block: T.proc.bind(T.class_of(RSpec::Core::ExampleGroup)).void,
|
10
|
+
).void
|
11
|
+
end
|
12
|
+
|
13
|
+
def describe(*args, &example_group_block); end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class RSpec::Core::ExampleGroup
|
18
|
+
include ::RSpec::Matchers
|
19
|
+
include ::RSpec::Mocks::ExampleMethods
|
20
|
+
|
21
|
+
class << self
|
22
|
+
sig do
|
23
|
+
params(
|
24
|
+
all_args: T.untyped,
|
25
|
+
block: T.proc.bind(RSpec::Core::ExampleGroup).void,
|
26
|
+
).void
|
27
|
+
end
|
28
|
+
|
29
|
+
def it(*all_args, &block); end
|
30
|
+
|
31
|
+
sig do
|
32
|
+
params(
|
33
|
+
all_args: T.untyped,
|
34
|
+
block: T.proc.bind(RSpec::Core::ExampleGroup).void,
|
35
|
+
).void
|
36
|
+
end
|
37
|
+
|
38
|
+
def specify(*all_args, &block); end
|
39
|
+
|
40
|
+
sig do
|
41
|
+
params(
|
42
|
+
args: T.untyped,
|
43
|
+
block: T.proc.bind(RSpec::Core::ExampleGroup).void,
|
44
|
+
).void
|
45
|
+
end
|
46
|
+
|
47
|
+
def before(*args, &block); end
|
48
|
+
|
49
|
+
sig do
|
50
|
+
params(
|
51
|
+
args: T.untyped,
|
52
|
+
block: T.proc.bind(RSpec::Core::ExampleGroup).void,
|
53
|
+
).void
|
54
|
+
end
|
55
|
+
|
56
|
+
def after(*args, &block); end
|
57
|
+
|
58
|
+
sig do
|
59
|
+
params(
|
60
|
+
args: T.untyped,
|
61
|
+
block: T.proc.bind(RSpec::Core::ExampleGroup).void,
|
62
|
+
).void
|
63
|
+
end
|
64
|
+
|
65
|
+
def around(*args, &block); end
|
66
|
+
end
|
67
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rspec-sorbet-types
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hongli Lai
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-01-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sorbet-runtime
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tapioca
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.16'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.16'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description: A gem that provides integration between Sorbet type checking and RSpec
|
56
|
+
testing framework
|
57
|
+
email:
|
58
|
+
- hongli@hongli.nl
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- lib/rspec/sorbet/types.rb
|
64
|
+
- lib/rspec/sorbet/types/sig.rb
|
65
|
+
- lib/tapioca/dsl/compilers/rspec.rb
|
66
|
+
- rbi/rspec-core.rbi
|
67
|
+
homepage: https://github.com/FooBarWidget/sorbet-rspec
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
metadata:
|
71
|
+
homepage_uri: https://github.com/FooBarWidget/sorbet-rspec
|
72
|
+
source_code_uri: https://github.com/FooBarWidget/sorbet-rspec
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 2.7.0
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubygems_version: 3.5.3
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Sorbet integration for RSpec
|
92
|
+
test_files: []
|