rbs 0.20.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +10 -4
  3. data/CHANGELOG.md +41 -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 +8 -4
  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: 5c422fed696c791b7cd4cbaa9c78cbdf28634d6152a1bd4496f801c539d74ac6
4
- data.tar.gz: 46012d3a5b09cb2a529620813c71d6a730b26078d409565320a60297e4153bb4
3
+ metadata.gz: 8d03121b9d58454590a45862ba1d479305feae4f2b4d10707ae8e1a3c24d4aba
4
+ data.tar.gz: f147d99859cfc7e18b41a751587f7b2cba484bf397d5b306b9fe69f15dd4b452
5
5
  SHA512:
6
- metadata.gz: 59f566eba0bb6398ee0cd4432403750ee8d3ce7e5916c61089c5c5032fff723259be3880aac88aec22d4ecaffff96c1190b18483a60feac517b3b6845bc8dae9
7
- data.tar.gz: a12d3d389eead680ff98886eff428a6b2fe4e1c3cab408866be1aa34e6a5cd3737391f370655a9798c04e73062bb0170c5be2525c66c4bf3b8aa69d21dc17750
6
+ metadata.gz: 2e325492bc73b6d9f2f62660c4e4821f7d3853780f39a957e02ad4b30fc44ca1e687fbde9d0b2843be786e51126fbb5473e1d5ae5c9c719f255bfc50fe2f7cde
7
+ data.tar.gz: '03995c9d63b9db359744338497985952eed7608729cb4a259b20af6e68de5eecdf3c996404701e2821f35d4bebfdb1e2c7c8e6289f9b5a7875fd4c6c507bde27'
@@ -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,47 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.0.1 (2021-01-27)
6
+
7
+ * Signature Updates
8
+ * PrettyPrint ([\#573](https://github.com/ruby/rbs/pull/573))
9
+ * FileUtils ([\#576](https://github.com/ruby/rbs/pull/576))
10
+ * UnboundMethod ([\#555](https://github.com/ruby/rbs/pull/555))
11
+ * IO ([\#571](https://github.com/ruby/rbs/pull/571))
12
+ * Kernel ([\#549](https://github.com/ruby/rbs/pull/549), [\#569](https://github.com/ruby/rbs/pull/569))
13
+ * File ([\#552](https://github.com/ruby/rbs/pull/552))
14
+ * Data is removed ([\#570](https://github.com/ruby/rbs/pull/570))
15
+ * Module ([\#568](https://github.com/ruby/rbs/pull/568))
16
+ * Object ([\#557](https://github.com/ruby/rbs/pull/557))
17
+ * Renew test sample code ([#581](https://github.com/ruby/rbs/pull/581))
18
+ * Add description to `generate:stdlib_test` Rake task ([\#578](https://github.com/ruby/rbs/pull/578))
19
+ * Declare supported ruby version >= 2.6 ([\#548](https://github.com/ruby/rbs/pull/548))
20
+ * Fix module self-type override ([\#577](https://github.com/ruby/rbs/pull/577))
21
+ * Fix parser to support all operator symbols ([\#550](https://github.com/ruby/rbs/pull/550))
22
+ * Migrate from Minitest to Test::Unit ([\#556](https://github.com/ruby/rbs/pull/556))
23
+ * Fix type alias parsing ([\#565](https://github.com/ruby/rbs/pull/565))
24
+ * Support end-less method definition in `prototype rb` ([\#561](https://github.com/ruby/rbs/pull/561))
25
+ * Support method argument forwarding in `prototype rb` ([\#560](https://github.com/ruby/rbs/pull/560))
26
+
27
+ ## 1.0.0 (2020-12-24)
28
+
29
+ * 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))
30
+ * `rbs prototype runtime` generates `extend`s ([#535](https://github.com/ruby/rbs/pull/535))
31
+ * `rbs prototype runtime` stability improvements ([#533](https://github.com/ruby/rbs/pull/533), [#526](https://github.com/ruby/rbs/pull/526))
32
+ * `rbs prototype rb` compatibility improvements ([#545](https://github.com/ruby/rbs/pull/545))
33
+ * Implement method names escape in `RBS::Writer` ([#537](https://github.com/ruby/rbs/pull/537))
34
+ * 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))
35
+ * Fix `ruby2_keywords` for `Proc` in Ruby <2.7 ([#513](https://github.com/ruby/rbs/pull/513))
36
+ * Better compatibility for record type attribute names ([#525](https://github.com/ruby/rbs/pull/525), [#524](https://github.com/ruby/rbs/pull/524))
37
+ * Let module self-types be classes ([#523](https://github.com/ruby/rbs/pull/523))
38
+ * Delete `extension` syntax ([#543](https://github.com/ruby/rbs/pull/543))
39
+ * 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))
40
+ * Better message for `DuplicatedMethodDefinitionError` ([#539](https://github.com/ruby/rbs/pull/539))
41
+
42
+ ## 0.20.1 (2020-12-06)
43
+
44
+ * Make the order of RBS load reproducible ([#508](https://github.com/ruby/rbs/pull/508))
45
+
5
46
  ## 0.20.0 (2020-12-06)
6
47
 
7
48
  * Signature updates for `TSort`, `DBM`, `Time`, and `Hash` ([#496](https://github.com/ruby/rbs/pull/496), [#497](https://github.com/ruby/rbs/pull/497), [#499](https://github.com/ruby/rbs/pull/499), [#507](https://github.com/ruby/rbs/pull/507))
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]