rbs 0.20.1 → 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7d0358484cf9cfd6a58aba4115025628e9af481fbeb11079ba189e387486bd85
4
- data.tar.gz: 01fa1f2883a0faa043d5116118e6d4bbebb33dc3290d32d9404935817e589643
3
+ metadata.gz: fd21602800550be064e741db770aa752eaab018ca894238f88d75d1d1e950edd
4
+ data.tar.gz: 346c39ff339931cf9866e29cd096a0877c620feff86044a2bbb007826276904b
5
5
  SHA512:
6
- metadata.gz: 7a16ce63cf0d28ba0834f7a702767aa5dcb7440a0ef83d00f443e6877977abdb751c6e7816266d45af44cbe21b3eafc7a563edfdf678662a8412f4d8b758d80c
7
- data.tar.gz: 45e237d7de22114e7f6d22f138b2850645067993c9577581842464bec7d06937a7427d13d9821d93088008f0ea838b6e475b43725d3b16b60c0e3c821b7fef93
6
+ metadata.gz: 94651715eeed037f3d899fdae1cc49dc5134f5d3df7da03d06b7ebc7a053d43139adf29680de4a0036446afb16ef824862fae4ad5a6870861ae48bd589799ac6
7
+ data.tar.gz: ec967eef1ab035d4da2fe66f8a4661523c672eb1bc13f7033ac73ac8593810fd73e52d2d52173f8284abc47273b4442f9a95f4a5325c0e265cdb6a6d6b0321e1
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.0.0 (Pre released)
6
+
7
+ * Signature updates for `URI`, `IO`, 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))
8
+ * `rbs prototype runtime` generates `extend`s ([#535](https://github.com/ruby/rbs/pull/535))
9
+ * `rbs prototype runtime` stability improvements ([#533](https://github.com/ruby/rbs/pull/533), [#526](https://github.com/ruby/rbs/pull/526))
10
+ * Improve runtime type checker compatibility ([#532](https://github.com/ruby/rbs/pull/532), [#528](https://github.com/ruby/rbs/pull/528), )
11
+ * Better compatibility for record type attribute names ([#525](https://github.com/ruby/rbs/pull/525), [#524](https://github.com/ruby/rbs/pull/524))
12
+ * Let module-self-types be classes ([#523](https://github.com/ruby/rbs/pull/523))
13
+ * 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))
14
+ * Fix `ruby2_keywords` for `Proc` in Ruby <2.7 ([#513](https://github.com/ruby/rbs/pull/513))
15
+
5
16
  ## 0.20.1 (2020-12-06)
6
17
 
7
18
  * Make the order of RBS load reproducible ([#508](https://github.com/ruby/rbs/pull/508))
data/Rakefile CHANGED
@@ -41,6 +41,10 @@ task :validate => :parser do
41
41
  lib << "pstore"
42
42
  end
43
43
 
44
+ if lib == ["logger"]
45
+ lib << "monitor"
46
+ end
47
+
44
48
  sh "#{ruby} #{rbs} #{lib.map {|l| "-r #{l}"}.join(" ")} validate --silent"
45
49
  end
46
50
  end
@@ -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
@@ -405,7 +405,63 @@ class IO < Object
405
405
 
406
406
  def puts: (*untyped arg0) -> NilClass
407
407
 
408
- def read: (?Integer length, ?String outbuf) -> String?
408
+ # Reads *length* bytes from the I/O stream.
409
+ #
410
+ # *length* must be a non-negative integer or `nil`.
411
+ #
412
+ # If *length* is a positive integer, `read` tries to read *length* bytes without
413
+ # any conversion (binary mode). It returns `nil` if an EOF is encountered before
414
+ # anything can be read. Fewer than *length* bytes are returned if an EOF is
415
+ # encountered during the read. In the case of an integer *length*, the resulting
416
+ # string is always in ASCII-8BIT encoding.
417
+ #
418
+ # If *length* is omitted or is `nil`, it reads until EOF and the encoding
419
+ # conversion is applied, if applicable. A string is returned even if EOF is
420
+ # encountered before any data is read.
421
+ #
422
+ # If *length* is zero, it returns an empty string (`""`).
423
+ #
424
+ # If the optional *outbuf* argument is present, it must reference a String,
425
+ # which will receive the data. The *outbuf* will contain only the received data
426
+ # after the method call even if it is not empty at the beginning.
427
+ #
428
+ # When this method is called at end of file, it returns `nil` or `""`, depending
429
+ # on *length*: `read`, `read(nil)`, and `read(0)` return `""`,
430
+ # `read(*positive_integer*)` returns `nil`.
431
+ #
432
+ # f = File.new("testfile")
433
+ # f.read(16) #=> "This is line one"
434
+ #
435
+ # # read whole file
436
+ # open("file") do |f|
437
+ # data = f.read # This returns a string even if the file is empty.
438
+ # # ...
439
+ # end
440
+ #
441
+ # # iterate over fixed length records
442
+ # open("fixed-record-file") do |f|
443
+ # while record = f.read(256)
444
+ # # ...
445
+ # end
446
+ # end
447
+ #
448
+ # # iterate over variable length records,
449
+ # # each record is prefixed by its 32-bit length
450
+ # open("variable-record-file") do |f|
451
+ # while len = f.read(4)
452
+ # len = len.unpack("N")[0] # 32-bit length
453
+ # record = f.read(len) # This returns a string even if len is 0.
454
+ # end
455
+ # end
456
+ #
457
+ # Note that this method behaves like the fread() function in C. This means it
458
+ # retries to invoke read(2) system calls to read data with the specified length
459
+ # (or until EOF). This behavior is preserved even if *ios* is in non-blocking
460
+ # mode. (This method is non-blocking flag insensitive as other methods.) If you
461
+ # need the behavior like a single read(2) system call, consider #readpartial,
462
+ # #read_nonblock, and #sysread.
463
+ #
464
+ def read: (?Integer? length, ?String outbuf) -> String?
409
465
 
410
466
  def read_nonblock: (Integer len) -> String
411
467
  | (Integer len, ?String buf) -> String
@@ -428,8 +484,63 @@ class IO < Object
428
484
 
429
485
  def readlines: (?String sep, ?Integer limit) -> ::Array[String]
430
486
 
431
- def readpartial: (Integer maxlen) -> String
432
- | (Integer maxlen, ?String outbuf) -> String
487
+ # Reads at most *maxlen* bytes from the I/O stream. It blocks only if *ios* has
488
+ # no data immediately available. It doesn't block if some data available.
489
+ #
490
+ # If the optional *outbuf* argument is present, it must reference a String,
491
+ # which will receive the data. The *outbuf* will contain only the received data
492
+ # after the method call even if it is not empty at the beginning.
493
+ #
494
+ # It raises EOFError on end of file.
495
+ #
496
+ # readpartial is designed for streams such as pipe, socket, tty, etc. It blocks
497
+ # only when no data immediately available. This means that it blocks only when
498
+ # following all conditions hold.
499
+ # * the byte buffer in the IO object is empty.
500
+ # * the content of the stream is empty.
501
+ # * the stream is not reached to EOF.
502
+ #
503
+ #
504
+ # When readpartial blocks, it waits data or EOF on the stream. If some data is
505
+ # reached, readpartial returns with the data. If EOF is reached, readpartial
506
+ # raises EOFError.
507
+ #
508
+ # When readpartial doesn't blocks, it returns or raises immediately. If the byte
509
+ # buffer is not empty, it returns the data in the buffer. Otherwise if the
510
+ # stream has some content, it returns the data in the stream. Otherwise if the
511
+ # stream is reached to EOF, it raises EOFError.
512
+ #
513
+ # r, w = IO.pipe # buffer pipe content
514
+ # w << "abc" # "" "abc".
515
+ # r.readpartial(4096) #=> "abc" "" ""
516
+ # r.readpartial(4096) # blocks because buffer and pipe is empty.
517
+ #
518
+ # r, w = IO.pipe # buffer pipe content
519
+ # w << "abc" # "" "abc"
520
+ # w.close # "" "abc" EOF
521
+ # r.readpartial(4096) #=> "abc" "" EOF
522
+ # r.readpartial(4096) # raises EOFError
523
+ #
524
+ # r, w = IO.pipe # buffer pipe content
525
+ # w << "abc\ndef\n" # "" "abc\ndef\n"
526
+ # r.gets #=> "abc\n" "def\n" ""
527
+ # w << "ghi\n" # "def\n" "ghi\n"
528
+ # r.readpartial(4096) #=> "def\n" "" "ghi\n"
529
+ # r.readpartial(4096) #=> "ghi\n" "" ""
530
+ #
531
+ # Note that readpartial behaves similar to sysread. The differences are:
532
+ # * If the byte buffer is not empty, read from the byte buffer instead of
533
+ # "sysread for buffered IO (IOError)".
534
+ # * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial
535
+ # meets EWOULDBLOCK and EINTR by read system call, readpartial retry the
536
+ # system call.
537
+ #
538
+ #
539
+ # The latter means that readpartial is nonblocking-flag insensitive. It blocks
540
+ # on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking
541
+ # mode.
542
+ #
543
+ def readpartial: (Integer maxlen, ?String outbuf) -> String
433
544
 
434
545
  def reopen: (IO other_IO_or_path) -> IO
435
546
  | (String other_IO_or_path, ?String mode_str) -> IO
@@ -508,13 +619,55 @@ class IO < Object
508
619
 
509
620
  def ungetc: (String arg0) -> NilClass
510
621
 
511
- def write: (*_ToS arg0) -> Integer
622
+ # Writes the given strings to *ios*. The stream must be opened for writing.
623
+ # Arguments that are not a string will be converted to a string using `to_s`.
624
+ # Returns the number of bytes written in total.
625
+ #
626
+ # count = $stdout.write("This is", " a test\n")
627
+ # puts "That was #{count} bytes of data"
628
+ #
629
+ # *produces:*
630
+ #
631
+ # This is a test
632
+ # That was 15 bytes of data
633
+ #
634
+ def write: (*_ToS string) -> Integer
512
635
 
636
+ # Opens the file, optionally seeks to the given *offset*, then returns *length*
637
+ # bytes (defaulting to the rest of the file). #binread ensures the file is
638
+ # closed before returning. The open mode would be `"rb:ASCII-8BIT"`.
639
+ #
640
+ # IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
641
+ # IO.binread("testfile", 20) #=> "This is line one\nThi"
642
+ # IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
643
+ #
513
644
  def self.binread: (String name, ?Integer length, ?Integer offset) -> String
514
645
 
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
646
+ # Same as IO.write except opening the file in binary mode and ASCII-8BIT
647
+ # encoding (`"wb:ASCII-8BIT"`).
648
+ #
649
+ def self.binwrite: (String name, _ToS string, ?Integer offset, ?mode: String mode) -> Integer
516
650
 
517
- def self.copy_stream: (_Reader src, _Writer dst, ?Integer copy_length, ?Integer src_offset) -> Integer
651
+ # IO.copy_stream copies *src* to *dst*. *src* and *dst* is either a filename or
652
+ # an IO-like object. IO-like object for *src* should have #readpartial or #read
653
+ # method. IO-like object for *dst* should have #write method. (Specialized
654
+ # mechanisms, such as sendfile system call, may be used on appropriate
655
+ # situation.)
656
+ #
657
+ # This method returns the number of bytes copied.
658
+ #
659
+ # If optional arguments are not given, the start position of the copy is the
660
+ # beginning of the filename or the current file offset of the IO. The end
661
+ # position of the copy is the end of file.
662
+ #
663
+ # If *copy_length* is given, No more than *copy_length* bytes are copied.
664
+ #
665
+ # If *src_offset* is given, it specifies the start position of the copy.
666
+ #
667
+ # When *src_offset* is specified and *src* is an IO, IO.copy_stream doesn't move
668
+ # the current file offset.
669
+ #
670
+ def self.copy_stream: ((String | _Reader | _ReaderPartial) src, (String | _Writer) dst, ?Integer copy_length, ?Integer src_offset) -> Integer
518
671
 
519
672
  def self.popen: (*untyped args) -> untyped
520
673
 
@@ -10,7 +10,7 @@
10
10
  # ```ruby
11
11
  # sprintf "%.1f", 1.234 #=> "1.2"
12
12
  # ```
13
- module Kernel
13
+ module Kernel : BasicObject
14
14
  private
15
15
 
16
16
  def caller: (?Integer start_or_range, ?Integer length) -> ::Array[String]?
@@ -28,6 +28,26 @@ rules:
28
28
  pass:
29
29
  - "def `send`: (String | Symbol, *untyped) -> untyped"
30
30
 
31
+ - id: rbs.prefer_boolish
32
+ pattern:
33
+ - regexp: '\([^(]*\bbool\b[^\n]*\)'
34
+ - token: "-> bool }"
35
+ message: |
36
+ Prefer `boolish` over `bool` for method arguments and block return values
37
+
38
+ See the doc below:
39
+ https://github.com/ruby/rbs/blob/78d04a2db0f1c4925d2b13c2939868edf9465d6c/docs/syntax.md#bool-or-boolish
40
+ glob:
41
+ - "**/*.rbs"
42
+ justification:
43
+ - When you strictly want `true | false`.
44
+ pass:
45
+ - "(arg: boolish)"
46
+ - "{ () -> boolish }"
47
+ fail:
48
+ - "(arg: bool)"
49
+ - "{ () -> bool }"
50
+
31
51
  - id: deprecate_stdlib_test
32
52
  pattern:
33
53
  token: < StdlibTest
data/lib/rbs.rb CHANGED
@@ -23,6 +23,8 @@ require "rbs/environment_loader"
23
23
  require "rbs/builtin_names"
24
24
  require "rbs/definition"
25
25
  require "rbs/definition_builder"
26
+ require "rbs/definition_builder/ancestor_builder"
27
+ require "rbs/definition_builder/method_builder"
26
28
  require "rbs/variance_calculator"
27
29
  require "rbs/substitution"
28
30
  require "rbs/constant"
@@ -136,10 +136,12 @@ module RBS
136
136
  class Super
137
137
  attr_reader :name
138
138
  attr_reader :args
139
+ attr_reader :location
139
140
 
140
- def initialize(name:, args:)
141
+ def initialize(name:, args:, location:)
141
142
  @name = name
142
143
  @args = args
144
+ @location = location
143
145
  end
144
146
 
145
147
  def ==(other)
@@ -155,7 +157,8 @@ module RBS
155
157
  def to_json(*a)
156
158
  {
157
159
  name: name,
158
- args: args
160
+ args: args,
161
+ location: location
159
162
  }.to_json(*a)
160
163
  end
161
164
  end
@@ -352,6 +355,8 @@ module RBS
352
355
  attr_reader :location
353
356
  attr_reader :comment
354
357
 
358
+ include MixinHelper
359
+
355
360
  def initialize(name:, type_params:, members:, annotations:, location:, comment:)
356
361
  @name = name
357
362
  @type_params = type_params
@@ -20,7 +20,7 @@ module RBS
20
20
  @annotations = annotations
21
21
  @location = location
22
22
  @comment = comment
23
- @overload = overload
23
+ @overload = overload ? true : false
24
24
  end
25
25
 
26
26
  def ==(other)
@@ -25,7 +25,7 @@ module RBS
25
25
  end
26
26
 
27
27
  loader = EnvironmentLoader.new(core_root: core_root, repository: repository)
28
-
28
+
29
29
  dirs.each do |dir|
30
30
  loader.add(path: Pathname(dir))
31
31
  end
@@ -43,21 +43,21 @@ module RBS
43
43
  opts.on("-r LIBRARY", "Load RBS files of the library") do |lib|
44
44
  libs << lib
45
45
  end
46
-
46
+
47
47
  opts.on("-I DIR", "Load RBS files from the directory") do |dir|
48
48
  dirs << dir
49
49
  end
50
-
50
+
51
51
  opts.on("--no-stdlib", "Skip loading standard library signatures") do
52
52
  self.core_root = nil
53
53
  end
54
-
54
+
55
55
  opts.on("--repo DIR", "Add RBS repository") do |dir|
56
56
  repos << dir
57
57
  end
58
-
58
+
59
59
  opts
60
- end
60
+ end
61
61
  end
62
62
 
63
63
  attr_reader :stdout
@@ -242,7 +242,7 @@ EOU
242
242
 
243
243
  env = Environment.from_loader(loader).resolve_type_names
244
244
 
245
- builder = DefinitionBuilder.new(env: env)
245
+ builder = DefinitionBuilder::AncestorBuilder.new(env: env)
246
246
  type_name = TypeName(args[0]).absolute!
247
247
 
248
248
  if env.class_decls.key?(type_name)
@@ -626,7 +626,7 @@ EOU
626
626
 
627
627
  opts = OptionParser.new
628
628
  opts.banner = <<EOU
629
- Usage: rbs prototype #{format} [options...] [files...]
629
+ Usage: rbs prototype #{format} [files...]
630
630
  #{availability}
631
631
  Generate RBS prototype from source code.
632
632
  It parses specified Ruby code and and generates RBS prototypes.
@@ -735,7 +735,7 @@ Examples:
735
735
  syntax_error = false
736
736
  args.each do |path|
737
737
  path = Pathname(path)
738
- loader.each_file(path, skip_hidden: false, immediate: true) do |file_path|
738
+ loader.each_file(path, skip_hidden: false, immediate: true) do |file_path|
739
739
  Parser.parse_signature(file_path.read)
740
740
  rescue RBS::Parser::SyntaxError => ex
741
741
  loc = ex.error_value.location
@@ -757,7 +757,7 @@ Examples:
757
757
  opts.push(*options.repos.map {|dir| "--repo #{Shellwords.escape(dir)}"})
758
758
  opts.push(*options.dirs.map {|dir| "-I #{Shellwords.escape(dir)}"})
759
759
  opts.push(*options.libs.map {|lib| "-r#{Shellwords.escape(lib)}"})
760
-
760
+
761
761
  opts.empty? ? nil : opts.join(" ")
762
762
  end
763
763
 
@@ -34,6 +34,20 @@ module RBS
34
34
  @implemented_in = implemented_in
35
35
  end
36
36
 
37
+ def ==(other)
38
+ other.is_a?(TypeDef) &&
39
+ other.type == type &&
40
+ other.member == member &&
41
+ other.defined_in == defined_in &&
42
+ other.implemented_in == implemented_in
43
+ end
44
+
45
+ alias eql? ==
46
+
47
+ def hash
48
+ self.class.hash ^ type.hash ^ member.hash ^ defined_in.hash ^ implemented_in.hash
49
+ end
50
+
37
51
  def comment
38
52
  member.comment
39
53
  end
@@ -70,6 +84,21 @@ module RBS
70
84
  @alias_of = alias_of
71
85
  end
72
86
 
87
+ def ==(other)
88
+ other.is_a?(Method) &&
89
+ other.super_method == super_method &&
90
+ other.defs == defs &&
91
+ other.accessibility == accessibility &&
92
+ other.annotations == annotations &&
93
+ other.alias_of == alias_of
94
+ end
95
+
96
+ alias eql? ==
97
+
98
+ def hash
99
+ self.class.hash ^ super_method.hash ^ defs.hash ^ accessibility.hash ^ annotations.hash ^ alias_of.hash
100
+ end
101
+
73
102
  def defined_in
74
103
  @defined_in ||= begin
75
104
  last_def = defs.last or raise
@@ -137,8 +166,43 @@ module RBS
137
166
  end
138
167
 
139
168
  module Ancestor
140
- Instance = _ = Struct.new(:name, :args, keyword_init: true)
141
- Singleton = _ = Struct.new(:name, keyword_init: true)
169
+ class Instance
170
+ attr_reader :name, :args, :source
171
+
172
+ def initialize(name:, args:, source:)
173
+ @name = name
174
+ @args = args
175
+ @source = source
176
+ end
177
+
178
+ def ==(other)
179
+ other.is_a?(Instance) && other.name == name && other.args == args
180
+ end
181
+
182
+ alias eql? ==
183
+
184
+ def hash
185
+ self.class.hash ^ name.hash ^ args.hash
186
+ end
187
+ end
188
+
189
+ class Singleton
190
+ attr_reader :name
191
+
192
+ def initialize(name:)
193
+ @name = name
194
+ end
195
+
196
+ def ==(other)
197
+ other.is_a?(Singleton) && other.name == name
198
+ end
199
+
200
+ alias eql? ==
201
+
202
+ def hash
203
+ self.class.hash ^ name.hash
204
+ end
205
+ end
142
206
  end
143
207
 
144
208
  class InstanceAncestors
@@ -170,7 +234,8 @@ module RBS
170
234
  else
171
235
  Ancestor::Instance.new(
172
236
  name: ancestor.name,
173
- args: ancestor.args.map {|type| type.sub(subst) }
237
+ args: ancestor.args.map {|type| type.sub(subst) },
238
+ source: ancestor.source
174
239
  )
175
240
  end
176
241
  when Ancestor::Singleton
@@ -233,6 +298,8 @@ module RBS
233
298
  case en = entry
234
299
  when Environment::SingleEntry
235
300
  en.decl.is_a?(AST::Declarations::Interface)
301
+ else
302
+ false
236
303
  end
237
304
  end
238
305