steep 0.7.1 → 0.8.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile +3 -0
- data/README.md +30 -1
- data/exe/steep +1 -1
- data/lib/steep/cli.rb +197 -61
- data/lib/steep/drivers/annotations.rb +2 -0
- data/lib/steep/drivers/check.rb +14 -3
- data/lib/steep/drivers/print_interface.rb +3 -0
- data/lib/steep/drivers/scaffold.rb +1 -0
- data/lib/steep/drivers/validate.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/smoke/regexp/a.rb +147 -0
- data/smoke/regexp/b.rb +105 -0
- data/stdlib/builtin.rbi +56 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d90e7067b0b17caaae304fa3de1e80e73a5a3cc8081270c338c291ec572a08d6
|
4
|
+
data.tar.gz: 15ab7f0d9168a6be10c0688fd8af60b4d85786a41f4648206287e04d737e690b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5a0c188bee7427b97ef8a57b88dd0ab6f5b77cade4287951010bf0318e97b33bcb642530763faf2494666261fceac63f72113cad9a38b7ecaa2f8c3f984e8a72
|
7
|
+
data.tar.gz: aae9a7653b739e11a9ebec676698b0a1dc4af22ab67a9701e6c4615ffe0466da7907bd0a5980c6f4285c25d63aa12b0ff02185425a03087ecdb0f45e6da3bf64
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.8.0 (2018-10-29)
|
6
|
+
|
7
|
+
* Load types from gems (#64, #66)
|
8
|
+
* Fix exit status (#65)
|
9
|
+
* Fix `--version` handling (#57 @ybiquitous, #58)
|
10
|
+
* Add `Regexp` and `MatchData` (#58 @ybiquitous)
|
11
|
+
|
5
12
|
## 0.7.1 (2018-10-22)
|
6
13
|
|
7
14
|
* Rename *hash type* to *record type* (#60)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -208,10 +208,39 @@ Use `--dump-all-types` for that.
|
|
208
208
|
|
209
209
|
$ steep check --dump-all-types test.rb
|
210
210
|
|
211
|
-
### Verbose
|
211
|
+
### Verbose Option
|
212
212
|
|
213
213
|
Try `-v` option to report more information about type checking.
|
214
214
|
|
215
|
+
### Loading Type definitions from Gems
|
216
|
+
|
217
|
+
You can pass `-G` option to specify name of gems to load type definitions.
|
218
|
+
|
219
|
+
```
|
220
|
+
$ steep check -G strong_json lib
|
221
|
+
```
|
222
|
+
|
223
|
+
When you are using bundler, Steep load type definitions from bundled gems automatically.
|
224
|
+
|
225
|
+
```
|
226
|
+
$ bundle exec steep check lib
|
227
|
+
```
|
228
|
+
|
229
|
+
To disable automatic gem detection from bundler, you can specify `--no-bundler` option.
|
230
|
+
|
231
|
+
```
|
232
|
+
$ bundle exec steep check --no-bundler -G strong_json lib
|
233
|
+
```
|
234
|
+
|
235
|
+
## Making a Gem with Type Definition
|
236
|
+
|
237
|
+
Put your type definition file in a directory, ship that in your gem, and let `metadata` of the gemspec to contain `"steep_types" => dir_name`.
|
238
|
+
|
239
|
+
```rb
|
240
|
+
spec.metadata = { "steep_types" => "sig" }
|
241
|
+
```
|
242
|
+
|
243
|
+
We recommend using `sig` as a name of the directory for type definitions, but you can use any directory.
|
215
244
|
|
216
245
|
## Examples
|
217
246
|
|
data/exe/steep
CHANGED
@@ -8,7 +8,7 @@ require 'steep'
|
|
8
8
|
require 'steep/cli'
|
9
9
|
|
10
10
|
begin
|
11
|
-
Steep::CLI.new(argv: ARGV.dup, stdout: STDOUT, stderr: STDERR, stdin: STDIN).run
|
11
|
+
exit Steep::CLI.new(argv: ARGV.dup, stdout: STDOUT, stderr: STDERR, stdin: STDIN).run
|
12
12
|
rescue => exn
|
13
13
|
STDERR.puts exn.inspect
|
14
14
|
exn.backtrace.each do |t|
|
data/lib/steep/cli.rb
CHANGED
@@ -2,6 +2,122 @@ require 'optparse'
|
|
2
2
|
|
3
3
|
module Steep
|
4
4
|
class CLI
|
5
|
+
BUILTIN_PATH = Pathname(__dir__).join("../../stdlib").realpath
|
6
|
+
|
7
|
+
class SignatureOptions
|
8
|
+
class MissingGemError < StandardError
|
9
|
+
attr_reader :name
|
10
|
+
attr_reader :version
|
11
|
+
|
12
|
+
def initialize(name:, version:)
|
13
|
+
@name = name
|
14
|
+
@version = version
|
15
|
+
super "Requested gem not found: name=#{name}, version=#{version}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class NoTypeDefinitionFromGemError < StandardError
|
20
|
+
attr_reader :gemspec
|
21
|
+
|
22
|
+
def initialize(gemspec:)
|
23
|
+
@gemspec = gemspec
|
24
|
+
super "Gem does not provide Steep type: gem=#{gemspec.name}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :no_builtin
|
29
|
+
attr_reader :no_bundler
|
30
|
+
|
31
|
+
def initialize
|
32
|
+
@options = []
|
33
|
+
end
|
34
|
+
|
35
|
+
def no_builtin!
|
36
|
+
@no_builtin = true
|
37
|
+
end
|
38
|
+
|
39
|
+
def no_bundler!
|
40
|
+
@no_bundler = true
|
41
|
+
end
|
42
|
+
|
43
|
+
def <<(option)
|
44
|
+
@options << option
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_gem_dir(gem)
|
48
|
+
name, version = gem.split(/:/)
|
49
|
+
spec =
|
50
|
+
begin
|
51
|
+
Gem::Specification.find_by_name(name, version)
|
52
|
+
rescue Gem::MissingSpecError
|
53
|
+
raise MissingGemError.new(name: name, version: version)
|
54
|
+
end
|
55
|
+
|
56
|
+
dirs_from_spec(spec).tap do |dirs|
|
57
|
+
if dirs.empty?
|
58
|
+
raise NoTypeDefinitionFromGemError.new(gemspec: spec)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def dirs_from_spec(spec)
|
64
|
+
type_dirs = spec.metadata["steep_types"].yield_self do |types|
|
65
|
+
case types
|
66
|
+
when nil
|
67
|
+
[]
|
68
|
+
when String
|
69
|
+
types.split(/:/).map do |type|
|
70
|
+
Pathname(type)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
base_dir = Pathname(spec.gem_dir)
|
76
|
+
type_dirs.map do |dir|
|
77
|
+
base_dir + dir
|
78
|
+
end.select(&:directory?)
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_bundler_gems(options)
|
82
|
+
if defined?(Bundler)
|
83
|
+
Steep.logger.info "Bundler detected!"
|
84
|
+
Bundler.load.gems.each do |spec|
|
85
|
+
dirs = dirs_from_spec(spec)
|
86
|
+
options.unshift *dirs
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def paths
|
92
|
+
options = if @options.none? {|option| option.is_a?(Pathname) }
|
93
|
+
@options + [Pathname("sig")]
|
94
|
+
else
|
95
|
+
@options
|
96
|
+
end
|
97
|
+
|
98
|
+
unless no_bundler
|
99
|
+
add_bundler_gems(options)
|
100
|
+
end
|
101
|
+
|
102
|
+
paths = options.flat_map do |option|
|
103
|
+
case option
|
104
|
+
when Pathname
|
105
|
+
# Dir
|
106
|
+
[option]
|
107
|
+
when String
|
108
|
+
# gem name
|
109
|
+
find_gem_dir(option)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
unless no_builtin
|
114
|
+
paths.unshift BUILTIN_PATH
|
115
|
+
end
|
116
|
+
|
117
|
+
paths
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
5
121
|
attr_reader :argv
|
6
122
|
attr_reader :stdout
|
7
123
|
attr_reader :stdin
|
@@ -16,10 +132,17 @@ module Steep
|
|
16
132
|
end
|
17
133
|
|
18
134
|
def self.available_commands
|
19
|
-
[:check, :validate, :annotations, :scaffold, :interface, :version]
|
135
|
+
[:check, :validate, :annotations, :scaffold, :interface, :version, :paths]
|
20
136
|
end
|
21
137
|
|
22
|
-
def
|
138
|
+
def process_global_options
|
139
|
+
OptionParser.new do |opts|
|
140
|
+
opts.on("--version") do
|
141
|
+
process_version
|
142
|
+
exit 0
|
143
|
+
end
|
144
|
+
end.order!
|
145
|
+
|
23
146
|
true
|
24
147
|
end
|
25
148
|
|
@@ -35,101 +158,114 @@ module Steep
|
|
35
158
|
end
|
36
159
|
|
37
160
|
def run
|
38
|
-
|
161
|
+
process_global_options or return 1
|
39
162
|
setup_command or return 1
|
40
163
|
|
41
164
|
__send__(:"process_#{command}")
|
42
165
|
end
|
43
166
|
|
167
|
+
def handle_dir_options(opts, options)
|
168
|
+
opts.on("-I [PATH]") {|path| options << Pathname(path) }
|
169
|
+
opts.on("-G [GEM]") {|gem| options << gem }
|
170
|
+
opts.on("--no-builtin") { options.no_builtin! }
|
171
|
+
opts.on("--no-bundler") { options.no_bundler! }
|
172
|
+
end
|
173
|
+
|
174
|
+
def with_signature_options
|
175
|
+
yield SignatureOptions.new
|
176
|
+
rescue SignatureOptions::MissingGemError => exn
|
177
|
+
stderr.puts Rainbow("Gem not found: name=#{exn.name}, version=#{exn.version}").red
|
178
|
+
1
|
179
|
+
rescue SignatureOptions::NoTypeDefinitionFromGemError => exn
|
180
|
+
stderr.puts Rainbow("Type definition directory not found: #{exn.gemspec.name} (#{exn.gemspec.version})").red
|
181
|
+
1
|
182
|
+
end
|
183
|
+
|
44
184
|
def process_check
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
strict = false
|
185
|
+
with_signature_options do |signature_options|
|
186
|
+
verbose = false
|
187
|
+
dump_all_types = false
|
188
|
+
fallback_any_is_error = false
|
189
|
+
strict = false
|
51
190
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end.parse!(argv)
|
60
|
-
|
61
|
-
if signature_dirs.empty?
|
62
|
-
signature_dirs << Pathname("sig")
|
63
|
-
end
|
191
|
+
OptionParser.new do |opts|
|
192
|
+
handle_dir_options opts, signature_options
|
193
|
+
opts.on("--verbose") { verbose = true }
|
194
|
+
opts.on("--dump-all-types") { dump_all_types = true }
|
195
|
+
opts.on("--strict") { strict = true }
|
196
|
+
opts.on("--fallback-any-is-error") { fallback_any_is_error = true }
|
197
|
+
end.parse!(argv)
|
64
198
|
|
65
|
-
|
66
|
-
|
67
|
-
|
199
|
+
source_paths = argv.map {|path| Pathname(path) }
|
200
|
+
if source_paths.empty?
|
201
|
+
source_paths << Pathname(".")
|
202
|
+
end
|
68
203
|
|
69
|
-
|
70
|
-
|
71
|
-
|
204
|
+
Drivers::Check.new(source_paths: source_paths, signature_dirs: signature_options.paths, stdout: stdout, stderr: stderr).tap do |check|
|
205
|
+
check.verbose = verbose
|
206
|
+
check.dump_all_types = dump_all_types
|
207
|
+
check.fallback_any_is_error = fallback_any_is_error || strict
|
208
|
+
check.allow_missing_definitions = false if strict
|
209
|
+
end.run
|
72
210
|
end
|
73
|
-
|
74
|
-
Drivers::Check.new(source_paths: source_paths, signature_dirs: signature_dirs, stdout: stdout, stderr: stderr).tap do |check|
|
75
|
-
check.verbose = verbose
|
76
|
-
check.dump_all_types = dump_all_types
|
77
|
-
check.fallback_any_is_error = fallback_any_is_error || strict
|
78
|
-
check.allow_missing_definitions = false if strict
|
79
|
-
end.run
|
80
211
|
end
|
81
212
|
|
82
213
|
def process_validate
|
83
|
-
|
84
|
-
|
214
|
+
with_signature_options do |signature_options|
|
215
|
+
verbose = false
|
85
216
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
217
|
+
OptionParser.new do |opts|
|
218
|
+
handle_dir_options opts, signature_options
|
219
|
+
opts.on("--verbose") { verbose = true }
|
220
|
+
end.parse!(argv)
|
90
221
|
|
91
|
-
|
92
|
-
|
93
|
-
|
222
|
+
Drivers::Validate.new(signature_dirs: signature_options.paths, stdout: stdout, stderr: stderr).tap do |validate|
|
223
|
+
validate.verbose = verbose
|
224
|
+
end.run
|
94
225
|
end
|
95
|
-
|
96
|
-
unless no_builtin
|
97
|
-
signature_dirs.unshift Pathname(__dir__).join("../../stdlib").realpath
|
98
|
-
end
|
99
|
-
|
100
|
-
Drivers::Validate.new(signature_dirs: signature_dirs, stdout: stdout, stderr: stderr).tap do |validate|
|
101
|
-
validate.verbose = verbose
|
102
|
-
end.run
|
103
226
|
end
|
104
227
|
|
105
228
|
def process_annotations
|
106
229
|
source_paths = argv.map {|file| Pathname(file) }
|
107
230
|
Drivers::Annotations.new(source_paths: source_paths, stdout: stdout, stderr: stderr).run
|
231
|
+
0
|
108
232
|
end
|
109
233
|
|
110
234
|
def process_scaffold
|
111
235
|
source_paths = argv.map {|file| Pathname(file) }
|
112
236
|
Drivers::Scaffold.new(source_paths: source_paths, stdout: stdout, stderr: stderr).run
|
237
|
+
0
|
113
238
|
end
|
114
239
|
|
115
240
|
def process_interface
|
116
|
-
|
117
|
-
|
241
|
+
with_signature_options do |signature_options|
|
242
|
+
OptionParser.new do |opts|
|
243
|
+
handle_dir_options opts, signature_options
|
244
|
+
end.parse!(argv)
|
118
245
|
|
119
|
-
|
120
|
-
opts.on("-I [PATH]") {|path| signature_dirs << Pathname(path) }
|
121
|
-
opts.on("--no-builtin") { no_builtin = true }
|
122
|
-
end.parse!(argv)
|
246
|
+
Drivers::PrintInterface.new(type_name: argv.first, signature_dirs: signature_options.paths, stdout: stdout, stderr: stderr).run
|
123
247
|
|
124
|
-
|
125
|
-
signature_dirs.unshift Pathname(__dir__).join("../../stdlib").realpath
|
248
|
+
0
|
126
249
|
end
|
127
|
-
|
128
|
-
Drivers::PrintInterface.new(type_name: argv.first, signature_dirs: signature_dirs, stdout: stdout, stderr: stderr).run
|
129
250
|
end
|
130
251
|
|
131
252
|
def process_version
|
132
253
|
stdout.puts Steep::VERSION
|
254
|
+
0
|
255
|
+
end
|
256
|
+
|
257
|
+
def process_paths
|
258
|
+
with_signature_options do |signature_options|
|
259
|
+
OptionParser.new do |opts|
|
260
|
+
handle_dir_options opts, signature_options
|
261
|
+
end.parse!(argv)
|
262
|
+
|
263
|
+
signature_options.paths.each do |path|
|
264
|
+
stdout.puts path
|
265
|
+
end
|
266
|
+
|
267
|
+
0
|
268
|
+
end
|
133
269
|
end
|
134
270
|
end
|
135
271
|
end
|
data/lib/steep/drivers/check.rb
CHANGED
@@ -111,11 +111,22 @@ module Steep
|
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
|
-
typing.errors.
|
115
|
-
|
116
|
-
|
114
|
+
errors = typing.errors.select do |error|
|
115
|
+
case
|
116
|
+
when error.is_a?(Errors::FallbackAny) && !fallback_any_is_error
|
117
|
+
false
|
118
|
+
when error.is_a?(Errors::MethodDefinitionMissing) && allow_missing_definitions
|
119
|
+
false
|
120
|
+
else
|
121
|
+
true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
errors.each do |error|
|
117
126
|
error.print_to stdout
|
118
127
|
end
|
128
|
+
|
129
|
+
errors.empty? ? 0 : 1
|
119
130
|
end
|
120
131
|
end
|
121
132
|
end
|
@@ -48,11 +48,14 @@ module Steep
|
|
48
48
|
puts " - #{Rainbow(method_type.to_s).red} (#{loc})"
|
49
49
|
end
|
50
50
|
end
|
51
|
+
0
|
51
52
|
rescue Steep::Subtyping::Check::CannotResolveError
|
52
53
|
stderr.puts "🤔 #{Rainbow(type.to_s).red} cannot be resolved to interface"
|
54
|
+
1
|
53
55
|
end
|
54
56
|
else
|
55
57
|
stderr.puts "Pass a type name to command line"
|
58
|
+
1
|
56
59
|
end
|
57
60
|
end
|
58
61
|
end
|
data/lib/steep/version.rb
CHANGED
data/smoke/regexp/a.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# ALLOW FAILURE
|
2
|
+
|
3
|
+
new_1 = Regexp.new("a")
|
4
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
5
|
+
new_1.foo
|
6
|
+
|
7
|
+
new_2 = Regexp.new("a", true)
|
8
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
9
|
+
new_2.foo
|
10
|
+
|
11
|
+
new_3 = Regexp.new("a", Regexp::EXTENDED | Regexp::IGNORECASE)
|
12
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
13
|
+
new_3.foo
|
14
|
+
|
15
|
+
new_4 = Regexp.new(/a/)
|
16
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
17
|
+
new_4.foo
|
18
|
+
|
19
|
+
compile_1 = Regexp.compile("a")
|
20
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
21
|
+
compile_1.foo
|
22
|
+
|
23
|
+
compile_2 = Regexp.compile("a", true)
|
24
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
25
|
+
compile_2.foo
|
26
|
+
|
27
|
+
compile_3 = Regexp.compile("a", Regexp::EXTENDED | Regexp::IGNORECASE)
|
28
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
29
|
+
compile_3.foo
|
30
|
+
|
31
|
+
compile_4 = Regexp.compile(/a/)
|
32
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
33
|
+
compile_4.foo
|
34
|
+
|
35
|
+
escape_1 = Regexp.escape("a")
|
36
|
+
# !expects NoMethodError: type=::String, method=foo
|
37
|
+
escape_1.foo
|
38
|
+
|
39
|
+
last_match_1 = Regexp.last_match
|
40
|
+
# !expects NoMethodError: type=(::MatchData | nil), method=foo
|
41
|
+
last_match_1.foo
|
42
|
+
|
43
|
+
last_match_2 = Regexp.last_match(1)
|
44
|
+
# !expects NoMethodError: type=(::String | nil), method=foo
|
45
|
+
last_match_2.foo
|
46
|
+
|
47
|
+
quote_1 = Regexp.quote("a")
|
48
|
+
# !expects NoMethodError: type=::String, method=foo
|
49
|
+
quote_1.foo
|
50
|
+
|
51
|
+
try_convert_1 = Regexp.try_convert(Object.new)
|
52
|
+
# !expects NoMethodError: type=(::Regexp | nil), method=foo
|
53
|
+
try_convert_1.foo
|
54
|
+
|
55
|
+
union_1 = Regexp.union
|
56
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
57
|
+
union_1.foo
|
58
|
+
|
59
|
+
union_2 = Regexp.union("a")
|
60
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
61
|
+
union_2.foo
|
62
|
+
|
63
|
+
union_3 = Regexp.union("a", "b")
|
64
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
65
|
+
union_3.foo
|
66
|
+
|
67
|
+
union_4 = Regexp.union(["a", "b"])
|
68
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
69
|
+
union_4.foo
|
70
|
+
|
71
|
+
union_5 = Regexp.union(/a/)
|
72
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
73
|
+
union_5.foo
|
74
|
+
|
75
|
+
union_6 = Regexp.union(/a/, /b/)
|
76
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
77
|
+
union_6.foo
|
78
|
+
|
79
|
+
union_7 = Regexp.union([/a/, /b/])
|
80
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
81
|
+
union_7.foo
|
82
|
+
|
83
|
+
op_eqeqeq_1 = /a/ === "a"
|
84
|
+
# !expects NoMethodError: type=bool, method=foo
|
85
|
+
op_eqeqeq_1.foo
|
86
|
+
|
87
|
+
op_match_1 = /a/ =~ "a"
|
88
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
89
|
+
op_match_1.foo
|
90
|
+
|
91
|
+
casefold_1 = /a/.casefold?
|
92
|
+
# !expects NoMethodError: type=bool, method=foo
|
93
|
+
casefold_1.foo
|
94
|
+
|
95
|
+
encoding_1 = /a/.encoding
|
96
|
+
# !expects NoMethodError: type=::Encoding, method=foo
|
97
|
+
encoding_1.foo
|
98
|
+
|
99
|
+
fixed_encoding_1 = /a/.fixed_encoding?
|
100
|
+
# !expects NoMethodError: type=bool, method=foo
|
101
|
+
fixed_encoding_1.foo
|
102
|
+
|
103
|
+
match_1 = /a/.match("a")
|
104
|
+
# !expects NoMethodError: type=(::MatchData | nil), method=foo
|
105
|
+
match_1.foo
|
106
|
+
|
107
|
+
match_2 = /a/.match("a", 0)
|
108
|
+
# !expects NoMethodError: type=(::MatchData | nil), method=foo
|
109
|
+
match_2.foo
|
110
|
+
|
111
|
+
/a/.match("a") do |m|
|
112
|
+
# !expects NoMethodError: type=::MatchData, method=foo
|
113
|
+
m.foo
|
114
|
+
end
|
115
|
+
|
116
|
+
/a/.match("a", 0) do |m|
|
117
|
+
# !expects NoMethodError: type=::MatchData, method=foo
|
118
|
+
m.foo
|
119
|
+
end
|
120
|
+
|
121
|
+
match_q_1 = /a/.match?("a")
|
122
|
+
# !expects NoMethodError: type=bool, method=foo
|
123
|
+
match_q_1.foo
|
124
|
+
|
125
|
+
match_q_2 = /a/.match?("a", 0)
|
126
|
+
# !expects NoMethodError: type=bool, method=foo
|
127
|
+
match_q_2.foo
|
128
|
+
|
129
|
+
named_captures_1 = /(?<foo>.)/.named_captures
|
130
|
+
# !expects NoMethodError: type=::Hash<::String, ::Array<::Integer>>, method=foo
|
131
|
+
named_captures_1.foo
|
132
|
+
|
133
|
+
names_1 = /(?<foo>.)/.names
|
134
|
+
# !expects NoMethodError: type=::Array<::String>, method=foo
|
135
|
+
names_1.foo
|
136
|
+
|
137
|
+
options_1 = /a/ix.options
|
138
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
139
|
+
options_1.foo
|
140
|
+
|
141
|
+
source_1 = /a/ix.source
|
142
|
+
# !expects NoMethodError: type=::String, method=foo
|
143
|
+
source_1.foo
|
144
|
+
|
145
|
+
op_unary_match_1 = ~ /a/
|
146
|
+
# !expects NoMethodError: type=(::Integer | nil), method=foo
|
147
|
+
op_unary_match_1.foo
|
data/smoke/regexp/b.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
/(?<foo>a)/.match("a") do |match|
|
2
|
+
match_ref_1 = match[0]
|
3
|
+
# !expects NoMethodError: type=(::String | nil), method=foo
|
4
|
+
match_ref_1.foo
|
5
|
+
|
6
|
+
match_ref_2 = match["foo"]
|
7
|
+
# !expects NoMethodError: type=(::String | nil), method=foo
|
8
|
+
match_ref_2.foo
|
9
|
+
|
10
|
+
match_ref_3 = match[:foo]
|
11
|
+
# !expects NoMethodError: type=(::String | nil), method=foo
|
12
|
+
match_ref_3.foo
|
13
|
+
|
14
|
+
match_ref_4 = match[0, 1]
|
15
|
+
# !expects NoMethodError: type=::Array<::String>, method=foo
|
16
|
+
match_ref_4.foo
|
17
|
+
|
18
|
+
match_ref_5 = match[0..1]
|
19
|
+
# !expects NoMethodError: type=::Array<::String>, method=foo
|
20
|
+
match_ref_5.foo
|
21
|
+
|
22
|
+
begin_1 = match.begin(0)
|
23
|
+
# !expects NoMethodError: type=(::Integer | nil), method=foo
|
24
|
+
begin_1.foo
|
25
|
+
|
26
|
+
begin_2 = match.begin("foo")
|
27
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
28
|
+
begin_2.foo
|
29
|
+
|
30
|
+
begin_3 = match.begin(:foo)
|
31
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
32
|
+
begin_3.foo
|
33
|
+
|
34
|
+
captures_1 = match.captures
|
35
|
+
# !expects NoMethodError: type=::Array<::String>, method=foo
|
36
|
+
captures_1.foo
|
37
|
+
|
38
|
+
end_1 = match.end(0)
|
39
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
40
|
+
end_1.foo
|
41
|
+
|
42
|
+
end_2 = match.end("foo")
|
43
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
44
|
+
end_2.foo
|
45
|
+
|
46
|
+
end_3 = match.end(:foo)
|
47
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
48
|
+
end_3.foo
|
49
|
+
|
50
|
+
length_1 = match.length
|
51
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
52
|
+
length_1.foo
|
53
|
+
|
54
|
+
named_captures_1 = match.named_captures
|
55
|
+
# !expects NoMethodError: type=::Hash<::String, (::String | nil)>, method=foo
|
56
|
+
named_captures_1.foo
|
57
|
+
|
58
|
+
names_1 = match.names
|
59
|
+
# !expects NoMethodError: type=::Array<::String>, method=foo
|
60
|
+
names_1.foo
|
61
|
+
|
62
|
+
offset_1 = match.offset(0)
|
63
|
+
# !expects NoMethodError: type=[::Integer, ::Integer], method=foo
|
64
|
+
offset_1.foo
|
65
|
+
|
66
|
+
offset_2 = match.offset("foo")
|
67
|
+
# !expects NoMethodError: type=[::Integer, ::Integer], method=foo
|
68
|
+
offset_2.foo
|
69
|
+
|
70
|
+
offset_3 = match.offset(:foo)
|
71
|
+
# !expects NoMethodError: type=[::Integer, ::Integer], method=foo
|
72
|
+
offset_3.foo
|
73
|
+
|
74
|
+
post_match_1 = match.post_match
|
75
|
+
# !expects NoMethodError: type=::String, method=foo
|
76
|
+
post_match_1.foo
|
77
|
+
|
78
|
+
pre_match_1 = match.pre_match
|
79
|
+
# !expects NoMethodError: type=::String, method=foo
|
80
|
+
pre_match_1.foo
|
81
|
+
|
82
|
+
regexp_1 = match.regexp
|
83
|
+
# !expects NoMethodError: type=::Regexp, method=foo
|
84
|
+
regexp_1.foo
|
85
|
+
|
86
|
+
size_1 = match.size
|
87
|
+
# !expects NoMethodError: type=::Integer, method=foo
|
88
|
+
size_1.foo
|
89
|
+
|
90
|
+
string_1 = match.string
|
91
|
+
# !expects NoMethodError: type=::String, method=foo
|
92
|
+
string_1.foo
|
93
|
+
|
94
|
+
to_a_1 = match.to_a
|
95
|
+
# !expects NoMethodError: type=::Array<::String>, method=foo
|
96
|
+
to_a_1.foo
|
97
|
+
|
98
|
+
values_at_1 = match.values_at
|
99
|
+
# !expects NoMethodError: type=::Array<(::String | nil)>, method=foo
|
100
|
+
values_at_1.foo
|
101
|
+
|
102
|
+
values_at_2 = match.values_at(0, "foo", :foo)
|
103
|
+
# !expects NoMethodError: type=::Array<(::String | nil)>, method=foo
|
104
|
+
values_at_2.foo
|
105
|
+
end
|
data/stdlib/builtin.rbi
CHANGED
@@ -560,10 +560,65 @@ class Enumerator<'a, 'b>
|
|
560
560
|
| -> Enumerator<['a, Integer], 'b>
|
561
561
|
end
|
562
562
|
|
563
|
+
class Encoding
|
564
|
+
end
|
565
|
+
|
563
566
|
class Regexp
|
564
|
-
def self.compile: (String
|
567
|
+
def self.compile: (String) -> Regexp
|
568
|
+
| (String, Integer) -> Regexp
|
569
|
+
| (String, bool) -> Regexp
|
570
|
+
| (Regexp) -> Regexp
|
565
571
|
def self.escape: (String) -> String
|
572
|
+
def self.last_match: -> MatchData?
|
573
|
+
| (Integer) -> String?
|
574
|
+
def self.quote: (String) -> String
|
575
|
+
def self.try_convert: (any) -> Regexp?
|
576
|
+
def self.union: (*String) -> Regexp
|
577
|
+
| (Array<String>) -> Regexp
|
578
|
+
| (*Regexp) -> Regexp
|
579
|
+
| (Array<Regexp>) -> Regexp
|
580
|
+
|
581
|
+
def initialize: (String) -> any
|
582
|
+
| (String, Integer) -> any
|
583
|
+
| (String, bool) -> any
|
584
|
+
| (Regexp) -> any
|
585
|
+
def ===: (String) -> bool
|
586
|
+
def =~: (String) -> Integer?
|
587
|
+
def casefold?: -> bool
|
588
|
+
def encoding: -> Encoding
|
589
|
+
def fixed_encoding?: -> bool
|
590
|
+
def match: (String) -> MatchData?
|
591
|
+
| (String, Integer) -> MatchData?
|
592
|
+
| <'a> (String) { (MatchData) -> 'a } -> ('a | nil)
|
593
|
+
| <'a> (String, Integer) { (MatchData) -> 'a } -> ('a | nil)
|
594
|
+
def match?: (String) -> bool
|
595
|
+
| (String, Integer) -> bool
|
596
|
+
def named_captures: -> Hash<String, Array<Integer>>
|
597
|
+
def names: -> Array<String>
|
598
|
+
def options: -> Integer
|
566
599
|
def source: -> String
|
600
|
+
def ~: -> Integer?
|
601
|
+
end
|
602
|
+
|
603
|
+
class MatchData
|
604
|
+
def []: (Integer | String | Symbol) -> String?
|
605
|
+
| (Integer, Integer) -> Array<String>
|
606
|
+
| (Range<Integer>) -> Array<String>
|
607
|
+
def begin: (Integer) -> Integer?
|
608
|
+
| (String | Symbol) -> Integer
|
609
|
+
def captures: -> Array<String>
|
610
|
+
def end: (Integer | String | Symbol) -> Integer
|
611
|
+
def length: -> Integer
|
612
|
+
def named_captures: -> Hash<String, String?>
|
613
|
+
def names: -> Array<String>
|
614
|
+
def offset: (Integer | String | Symbol) -> [Integer, Integer]
|
615
|
+
def post_match: -> String
|
616
|
+
def pre_match: -> String
|
617
|
+
def regexp: -> Regexp
|
618
|
+
def size: -> Integer
|
619
|
+
def string: -> String
|
620
|
+
def to_a: -> Array<String>
|
621
|
+
def values_at: (*(Integer | String | Symbol)) -> Array<String?>
|
567
622
|
end
|
568
623
|
|
569
624
|
class IO
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steep
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-10-
|
11
|
+
date: 2018-10-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -292,6 +292,8 @@ files:
|
|
292
292
|
- smoke/module/d.rb
|
293
293
|
- smoke/module/e.rb
|
294
294
|
- smoke/module/f.rb
|
295
|
+
- smoke/regexp/a.rb
|
296
|
+
- smoke/regexp/b.rb
|
295
297
|
- smoke/regression/array.rb
|
296
298
|
- smoke/regression/hash.rb
|
297
299
|
- smoke/regression/set_divide.rb
|