rbs 3.4.4 → 3.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +12 -4
  3. data/.github/workflows/dependabot.yml +26 -0
  4. data/.github/workflows/ruby.yml +14 -1
  5. data/CHANGELOG.md +87 -1
  6. data/README.md +5 -3
  7. data/Rakefile +20 -3
  8. data/Steepfile +1 -1
  9. data/core/enumerator.rbs +1 -1
  10. data/core/float.rbs +2 -1
  11. data/core/gc.rbs +272 -150
  12. data/core/integer.rbs +6 -4
  13. data/core/io/wait.rbs +4 -4
  14. data/core/io.rbs +10 -3
  15. data/core/kernel.rbs +8 -7
  16. data/core/module.rbs +17 -4
  17. data/core/proc.rbs +1 -1
  18. data/core/range.rbs +2 -2
  19. data/core/rational.rbs +2 -1
  20. data/core/regexp.rbs +101 -90
  21. data/core/ruby_vm.rbs +107 -103
  22. data/core/rubygems/rubygems.rbs +1 -1
  23. data/core/set.rbs +13 -7
  24. data/core/string.rbs +3 -3
  25. data/core/symbol.rbs +2 -1
  26. data/core/thread.rbs +1 -1
  27. data/core/time.rbs +24 -4
  28. data/docs/architecture.md +110 -0
  29. data/docs/gem.md +0 -1
  30. data/docs/syntax.md +5 -1
  31. data/ext/rbs_extension/constants.c +2 -0
  32. data/ext/rbs_extension/constants.h +1 -0
  33. data/ext/rbs_extension/lexer.c +1338 -1341
  34. data/ext/rbs_extension/lexer.h +2 -0
  35. data/ext/rbs_extension/lexer.re +2 -3
  36. data/ext/rbs_extension/lexstate.c +5 -1
  37. data/ext/rbs_extension/location.c +80 -70
  38. data/ext/rbs_extension/location.h +25 -5
  39. data/ext/rbs_extension/parser.c +149 -43
  40. data/ext/rbs_extension/parserstate.c +12 -1
  41. data/ext/rbs_extension/parserstate.h +9 -0
  42. data/ext/rbs_extension/ruby_objs.c +13 -3
  43. data/ext/rbs_extension/ruby_objs.h +1 -0
  44. data/lib/rbs/cli/validate.rb +2 -2
  45. data/lib/rbs/cli.rb +4 -6
  46. data/lib/rbs/collection/config.rb +1 -1
  47. data/lib/rbs/collection/sources/git.rb +1 -6
  48. data/lib/rbs/definition_builder/method_builder.rb +1 -1
  49. data/lib/rbs/definition_builder.rb +8 -8
  50. data/lib/rbs/diff.rb +1 -1
  51. data/lib/rbs/environment_loader.rb +2 -1
  52. data/lib/rbs/errors.rb +0 -14
  53. data/lib/rbs/location_aux.rb +6 -1
  54. data/lib/rbs/parser/lex_result.rb +15 -0
  55. data/lib/rbs/parser/token.rb +23 -0
  56. data/lib/rbs/parser_aux.rb +12 -5
  57. data/lib/rbs/prototype/helpers.rb +22 -12
  58. data/lib/rbs/prototype/rb.rb +38 -4
  59. data/lib/rbs/prototype/rbi.rb +30 -20
  60. data/lib/rbs/test/errors.rb +19 -14
  61. data/lib/rbs/test/tester.rb +1 -1
  62. data/lib/rbs/test/type_check.rb +95 -16
  63. data/lib/rbs/types.rb +112 -13
  64. data/lib/rbs/unit_test/spy.rb +1 -1
  65. data/lib/rbs/version.rb +1 -1
  66. data/rbs.gemspec +7 -2
  67. data/sig/environment_loader.rbs +1 -1
  68. data/sig/errors.rbs +1 -1
  69. data/sig/manifest.yaml +0 -1
  70. data/sig/method_types.rbs +3 -3
  71. data/sig/parser.rbs +28 -0
  72. data/sig/prototype/helpers.rbs +4 -0
  73. data/sig/prototype/rbi.rbs +2 -0
  74. data/sig/types.rbs +54 -4
  75. data/sig/variance_calculator.rbs +2 -2
  76. data/stdlib/csv/0/csv.rbs +4 -1
  77. data/stdlib/fileutils/0/fileutils.rbs +1 -1
  78. data/stdlib/net-http/0/net-http.rbs +29 -27
  79. data/stdlib/socket/0/socket.rbs +2 -2
  80. data/stdlib/timeout/0/timeout.rbs +6 -0
  81. data/stdlib/uri/0/generic.rbs +2 -2
  82. data/stdlib/uri/0/http.rbs +2 -2
  83. data/stdlib/uri/0/mailto.rbs +84 -0
  84. metadata +7 -9
  85. data/Gemfile +0 -30
  86. data/Gemfile.lock +0 -117
  87. data/lib/rbs/parser_compat/lexer_error.rb +0 -6
  88. data/lib/rbs/parser_compat/located_value.rb +0 -7
  89. data/lib/rbs/parser_compat/semantics_error.rb +0 -6
  90. data/lib/rbs/parser_compat/syntax_error.rb +0 -6
data/lib/rbs/types.rb CHANGED
@@ -515,22 +515,34 @@ module RBS
515
515
  end
516
516
 
517
517
  class Record
518
- attr_reader :fields
518
+ attr_reader :all_fields, :fields, :optional_fields
519
519
  attr_reader :location
520
520
 
521
- def initialize(fields:, location:)
522
- @fields = fields
521
+ def initialize(all_fields: nil, fields: nil, location:)
522
+ case
523
+ when fields && all_fields.nil?
524
+ @all_fields = fields.map { |k, v| [k, [v, true]] }.to_h
525
+ @fields = fields
526
+ @optional_fields = {}
527
+ when all_fields && fields.nil?
528
+ @all_fields = all_fields
529
+ @fields = all_fields.filter_map { |k, (v, required)| [k, v] if required }.to_h
530
+ @optional_fields = all_fields.filter_map { |k, (v, required)| [k, v] unless required }.to_h
531
+ else
532
+ raise ArgumentError, "only one of `:fields` or `:all_fields` is requireds"
533
+ end
534
+
523
535
  @location = location
524
536
  end
525
537
 
526
538
  def ==(other)
527
- other.is_a?(Record) && other.fields == fields
539
+ other.is_a?(Record) && other.fields == fields && other.optional_fields == optional_fields
528
540
  end
529
541
 
530
542
  alias eql? ==
531
543
 
532
544
  def hash
533
- self.class.hash ^ fields.hash
545
+ self.class.hash ^ all_fields.hash
534
546
  end
535
547
 
536
548
  def free_variables(set = Set.new)
@@ -538,27 +550,35 @@ module RBS
538
550
  fields.each_value do |type|
539
551
  type.free_variables set
540
552
  end
553
+ optional_fields.each_value do |type|
554
+ type.free_variables set
555
+ end
541
556
  end
542
557
  end
543
558
 
544
559
  def to_json(state = _ = nil)
545
- { class: :record, fields: fields, location: location }.to_json(state)
560
+ { class: :record, fields: fields, optional_fields: optional_fields, location: location }.to_json(state)
546
561
  end
547
562
 
548
563
  def sub(s)
549
- self.class.new(fields: fields.transform_values {|ty| ty.sub(s) },
550
- location: location)
564
+ self.class.new(
565
+ all_fields: all_fields.transform_values {|ty, required| [ty.sub(s), required] },
566
+ location: location
567
+ )
551
568
  end
552
569
 
553
570
  def to_s(level = 0)
554
- return "{ }" if self.fields.empty?
571
+ return "{ }" if all_fields.empty?
555
572
 
556
- fields = self.fields.map do |key, type|
557
- if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_0-9]*\z/)
573
+ fields = all_fields.map do |key, (type, required)|
574
+ field = if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_0-9]*\z/)
558
575
  "#{key}: #{type}"
559
576
  else
560
577
  "#{key.inspect} => #{type}"
561
578
  end
579
+
580
+ field = "?#{field}" unless required
581
+ field
562
582
  end
563
583
  "{ #{fields.join(", ")} }"
564
584
  end
@@ -566,6 +586,7 @@ module RBS
566
586
  def each_type(&block)
567
587
  if block
568
588
  fields.each_value(&block)
589
+ optional_fields.each_value(&block)
569
590
  else
570
591
  enum_for :each_type
571
592
  end
@@ -573,7 +594,7 @@ module RBS
573
594
 
574
595
  def map_type_name(&block)
575
596
  Record.new(
576
- fields: fields.transform_values {|ty| ty.map_type_name(&block) },
597
+ all_fields: all_fields.transform_values {|ty, required| [ty.map_type_name(&block), required] },
577
598
  location: location
578
599
  )
579
600
  end
@@ -581,7 +602,7 @@ module RBS
581
602
  def map_type(&block)
582
603
  if block
583
604
  Record.new(
584
- fields: fields.transform_values {|type| yield type },
605
+ all_fields: all_fields.transform_values {|type, required| [yield(type), required] },
585
606
  location: location
586
607
  )
587
608
  else
@@ -1181,6 +1202,84 @@ module RBS
1181
1202
  end
1182
1203
  end
1183
1204
 
1205
+ class UntypedFunction
1206
+ attr_reader :return_type
1207
+
1208
+ def initialize(return_type:)
1209
+ @return_type = return_type
1210
+ end
1211
+
1212
+ def free_variables(acc = Set.new)
1213
+ return_type.free_variables(acc)
1214
+ end
1215
+
1216
+ def map_type(&block)
1217
+ if block
1218
+ update(return_type: yield(return_type))
1219
+ else
1220
+ enum_for :map_type
1221
+ end
1222
+ end
1223
+
1224
+ def each_type(&block)
1225
+ if block
1226
+ yield return_type
1227
+ else
1228
+ enum_for :each_type
1229
+ end
1230
+ end
1231
+
1232
+ def each_param(&block)
1233
+ if block
1234
+ # noop
1235
+ else
1236
+ enum_for :each_param
1237
+ end
1238
+ end
1239
+
1240
+ def to_json(state = _ = nil)
1241
+ {
1242
+ return_type: return_type
1243
+ }.to_json(state)
1244
+ end
1245
+
1246
+ def sub(subst)
1247
+ map_type { _1.sub(subst) }
1248
+ end
1249
+
1250
+ def with_return_type(ty)
1251
+ update(return_type: ty)
1252
+ end
1253
+
1254
+ def update(return_type: self.return_type)
1255
+ UntypedFunction.new(return_type: return_type)
1256
+ end
1257
+
1258
+ def empty?
1259
+ true
1260
+ end
1261
+
1262
+ def has_self_type?
1263
+ return_type.has_self_type?
1264
+ end
1265
+
1266
+ def has_classish_type?
1267
+ return_type.has_classish_type?
1268
+ end
1269
+
1270
+ def with_nonreturn_void
1271
+ false
1272
+ end
1273
+
1274
+ def param_to_s
1275
+ "?"
1276
+ end
1277
+
1278
+ def return_to_s
1279
+ return_type.to_s(1)
1280
+ end
1281
+ end
1282
+
1184
1283
  class Block
1185
1284
  attr_reader :type
1186
1285
  attr_reader :required
@@ -128,7 +128,7 @@ module RBS
128
128
  end
129
129
  end.ruby2_keywords
130
130
  )
131
- end.new()
131
+ end.allocate()
132
132
  end
133
133
  end
134
134
  end
data/lib/rbs/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RBS
4
- VERSION = "3.4.4"
4
+ VERSION = "3.5.1"
5
5
  end
data/rbs.gemspec CHANGED
@@ -28,7 +28,12 @@ Gem::Specification.new do |spec|
28
28
  # Specify which files should be added to the gem when it is released.
29
29
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
30
30
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
31
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|bin|steep)/}) }
31
+ `git ls-files -z`.split("\x0").reject do |f|
32
+ [
33
+ %r{^(test|spec|features|bin|steep|benchmark)/},
34
+ /Gemfile/
35
+ ].any? {|r| f.match(r) }
36
+ end
32
37
  end
33
38
  spec.extensions = %w{ext/rbs_extension/extconf.rb}
34
39
 
@@ -36,5 +41,5 @@ Gem::Specification.new do |spec|
36
41
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
37
42
  spec.require_paths = ["lib"]
38
43
  spec.required_ruby_version = ">= 3.0"
39
- spec.add_dependency "abbrev"
44
+ spec.add_dependency "logger"
40
45
  end
@@ -30,7 +30,7 @@ module RBS
30
30
  def initialize: (lib: Library) -> void
31
31
  end
32
32
 
33
- class Library < Struct[String | String?]
33
+ class Library
34
34
  attr_reader name: String
35
35
  attr_reader version: String?
36
36
 
data/sig/errors.rbs CHANGED
@@ -363,6 +363,6 @@ module RBS
363
363
 
364
364
  def initialize: (String message, location: Location[untyped, untyped]?) -> void
365
365
 
366
- def location: () -> Location[untyped, untyped]?
366
+ attr_reader location: Location[untyped, untyped]?
367
367
  end
368
368
  end
data/sig/manifest.yaml CHANGED
@@ -5,4 +5,3 @@ dependencies:
5
5
  - name: optparse
6
6
  - name: tsort
7
7
  - name: rdoc
8
- - name: abbrev
data/sig/method_types.rbs CHANGED
@@ -14,11 +14,11 @@ module RBS
14
14
  type loc = def_loc | attr_loc
15
15
 
16
16
  attr_reader type_params: Array[AST::TypeParam]
17
- attr_reader type: Types::Function
17
+ attr_reader type: Types::function
18
18
  attr_reader block: Types::Block?
19
19
  attr_reader location: loc?
20
20
 
21
- def initialize: (type_params: Array[AST::TypeParam], type: Types::Function, block: Types::Block?, location: loc?) -> void
21
+ def initialize: (type_params: Array[AST::TypeParam], type: Types::function, block: Types::Block?, location: loc?) -> void
22
22
 
23
23
  def ==: (untyped other) -> bool
24
24
 
@@ -29,7 +29,7 @@ module RBS
29
29
  #
30
30
  def sub: (Substitution) -> MethodType
31
31
 
32
- def update: (?type_params: Array[AST::TypeParam], ?type: Types::Function, ?block: Types::Block?, ?location: loc?) -> MethodType
32
+ def update: (?type_params: Array[AST::TypeParam], ?type: Types::function, ?block: Types::Block?, ?location: loc?) -> MethodType
33
33
 
34
34
  def free_variables: (?Set[Symbol] set) -> Set[Symbol]
35
35
 
data/sig/parser.rbs CHANGED
@@ -1,5 +1,23 @@
1
1
  module RBS
2
2
  class Parser
3
+ # Result of `Parser.lex`
4
+ class LexResult
5
+ attr_reader buffer: Buffer
6
+ attr_reader value: Array[Token]
7
+
8
+ def initialize: (buffer: Buffer, value: Array[Token]) -> void
9
+ end
10
+
11
+ # Represents a token per result of `Parser.lex`.
12
+ class Token
13
+ attr_reader type: Symbol
14
+ attr_reader location: Location[untyped, untyped]
15
+
16
+ def initialize: (type: Symbol, location: Location[untyped, untyped]) -> void
17
+ def value: () -> String
18
+ def comment?: () -> bool
19
+ end
20
+
3
21
  # Parse a method type and return it
4
22
  #
5
23
  # When `range` keyword is specified, it starts parsing from the `begin` to the `end` of the range.
@@ -50,6 +68,14 @@ module RBS
50
68
  #
51
69
  def self.parse_signature: (Buffer | String) -> [Buffer, Array[AST::Directives::t], Array[AST::Declarations::t]]
52
70
 
71
+ # Parse whole RBS file and return result.
72
+ #
73
+ # ```ruby
74
+ # RBS::Parser.lex("# Comment\nmodule A\nend\n").value.map(&:type)
75
+ # # => [:tLINECOMMENT, :kMODULE, :tUIDENT, :kEND, :pEOF]
76
+ # ```
77
+ def self.lex: (Buffer | String) -> LexResult
78
+
53
79
  KEYWORDS: Hash[String, bot]
54
80
 
55
81
  private
@@ -62,6 +88,8 @@ module RBS
62
88
 
63
89
  def self._parse_signature: (Buffer, Integer end_pos) -> [Array[AST::Directives::t], Array[AST::Declarations::t]]
64
90
 
91
+ def self._lex: (Buffer, Integer end_pos) -> Array[[Symbol, Location[untyped, untyped]]]
92
+
65
93
  class LocatedValue
66
94
  end
67
95
  end
@@ -13,6 +13,10 @@ module RBS
13
13
 
14
14
  def keyword_hash?: (node) -> bool
15
15
 
16
+ # Returns a symbol if the node is a symbol literal node
17
+ #
18
+ def symbol_literal_node?: (node) -> Symbol?
19
+
16
20
  def args_from_node: (node?) -> Array[untyped]
17
21
 
18
22
  def untyped: () -> Types::Bases::Any
@@ -1,6 +1,8 @@
1
1
  module RBS
2
2
  module Prototype
3
3
  class RBI
4
+ include Helpers
5
+
4
6
  attr_reader decls: Array[AST::Declarations::t]
5
7
 
6
8
  type module_decl = AST::Declarations::Class | AST::Declarations::Module
data/sig/types.rbs CHANGED
@@ -301,11 +301,16 @@ module RBS
301
301
  end
302
302
 
303
303
  class Record
304
+ attr_reader all_fields: Hash[Symbol, [t, bool]]
305
+
304
306
  attr_reader fields: Hash[Symbol, t]
305
307
 
308
+ attr_reader optional_fields: Hash[Symbol, t]
309
+
306
310
  type loc = Location[bot, bot]
307
311
 
308
312
  def initialize: (fields: Hash[Symbol, t], location: loc?) -> void
313
+ | (all_fields: Hash[Symbol, [t, bool]], location: loc?) -> void
309
314
 
310
315
  include _TypeBase
311
316
 
@@ -443,13 +448,58 @@ module RBS
443
448
  def with_nonreturn_void?: () -> bool
444
449
  end
445
450
 
451
+ # Function type without type checking arguments
452
+ #
453
+ class UntypedFunction
454
+ attr_reader return_type: t
455
+
456
+ def initialize: (return_type: t) -> void
457
+
458
+ def free_variables: (?Set[Symbol]) -> Set[Symbol]
459
+
460
+ def map_type: { (t) -> t } -> UntypedFunction
461
+ | -> Enumerator[t, UntypedFunction]
462
+
463
+ def map_type_name: () { (TypeName, Location[untyped, untyped]?, t) -> TypeName } -> UntypedFunction
464
+
465
+ def each_type: () { (t) -> void } -> void
466
+ | -> Enumerator[t, void]
467
+
468
+ def each_param: () { (Function::Param) -> void } -> void
469
+ | -> Enumerator[Function::Param, void]
470
+
471
+ include _ToJson
472
+
473
+ def sub: (Substitution) -> UntypedFunction
474
+
475
+ def with_return_type: (t) -> UntypedFunction
476
+
477
+ def update: (?return_type: t) -> UntypedFunction
478
+
479
+ def empty?: () -> bool
480
+
481
+ def has_self_type?: () -> bool
482
+
483
+ def has_classish_type?: () -> bool
484
+
485
+ def with_nonreturn_void?: () -> bool
486
+
487
+ # Returns `?`
488
+ def param_to_s: () -> String
489
+
490
+ # Returns `return_type.to_s(1)`
491
+ def return_to_s: () -> String
492
+ end
493
+
494
+ type function = Types::Function | Types::UntypedFunction
495
+
446
496
  class Block
447
- attr_reader type: Types::Function
497
+ attr_reader type: function
448
498
  attr_reader required: bool
449
499
 
450
500
  attr_reader self_type: t?
451
501
 
452
- def initialize: (type: Types::Function, ?self_type: t?, required: boolish) -> void
502
+ def initialize: (type: function, ?self_type: t?, required: boolish) -> void
453
503
 
454
504
  def ==: (untyped other) -> bool
455
505
 
@@ -465,14 +515,14 @@ module RBS
465
515
  end
466
516
 
467
517
  class Proc
468
- attr_reader type: Function
518
+ attr_reader type: function
469
519
  attr_reader block: Block?
470
520
 
471
521
  attr_reader self_type: t?
472
522
 
473
523
  type loc = Location[bot, bot]
474
524
 
475
- def initialize: (location: loc?, type: Function, ?self_type: t?, block: Block?) -> void
525
+ def initialize: (location: loc?, type: function, ?self_type: t?, block: Block?) -> void
476
526
 
477
527
  include _TypeBase
478
528
 
@@ -73,14 +73,14 @@ module RBS
73
73
  def in_inherit: (name: TypeName, args: Array[Types::t], variables: Array[Symbol]) -> Result
74
74
 
75
75
  # The type name must be normalized
76
- #
76
+ #
77
77
  def in_type_alias: (name: TypeName) -> Result
78
78
 
79
79
  private
80
80
 
81
81
  def type: (Types::t, result: Result, context: variance) -> void
82
82
 
83
- def function: (Types::Function, result: Result, context: variance) -> void
83
+ def function: (Types::function, result: Result, context: variance) -> void
84
84
 
85
85
  def negate: (variance) -> variance
86
86
  end
data/stdlib/csv/0/csv.rbs CHANGED
@@ -1722,7 +1722,10 @@ class CSV < Object
1722
1722
  # would read `UTF-32BE` data from the file but transcode it to `UTF-8`
1723
1723
  # before parsing.
1724
1724
  #
1725
- def self.foreach: [U] (String | IO | StringIO path, ?::Hash[Symbol, U] options) { (::Array[String?] arg0) -> void } -> void
1725
+ def self.foreach: (String | IO path, ?String mode, headers: true, **untyped options) { (::CSV::Row arg0) -> void } -> void
1726
+ | (String | IO path, ?String mode, headers: true, **untyped options) -> Enumerator[::CSV::Row, void]
1727
+ | (String | IO path, ?String mode, **untyped options) { (::Array[String?] arg0) -> void } -> void
1728
+ | (String | IO path, ?String mode, **untyped options) -> Enumerator[::Array[String?], void]
1726
1729
 
1727
1730
  # <!--
1728
1731
  # rdoc-file=lib/csv.rb
@@ -1771,5 +1771,5 @@ module FileUtils
1771
1771
  #
1772
1772
  # Related: FileUtils.touch.
1773
1773
  #
1774
- def self?.uptodate?: (path new, pathlist old_list) -> bool
1774
+ def self?.uptodate?: (path new, _Each[path] old_list) -> bool
1775
1775
  end