rbs 0.20.1 → 1.0.2

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +10 -4
  3. data/CHANGELOG.md +42 -0
  4. data/Gemfile +7 -2
  5. data/README.md +1 -1
  6. data/Rakefile +15 -4
  7. data/Steepfile +2 -1
  8. data/bin/annotate-with-rdoc +0 -4
  9. data/bin/test_runner.rb +4 -5
  10. data/core/builtin.rbs +4 -0
  11. data/core/encoding.rbs +1 -1
  12. data/core/file.rbs +4 -0
  13. data/core/io.rbs +240 -11
  14. data/core/kernel.rbs +57 -57
  15. data/core/module.rbs +43 -2
  16. data/core/unbound_method.rbs +16 -0
  17. data/docs/CONTRIBUTING.md +2 -2
  18. data/docs/stdlib.md +50 -12
  19. data/docs/syntax.md +0 -17
  20. data/goodcheck.yml +23 -3
  21. data/lib/rbs.rb +2 -0
  22. data/lib/rbs/ast/declarations.rb +7 -49
  23. data/lib/rbs/ast/members.rb +1 -1
  24. data/lib/rbs/cli.rb +10 -10
  25. data/lib/rbs/definition.rb +70 -3
  26. data/lib/rbs/definition_builder.rb +580 -1006
  27. data/lib/rbs/definition_builder/ancestor_builder.rb +525 -0
  28. data/lib/rbs/definition_builder/method_builder.rb +217 -0
  29. data/lib/rbs/environment.rb +3 -8
  30. data/lib/rbs/environment_loader.rb +7 -3
  31. data/lib/rbs/errors.rb +88 -121
  32. data/lib/rbs/parser.rb +1017 -995
  33. data/lib/rbs/parser.y +25 -23
  34. data/lib/rbs/prototype/rb.rb +19 -5
  35. data/lib/rbs/prototype/rbi.rb +1 -1
  36. data/lib/rbs/prototype/runtime.rb +70 -34
  37. data/lib/rbs/substitution.rb +4 -0
  38. data/lib/rbs/test.rb +3 -1
  39. data/lib/rbs/test/hook.rb +22 -7
  40. data/lib/rbs/test/setup_helper.rb +0 -1
  41. data/lib/rbs/types.rb +6 -2
  42. data/lib/rbs/validator.rb +4 -2
  43. data/lib/rbs/variance_calculator.rb +5 -1
  44. data/lib/rbs/version.rb +1 -1
  45. data/lib/rbs/writer.rb +4 -3
  46. data/rbs.gemspec +1 -0
  47. data/sig/ancestor_builder.rbs +98 -0
  48. data/sig/declarations.rbs +4 -16
  49. data/sig/definition.rbs +6 -1
  50. data/sig/definition_builder.rbs +17 -71
  51. data/sig/errors.rbs +159 -0
  52. data/sig/method_builder.rbs +71 -0
  53. data/sig/substitution.rbs +3 -0
  54. data/sig/type_name_resolver.rbs +4 -2
  55. data/sig/types.rbs +1 -15
  56. data/sig/validator.rbs +12 -0
  57. data/stdlib/csv/0/csv.rbs +3 -0
  58. data/stdlib/fileutils/0/fileutils.rbs +585 -0
  59. data/stdlib/logger/0/log_device.rbs +1 -2
  60. data/stdlib/pathname/0/pathname.rbs +2 -2
  61. data/stdlib/prettyprint/0/prettyprint.rbs +366 -0
  62. data/stdlib/prime/0/prime.rbs +6 -0
  63. data/stdlib/securerandom/0/securerandom.rbs +2 -0
  64. data/stdlib/time/0/time.rbs +327 -0
  65. data/stdlib/uri/0/common.rbs +401 -0
  66. data/stdlib/uri/0/rfc2396_parser.rbs +9 -0
  67. data/stdlib/uri/0/rfc3986_parser.rbs +2 -0
  68. data/steep/Gemfile.lock +10 -11
  69. metadata +16 -5
  70. data/core/data.rbs +0 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d0358484cf9cfd6a58aba4115025628e9af481fbeb11079ba189e387486bd85
4
- data.tar.gz: 01fa1f2883a0faa043d5116118e6d4bbebb33dc3290d32d9404935817e589643
3
+ metadata.gz: f770aaafebf7f9377990a42eb6d3bb32e733166ecd86407ffc62d386839f9cf0
4
+ data.tar.gz: c6421b9f56d6041e63862147656e1f369d9cc057e3ee35b140fe8fccab0101a4
5
5
  SHA512:
6
- metadata.gz: 7a16ce63cf0d28ba0834f7a702767aa5dcb7440a0ef83d00f443e6877977abdb751c6e7816266d45af44cbe21b3eafc7a563edfdf678662a8412f4d8b758d80c
7
- data.tar.gz: 45e237d7de22114e7f6d22f138b2850645067993c9577581842464bec7d06937a7427d13d9821d93088008f0ea838b6e475b43725d3b16b60c0e3c821b7fef93
6
+ metadata.gz: 49dea6bbe71560ffd16a38d66716cc0e7f00293d0bb1c4be9951c65185df5286cab8ca0e49a1d2d13cd1b05f97d8695e9242f3e4a356ad3db6225b3bfc4bfbba
7
+ data.tar.gz: 57ad2767f7d652ba5fda881d5fcb8f67dc6a7f631a13369026946df9a5f70c72c6497d9fdaa9a540b128285ba4d83a5fcdd1548c0ee9542048e09835e153abc2
@@ -12,8 +12,8 @@ jobs:
12
12
  strategy:
13
13
  matrix:
14
14
  container_tag:
15
- - master-nightly-bionic
16
- - 2.6-bionic
15
+ - master-nightly-focal
16
+ - 3.0-focal
17
17
  - 2.7-bionic
18
18
  job:
19
19
  - test
@@ -27,12 +27,18 @@ jobs:
27
27
  run: |
28
28
  apt-get update
29
29
  apt-get install -y libdb-dev
30
- - name: Install
30
+ - name: Install bundler
31
31
  run: |
32
32
  ruby -v
33
33
  gem install bundler
34
+ - name: bundle config set with
35
+ run: |
36
+ echo "NO_MINITEST=true" >> $GITHUB_ENV
37
+ bundle config set --local without 'minitest'
38
+ if: "contains(matrix.container_tag, 'master-nightly')"
39
+ - name: bin/setup
40
+ run: |
34
41
  bin/setup
35
42
  - name: Run test
36
43
  run: |
37
44
  bundle exec rake ${{ matrix.job }}
38
- if: "!(matrix.job == 'stdlib_test' && contains(matrix.container_tag, '2.6'))"
@@ -2,6 +2,48 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.0.2 (2021-01-28)
6
+
7
+ * Signature Updates
8
+ * Kernel([#582](https://github.com/ruby/rbs/pull/582))
9
+
10
+ ## 1.0.1 (2021-01-27)
11
+
12
+ * Signature Updates
13
+ * PrettyPrint ([\#573](https://github.com/ruby/rbs/pull/573))
14
+ * FileUtils ([\#576](https://github.com/ruby/rbs/pull/576))
15
+ * UnboundMethod ([\#555](https://github.com/ruby/rbs/pull/555))
16
+ * IO ([\#571](https://github.com/ruby/rbs/pull/571))
17
+ * Kernel ([\#549](https://github.com/ruby/rbs/pull/549), [\#569](https://github.com/ruby/rbs/pull/569))
18
+ * File ([\#552](https://github.com/ruby/rbs/pull/552))
19
+ * Data is removed ([\#570](https://github.com/ruby/rbs/pull/570))
20
+ * Module ([\#568](https://github.com/ruby/rbs/pull/568))
21
+ * Object ([\#557](https://github.com/ruby/rbs/pull/557))
22
+ * Renew test sample code ([#581](https://github.com/ruby/rbs/pull/581))
23
+ * Add description to `generate:stdlib_test` Rake task ([\#578](https://github.com/ruby/rbs/pull/578))
24
+ * Declare supported ruby version >= 2.6 ([\#548](https://github.com/ruby/rbs/pull/548))
25
+ * Fix module self-type override ([\#577](https://github.com/ruby/rbs/pull/577))
26
+ * Fix parser to support all operator symbols ([\#550](https://github.com/ruby/rbs/pull/550))
27
+ * Migrate from Minitest to Test::Unit ([\#556](https://github.com/ruby/rbs/pull/556))
28
+ * Fix type alias parsing ([\#565](https://github.com/ruby/rbs/pull/565))
29
+ * Support end-less method definition in `prototype rb` ([\#561](https://github.com/ruby/rbs/pull/561))
30
+ * Support method argument forwarding in `prototype rb` ([\#560](https://github.com/ruby/rbs/pull/560))
31
+
32
+ ## 1.0.0 (2020-12-24)
33
+
34
+ * Signature updates for `URI`, `IO`, `File`, `Pathname`, `Module`, and `Time` ([#529](https://github.com/ruby/rbs/pull/529), [#521](https://github.com/ruby/rbs/pull/521), [#520](https://github.com/ruby/rbs/pull/520), [#511](https://github.com/ruby/rbs/pull/511), [#517](https://github.com/ruby/rbs/pull/517), [#542](https://github.com/ruby/rbs/pull/542), [#546](https://github.com/ruby/rbs/pull/546), [#540](https://github.com/ruby/rbs/pull/540), [#538](https://github.com/ruby/rbs/pull/538))
35
+ * `rbs prototype runtime` generates `extend`s ([#535](https://github.com/ruby/rbs/pull/535))
36
+ * `rbs prototype runtime` stability improvements ([#533](https://github.com/ruby/rbs/pull/533), [#526](https://github.com/ruby/rbs/pull/526))
37
+ * `rbs prototype rb` compatibility improvements ([#545](https://github.com/ruby/rbs/pull/545))
38
+ * Implement method names escape in `RBS::Writer` ([#537](https://github.com/ruby/rbs/pull/537))
39
+ * Improve runtime type checker compatibility ([#532](https://github.com/ruby/rbs/pull/532), [#528](https://github.com/ruby/rbs/pull/528), [#547](https://github.com/ruby/rbs/pull/547))
40
+ * Fix `ruby2_keywords` for `Proc` in Ruby <2.7 ([#513](https://github.com/ruby/rbs/pull/513))
41
+ * Better compatibility for record type attribute names ([#525](https://github.com/ruby/rbs/pull/525), [#524](https://github.com/ruby/rbs/pull/524))
42
+ * Let module self-types be classes ([#523](https://github.com/ruby/rbs/pull/523))
43
+ * Delete `extension` syntax ([#543](https://github.com/ruby/rbs/pull/543))
44
+ * Method resolution improvements about `alias` and `.new` ([#522](https://github.com/ruby/rbs/pull/522), [#519](https://github.com/ruby/rbs/pull/519), [#516](https://github.com/ruby/rbs/pull/516))
45
+ * Better message for `DuplicatedMethodDefinitionError` ([#539](https://github.com/ruby/rbs/pull/539))
46
+
5
47
  ## 0.20.1 (2020-12-06)
6
48
 
7
49
  * Make the order of RBS load reproducible ([#508](https://github.com/ruby/rbs/pull/508))
data/Gemfile CHANGED
@@ -5,12 +5,12 @@ gemspec
5
5
 
6
6
  # Development dependencies
7
7
  gem "rake"
8
- gem "minitest"
8
+ gem "test-unit"
9
+ gem "test-unit-rr"
9
10
  gem "rspec"
10
11
  gem "racc"
11
12
  gem "rubocop"
12
13
  gem "rubocop-rubycw"
13
- gem "minitest-reporters"
14
14
  gem "json"
15
15
  gem "json-schema"
16
16
  gem 'stackprof'
@@ -22,4 +22,9 @@ gem "rbs-amber", path: "test/assets/test-gem"
22
22
 
23
23
  group :ide, optional: true do
24
24
  gem "ruby-debug-ide"
25
+ gem "debase", ">= 0.2.5.beta2"
26
+ end
27
+
28
+ group :minitest do
29
+ gem "minitest"
25
30
  end
data/README.md CHANGED
@@ -107,7 +107,7 @@ instance = builder.build_instance(string)
107
107
 
108
108
  # Print the types of `gsub` method:
109
109
  puts instance.methods[:gsub].method_types.join("\n")
110
- # Ouputs =>
110
+ # Outputs =>
111
111
  # (::Regexp | ::string pattern, ::string replacement) -> ::String
112
112
  # (::Regexp | ::string pattern, ::Hash[::String, ::String] hash) -> ::String
113
113
  # (::Regexp | ::string pattern) { (::String match) -> ::_ToS } -> ::String
data/Rakefile CHANGED
@@ -28,8 +28,6 @@ task :validate => :parser do
28
28
  sh "#{ruby} #{rbs} validate --silent"
29
29
 
30
30
  FileList["stdlib/*"].each do |path|
31
- next if path =~ %r{stdlib/builtin}
32
-
33
31
  lib = [File.basename(path).to_s]
34
32
 
35
33
  if lib == ["bigdecimal-math"]
@@ -41,6 +39,18 @@ task :validate => :parser do
41
39
  lib << "pstore"
42
40
  end
43
41
 
42
+ if lib == ["logger"]
43
+ lib << "monitor"
44
+ end
45
+
46
+ if lib == ["csv"]
47
+ lib << "forwardable"
48
+ end
49
+
50
+ if lib == ["prime"]
51
+ lib << "singleton"
52
+ end
53
+
44
54
  sh "#{ruby} #{rbs} #{lib.map {|l| "-r #{l}"}.join(" ")} validate --silent"
45
55
  end
46
56
  end
@@ -72,6 +82,7 @@ task :confirm_parser do
72
82
  end
73
83
 
74
84
  namespace :generate do
85
+ desc "Generate a test file for a stdlib class signatures"
75
86
  task :stdlib_test, [:class] do |_task, args|
76
87
  klass = args.fetch(:class) do
77
88
  raise "Class name is necessary. e.g. rake 'generate:stdlib_test[String]'"
@@ -103,7 +114,7 @@ namespace :generate do
103
114
  require_relative "test_helper"
104
115
 
105
116
  <%- unless class_methods.empty? -%>
106
- class <%= klass %>SingletonTest < Minitest::Test
117
+ class <%= klass %>SingletonTest < Test::Unit::TestCase
107
118
  include TypeAssertions
108
119
 
109
120
  # library "pathname", "set", "securerandom" # Declare library signatures to load
@@ -121,7 +132,7 @@ namespace :generate do
121
132
  <%- end -%>
122
133
 
123
134
  <%- unless instance_methods.empty? -%>
124
- class <%= klass %>Test < Minitest::Test
135
+ class <%= klass %>Test < Test::Unit::TestCase
125
136
  include TypeAssertions
126
137
 
127
138
  # library "pathname", "set", "securerandom" # Declare library signatures to load
data/Steepfile CHANGED
@@ -2,8 +2,9 @@ target :lib do
2
2
  signature "sig"
3
3
  check "lib"
4
4
  ignore "lib/rbs/parser.rb"
5
+ ignore "lib/rbs/prototype", "lib/rbs/test", "lib/rbs/test.rb"
5
6
 
6
- library "set", "pathname", "json", "logger"
7
+ library "set", "pathname", "json", "logger", "monitor", "tsort"
7
8
  end
8
9
 
9
10
  # target :lib do
@@ -140,10 +140,6 @@ ARGV.map {|f| Pathname(f) }.each do |path|
140
140
  comment = comment_for_class(decl, stores: stores)
141
141
  decl.instance_variable_set(:@comment, comment)
142
142
 
143
- print_members stores, decl.name.to_s, decl.members
144
- when RBS::AST::Declarations::Extension
145
- puts " Importing documentation for #{decl.name} (#{decl.extension_name})"
146
-
147
143
  print_members stores, decl.name.to_s, decl.members
148
144
  end
149
145
  end
@@ -4,13 +4,12 @@ $LOAD_PATH << File.join(__dir__, "../lib")
4
4
 
5
5
  require "set"
6
6
 
7
- IS_RUBY_27 = Gem::Version.new(RUBY_VERSION).yield_self do |ruby_version|
8
- Gem::Version.new('2.7.0') <= ruby_version &&
9
- ruby_version <= Gem::Version.new('2.8.0')
7
+ IS_LATEST_RUBY = Gem::Version.new(RUBY_VERSION).yield_self do |ruby_version|
8
+ Gem::Version.new('3.0.0') <= ruby_version && ruby_version < Gem::Version.new('3.1.0')
10
9
  end
11
10
 
12
- unless IS_RUBY_27
13
- STDERR.puts "⚠️⚠️⚠️⚠️ stdlib test assumes Ruby 2.7 but RUBY_VERSION==#{RUBY_VERSION} ⚠️⚠️⚠️⚠️"
11
+ unless IS_LATEST_RUBY
12
+ STDERR.puts "⚠️⚠️⚠️⚠️ stdlib test assumes Ruby 3.0 but RUBY_VERSION==#{RUBY_VERSION} ⚠️⚠️⚠️⚠️"
14
13
  end
15
14
 
16
15
  KNOWN_FAILS = %w(dbm).map do |lib|
@@ -34,6 +34,10 @@ interface _Reader
34
34
  def read: (?int length, ?string outbuf) -> String?
35
35
  end
36
36
 
37
+ interface _ReaderPartial
38
+ def readpartial: (int maxlen, ?string outbuf) -> String
39
+ end
40
+
37
41
  interface _Writer
38
42
  # Writes the +data+ string. Returns the number of bytes written
39
43
  def write: (*_ToS data) -> Integer
@@ -567,7 +567,7 @@ Encoding::Windows_31J: Encoding
567
567
 
568
568
  Encoding::Windows_874: Encoding
569
569
 
570
- class Encoding::Converter < Data
570
+ class Encoding::Converter < Object
571
571
  end
572
572
 
573
573
  Encoding::Converter::AFTER_OUTPUT: Integer
@@ -531,6 +531,10 @@ class File < IO
531
531
  #
532
532
  def self.mtime: (string | _ToPath | IO file_name) -> Time
533
533
 
534
+ # Alias of `File.new`.
535
+ def self.open: (string | _ToPath | int file_name, ?(string | int) mode, ?int perm) -> instance
536
+ | [T] (string | _ToPath | int file_name, ?(string | int) mode, ?int perm) { (File) -> T } -> T
537
+
534
538
  # Returns `true` if the named file exists and the effective used id of the
535
539
  # calling process is the owner of the file.
536
540
  #
@@ -107,14 +107,85 @@ class IO < Object
107
107
 
108
108
  include Enumerable[String]
109
109
 
110
- def <<: (untyped arg0) -> self
110
+ # String Output---Writes *obj* to *ios*. *obj* will be converted to a string
111
+ # using `to_s`.
112
+ #
113
+ # $stdout << "Hello " << "world!\n"
114
+ #
115
+ # *produces:*
116
+ #
117
+ # Hello world!
118
+ #
119
+ def <<: (_ToS obj) -> self
111
120
 
112
- def advise: (Symbol arg0, ?Integer offset, ?Integer len) -> NilClass
121
+ # Announce an intention to access data from the current file in a specific
122
+ # pattern. On platforms that do not support the *posix_fadvise(2)* system call,
123
+ # this method is a no-op.
124
+ #
125
+ # *advice* is one of the following symbols:
126
+ #
127
+ # :normal
128
+ # : No advice to give; the default assumption for an open file.
129
+ # :sequential
130
+ # : The data will be accessed sequentially with lower offsets read before
131
+ # higher ones.
132
+ # :random
133
+ # : The data will be accessed in random order.
134
+ # :willneed
135
+ # : The data will be accessed in the near future.
136
+ # :dontneed
137
+ # : The data will not be accessed in the near future.
138
+ # :noreuse
139
+ # : The data will only be accessed once.
140
+ #
141
+ #
142
+ # The semantics of a piece of advice are platform-dependent. See *man 2
143
+ # posix_fadvise* for details.
144
+ #
145
+ # "data" means the region of the current file that begins at *offset* and
146
+ # extends for *len* bytes. If *len* is 0, the region ends at the last byte of
147
+ # the file. By default, both *offset* and *len* are 0, meaning that the advice
148
+ # applies to the entire file.
149
+ #
150
+ # If an error occurs, one of the following exceptions will be raised:
151
+ #
152
+ # IOError
153
+ # : The IO stream is closed.
154
+ # Errno::EBADF
155
+ # : The file descriptor of the current file is invalid.
156
+ # Errno::EINVAL
157
+ # : An invalid value for *advice* was given.
158
+ # Errno::ESPIPE
159
+ # : The file descriptor of the current file refers to a FIFO or pipe. (Linux
160
+ # raises Errno::EINVAL in this case).
161
+ # TypeError
162
+ # : Either *advice* was not a Symbol, or one of the other arguments was not an
163
+ # Integer.
164
+ # RangeError
165
+ # : One of the arguments given was too big/small.
166
+ #
167
+ # This list is not exhaustive; other Errno
168
+ # : exceptions are also possible.
169
+ #
170
+ def advise: ((:normal | :sequential | :random | :willneed | :dontneed | :noreuse) advise, ?Integer offset, ?Integer len) -> nil
113
171
 
114
- def autoclose=: (boolish) -> bool
172
+ # Sets auto-close flag.
173
+ #
174
+ # f = open("/dev/null")
175
+ # IO.for_fd(f.fileno)
176
+ # # ...
177
+ # f.gets # may cause Errno::EBADF
178
+ #
179
+ # f = open("/dev/null")
180
+ # IO.for_fd(f.fileno).autoclose = false
181
+ # # ...
182
+ # f.gets # won't cause Errno::EBADF
183
+ #
184
+ def autoclose=: (bool) -> bool
115
185
 
116
186
  # Returns `true` if the underlying file descriptor of *ios* will be closed
117
- # automatically at its finalization, otherwise `false` .
187
+ # automatically at its finalization, otherwise `false`.
188
+ #
118
189
  def autoclose?: () -> bool
119
190
 
120
191
  # Puts *ios* into binary mode. Once a stream is in binary mode, it cannot
@@ -405,7 +476,63 @@ class IO < Object
405
476
 
406
477
  def puts: (*untyped arg0) -> NilClass
407
478
 
408
- def read: (?Integer length, ?String outbuf) -> String?
479
+ # Reads *length* bytes from the I/O stream.
480
+ #
481
+ # *length* must be a non-negative integer or `nil`.
482
+ #
483
+ # If *length* is a positive integer, `read` tries to read *length* bytes without
484
+ # any conversion (binary mode). It returns `nil` if an EOF is encountered before
485
+ # anything can be read. Fewer than *length* bytes are returned if an EOF is
486
+ # encountered during the read. In the case of an integer *length*, the resulting
487
+ # string is always in ASCII-8BIT encoding.
488
+ #
489
+ # If *length* is omitted or is `nil`, it reads until EOF and the encoding
490
+ # conversion is applied, if applicable. A string is returned even if EOF is
491
+ # encountered before any data is read.
492
+ #
493
+ # If *length* is zero, it returns an empty string (`""`).
494
+ #
495
+ # If the optional *outbuf* argument is present, it must reference a String,
496
+ # which will receive the data. The *outbuf* will contain only the received data
497
+ # after the method call even if it is not empty at the beginning.
498
+ #
499
+ # When this method is called at end of file, it returns `nil` or `""`, depending
500
+ # on *length*: `read`, `read(nil)`, and `read(0)` return `""`,
501
+ # `read(*positive_integer*)` returns `nil`.
502
+ #
503
+ # f = File.new("testfile")
504
+ # f.read(16) #=> "This is line one"
505
+ #
506
+ # # read whole file
507
+ # open("file") do |f|
508
+ # data = f.read # This returns a string even if the file is empty.
509
+ # # ...
510
+ # end
511
+ #
512
+ # # iterate over fixed length records
513
+ # open("fixed-record-file") do |f|
514
+ # while record = f.read(256)
515
+ # # ...
516
+ # end
517
+ # end
518
+ #
519
+ # # iterate over variable length records,
520
+ # # each record is prefixed by its 32-bit length
521
+ # open("variable-record-file") do |f|
522
+ # while len = f.read(4)
523
+ # len = len.unpack("N")[0] # 32-bit length
524
+ # record = f.read(len) # This returns a string even if len is 0.
525
+ # end
526
+ # end
527
+ #
528
+ # Note that this method behaves like the fread() function in C. This means it
529
+ # retries to invoke read(2) system calls to read data with the specified length
530
+ # (or until EOF). This behavior is preserved even if *ios* is in non-blocking
531
+ # mode. (This method is non-blocking flag insensitive as other methods.) If you
532
+ # need the behavior like a single read(2) system call, consider #readpartial,
533
+ # #read_nonblock, and #sysread.
534
+ #
535
+ def read: (?Integer? length, ?String outbuf) -> String?
409
536
 
410
537
  def read_nonblock: (Integer len) -> String
411
538
  | (Integer len, ?String buf) -> String
@@ -428,8 +555,63 @@ class IO < Object
428
555
 
429
556
  def readlines: (?String sep, ?Integer limit) -> ::Array[String]
430
557
 
431
- def readpartial: (Integer maxlen) -> String
432
- | (Integer maxlen, ?String outbuf) -> String
558
+ # Reads at most *maxlen* bytes from the I/O stream. It blocks only if *ios* has
559
+ # no data immediately available. It doesn't block if some data available.
560
+ #
561
+ # If the optional *outbuf* argument is present, it must reference a String,
562
+ # which will receive the data. The *outbuf* will contain only the received data
563
+ # after the method call even if it is not empty at the beginning.
564
+ #
565
+ # It raises EOFError on end of file.
566
+ #
567
+ # readpartial is designed for streams such as pipe, socket, tty, etc. It blocks
568
+ # only when no data immediately available. This means that it blocks only when
569
+ # following all conditions hold.
570
+ # * the byte buffer in the IO object is empty.
571
+ # * the content of the stream is empty.
572
+ # * the stream is not reached to EOF.
573
+ #
574
+ #
575
+ # When readpartial blocks, it waits data or EOF on the stream. If some data is
576
+ # reached, readpartial returns with the data. If EOF is reached, readpartial
577
+ # raises EOFError.
578
+ #
579
+ # When readpartial doesn't blocks, it returns or raises immediately. If the byte
580
+ # buffer is not empty, it returns the data in the buffer. Otherwise if the
581
+ # stream has some content, it returns the data in the stream. Otherwise if the
582
+ # stream is reached to EOF, it raises EOFError.
583
+ #
584
+ # r, w = IO.pipe # buffer pipe content
585
+ # w << "abc" # "" "abc".
586
+ # r.readpartial(4096) #=> "abc" "" ""
587
+ # r.readpartial(4096) # blocks because buffer and pipe is empty.
588
+ #
589
+ # r, w = IO.pipe # buffer pipe content
590
+ # w << "abc" # "" "abc"
591
+ # w.close # "" "abc" EOF
592
+ # r.readpartial(4096) #=> "abc" "" EOF
593
+ # r.readpartial(4096) # raises EOFError
594
+ #
595
+ # r, w = IO.pipe # buffer pipe content
596
+ # w << "abc\ndef\n" # "" "abc\ndef\n"
597
+ # r.gets #=> "abc\n" "def\n" ""
598
+ # w << "ghi\n" # "def\n" "ghi\n"
599
+ # r.readpartial(4096) #=> "def\n" "" "ghi\n"
600
+ # r.readpartial(4096) #=> "ghi\n" "" ""
601
+ #
602
+ # Note that readpartial behaves similar to sysread. The differences are:
603
+ # * If the byte buffer is not empty, read from the byte buffer instead of
604
+ # "sysread for buffered IO (IOError)".
605
+ # * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial
606
+ # meets EWOULDBLOCK and EINTR by read system call, readpartial retry the
607
+ # system call.
608
+ #
609
+ #
610
+ # The latter means that readpartial is nonblocking-flag insensitive. It blocks
611
+ # on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking
612
+ # mode.
613
+ #
614
+ def readpartial: (Integer maxlen, ?String outbuf) -> String
433
615
 
434
616
  def reopen: (IO other_IO_or_path) -> IO
435
617
  | (String other_IO_or_path, ?String mode_str) -> IO
@@ -508,13 +690,55 @@ class IO < Object
508
690
 
509
691
  def ungetc: (String arg0) -> NilClass
510
692
 
511
- def write: (*_ToS arg0) -> Integer
693
+ # Writes the given strings to *ios*. The stream must be opened for writing.
694
+ # Arguments that are not a string will be converted to a string using `to_s`.
695
+ # Returns the number of bytes written in total.
696
+ #
697
+ # count = $stdout.write("This is", " a test\n")
698
+ # puts "That was #{count} bytes of data"
699
+ #
700
+ # *produces:*
701
+ #
702
+ # This is a test
703
+ # That was 15 bytes of data
704
+ #
705
+ def write: (*_ToS string) -> Integer
512
706
 
707
+ # Opens the file, optionally seeks to the given *offset*, then returns *length*
708
+ # bytes (defaulting to the rest of the file). #binread ensures the file is
709
+ # closed before returning. The open mode would be `"rb:ASCII-8BIT"`.
710
+ #
711
+ # IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
712
+ # IO.binread("testfile", 20) #=> "This is line one\nThi"
713
+ # IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
714
+ #
513
715
  def self.binread: (String name, ?Integer length, ?Integer offset) -> String
514
716
 
515
- def self.binwrite: (String name, _ToS arg0, ?Integer offset, ?external_encoding: String external_encoding, ?internal_encoding: String internal_encoding, ?encoding: String encoding, ?textmode: untyped textmode, ?binmode: untyped binmode, ?autoclose: untyped autoclose, ?mode: String mode) -> Integer
717
+ # Same as IO.write except opening the file in binary mode and ASCII-8BIT
718
+ # encoding (`"wb:ASCII-8BIT"`).
719
+ #
720
+ def self.binwrite: (String name, _ToS string, ?Integer offset, ?mode: String mode) -> Integer
516
721
 
517
- def self.copy_stream: (_Reader src, _Writer dst, ?Integer copy_length, ?Integer src_offset) -> Integer
722
+ # IO.copy_stream copies *src* to *dst*. *src* and *dst* is either a filename or
723
+ # an IO-like object. IO-like object for *src* should have #readpartial or #read
724
+ # method. IO-like object for *dst* should have #write method. (Specialized
725
+ # mechanisms, such as sendfile system call, may be used on appropriate
726
+ # situation.)
727
+ #
728
+ # This method returns the number of bytes copied.
729
+ #
730
+ # If optional arguments are not given, the start position of the copy is the
731
+ # beginning of the filename or the current file offset of the IO. The end
732
+ # position of the copy is the end of file.
733
+ #
734
+ # If *copy_length* is given, No more than *copy_length* bytes are copied.
735
+ #
736
+ # If *src_offset* is given, it specifies the start position of the copy.
737
+ #
738
+ # When *src_offset* is specified and *src* is an IO, IO.copy_stream doesn't move
739
+ # the current file offset.
740
+ #
741
+ def self.copy_stream: ((String | _Reader | _ReaderPartial) src, (String | _Writer) dst, ?Integer copy_length, ?Integer src_offset) -> Integer
518
742
 
519
743
  def self.popen: (*untyped args) -> untyped
520
744
 
@@ -530,7 +754,12 @@ class IO < Object
530
754
 
531
755
  def self.write: (String name, _ToS arg0, ?Integer offset, ?external_encoding: String external_encoding, ?internal_encoding: String internal_encoding, ?encoding: String encoding, ?textmode: untyped textmode, ?binmode: untyped binmode, ?autoclose: untyped autoclose, ?mode: String mode) -> Integer
532
756
 
533
- def self.for_fd: (Integer fd, ?Integer mode, ?Integer opt) -> self
757
+ def self.for_fd: (int fd, ?(string | int) mode, **untyped opt) -> instance
758
+
759
+ alias self.open self.for_fd
760
+
761
+ def self.open: [A] (int fd, ?(string | int) mode, **untyped opt) { (instance) -> A } -> A
762
+ | ...
534
763
 
535
764
  def bytes: () { (Integer arg0) -> untyped } -> self
536
765
  | () -> ::Enumerator[Integer, self]