rbs 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rbs/parser.y CHANGED
@@ -1,5 +1,5 @@
1
1
  class RBS::Parser
2
- token tUIDENT tLIDENT tNAMESPACE tINTERFACEIDENT tGLOBALIDENT
2
+ token tUIDENT tLIDENT tUNDERSCOREIDENT tNAMESPACE tINTERFACEIDENT tGLOBALIDENT
3
3
  tLKEYWORD tUKEYWORD tLKEYWORD_Q_E tUKEYWORD_Q_E
4
4
  tIVAR tCLASSVAR
5
5
  tANNOTATION
@@ -12,6 +12,7 @@ class RBS::Parser
12
12
  kPREPEND kEXTENSION kINCOMPATIBLE
13
13
  type_TYPE type_SIGNATURE type_METHODTYPE tEOF
14
14
  kOUT kIN kUNCHECKED kOVERLOAD
15
+ kUNDERSCORE
15
16
 
16
17
  prechigh
17
18
  nonassoc kQUESTION
@@ -1326,7 +1327,7 @@ rule
1326
1327
  }
1327
1328
 
1328
1329
  var_name_opt:
1329
- | tLIDENT | tINTERFACEIDENT | tQUOTEDIDENT
1330
+ | tLIDENT | tINTERFACEIDENT | tQUOTEDIDENT | tUNDERSCOREIDENT | kUNDERSCORE
1330
1331
 
1331
1332
  qualified_name:
1332
1333
  namespace simple_name {
@@ -1713,12 +1714,16 @@ def next_token
1713
1714
  new_token(:tIVAR, input.matched.to_sym)
1714
1715
  when input.scan(/@@[a-zA-Z_]\w*/)
1715
1716
  new_token(:tCLASSVAR, input.matched.to_sym)
1716
- when input.scan(/_[a-zA-Z]\w*\b/)
1717
+ when input.scan(/_[A-Z]\w*\b/)
1717
1718
  new_token(:tINTERFACEIDENT)
1718
1719
  when input.scan(/[A-Z]\w*\b/)
1719
1720
  new_token(:tUIDENT)
1720
- when input.scan(/[a-z_]\w*\b/)
1721
+ when input.scan(/[a-z]\w*\b/)
1721
1722
  new_token(:tLIDENT)
1723
+ when input.scan(/_[a-z]\w*\b/)
1724
+ new_token(:tUNDERSCOREIDENT)
1725
+ when input.scan(/_/)
1726
+ new_token(:kUNDERSCORE)
1722
1727
  when input.scan(/"(\\"|[^"])*"/)
1723
1728
  s = input.matched.yield_self {|s| s[1, s.length - 2] }
1724
1729
  .gsub(DBL_QUOTE_STR_ESCAPE_SEQUENCES_RE) do |match|
@@ -148,7 +148,7 @@ module RBS
148
148
  types = [
149
149
  MethodType.new(
150
150
  type_params: [],
151
- type: function_type_from_body(def_body),
151
+ type: function_type_from_body(def_body, def_name),
152
152
  block: block_from_body(def_body),
153
153
  location: nil
154
154
  )
@@ -377,12 +377,16 @@ module RBS
377
377
  each_node node.children, &block
378
378
  end
379
379
 
380
- def function_type_from_body(node)
380
+ def function_type_from_body(node, def_name)
381
381
  table_node, args_node, *_ = node.children
382
382
 
383
383
  pre_num, _pre_init, opt, _first_post, post_num, _post_init, rest, kw, kwrest, _block = args_from_node(args_node)
384
384
 
385
- return_type = function_return_type_from_body(node)
385
+ return_type = if def_name == :initialize
386
+ Types::Bases::Void.new(location: nil)
387
+ else
388
+ function_return_type_from_body(node)
389
+ end
386
390
 
387
391
  fun = Types::Function.empty(return_type)
388
392
 
@@ -9,6 +9,7 @@ module RBS
9
9
  def initialize(patterns:, env:, merge:, owners_included: [])
10
10
  @patterns = patterns
11
11
  @decls = nil
12
+ @modules = []
12
13
  @env = env
13
14
  @merge = merge
14
15
  @owners_included = owners_included.map do |name|
@@ -39,7 +40,8 @@ module RBS
39
40
  def decls
40
41
  unless @decls
41
42
  @decls = []
42
- ObjectSpace.each_object(Module).select {|mod| target?(mod) }.sort_by{|mod| const_name(mod) }.each do |mod|
43
+ @modules = ObjectSpace.each_object(Module).to_a
44
+ @modules.select {|mod| target?(mod) }.sort_by{|mod| const_name(mod) }.each do |mod|
43
45
  case mod
44
46
  when Class
45
47
  generate_class mod
@@ -48,16 +50,21 @@ module RBS
48
50
  end
49
51
  end
50
52
  end
53
+
51
54
  @decls
52
55
  end
53
56
 
54
- def to_type_name(name)
57
+ def to_type_name(name, full_name: false)
55
58
  *prefix, last = name.split(/::/)
56
59
 
57
- if prefix.empty?
58
- TypeName.new(name: last.to_sym, namespace: Namespace.empty)
60
+ if full_name
61
+ if prefix.empty?
62
+ TypeName.new(name: last.to_sym, namespace: Namespace.empty)
63
+ else
64
+ TypeName.new(name: last.to_sym, namespace: Namespace.parse(prefix.join("::")))
65
+ end
59
66
  else
60
- TypeName.new(name: last.to_sym, namespace: Namespace.parse(prefix.join("::")))
67
+ TypeName.new(name: last.to_sym, namespace: Namespace.empty)
61
68
  end
62
69
  end
63
70
 
@@ -131,6 +138,11 @@ module RBS
131
138
  end
132
139
  end
133
140
 
141
+ return_type = if method.name == :initialize
142
+ Types::Bases::Void.new(location: nil)
143
+ else
144
+ untyped
145
+ end
134
146
  method_type = Types::Function.new(
135
147
  required_positionals: required_positionals,
136
148
  optional_positionals: optional_positionals,
@@ -139,7 +151,7 @@ module RBS
139
151
  required_keywords: required_keywords,
140
152
  optional_keywords: optional_keywords,
141
153
  rest_keywords: rest_keywords,
142
- return_type: untyped
154
+ return_type: return_type,
143
155
  )
144
156
 
145
157
  MethodType.new(
@@ -300,7 +312,7 @@ module RBS
300
312
  end
301
313
  end
302
314
 
303
- def generate_constants(mod)
315
+ def generate_constants(mod, decls)
304
316
  mod.constants(false).sort.each do |name|
305
317
  value = mod.const_get(name)
306
318
 
@@ -324,8 +336,8 @@ module RBS
324
336
  Types::ClassInstance.new(name: value_type_name, args: args, location: nil)
325
337
  end
326
338
 
327
- @decls << AST::Declarations::Constant.new(
328
- name: "#{const_name(mod)}::#{name}",
339
+ decls << AST::Declarations::Constant.new(
340
+ name: name,
329
341
  type: type,
330
342
  location: nil,
331
343
  comment: nil
@@ -333,28 +345,38 @@ module RBS
333
345
  end
334
346
  end
335
347
 
348
+ def generate_super_class(mod)
349
+ if mod.superclass == ::Object
350
+ nil
351
+ elsif const_name(mod.superclass).nil?
352
+ RBS.logger.warn("Skipping anonymous superclass #{mod.superclass} of #{mod}")
353
+ nil
354
+ else
355
+ super_name = to_type_name(const_name(mod.superclass), full_name: true)
356
+ super_args = type_args(super_name)
357
+ AST::Declarations::Class::Super.new(name: super_name, args: super_args, location: nil)
358
+ end
359
+ end
360
+
336
361
  def generate_class(mod)
337
362
  type_name = to_type_name(const_name(mod))
338
- super_class = if mod.superclass == ::Object
339
- nil
340
- elsif const_name(mod.superclass).nil?
341
- RBS.logger.warn("Skipping anonymous superclass #{mod.superclass} of #{mod}")
342
- nil
343
- else
344
- super_name = to_type_name(const_name(mod.superclass))
345
- super_args = type_args(super_name)
346
- AST::Declarations::Class::Super.new(name: super_name, args: super_args, location: nil)
347
- end
363
+ outer_decls = ensure_outer_module_declarations(mod)
364
+
365
+ # Check if a declaration exists for the actual module
366
+ decl = outer_decls.detect { |decl| decl.is_a?(AST::Declarations::Class) && decl.name.name == only_name(mod).to_sym }
367
+ unless decl
368
+ decl = AST::Declarations::Class.new(
369
+ name: to_type_name(only_name(mod)),
370
+ type_params: AST::Declarations::ModuleTypeParams.empty,
371
+ super_class: generate_super_class(mod),
372
+ members: [],
373
+ annotations: [],
374
+ location: nil,
375
+ comment: nil
376
+ )
348
377
 
349
- decl = AST::Declarations::Class.new(
350
- name: type_name,
351
- type_params: AST::Declarations::ModuleTypeParams.empty,
352
- super_class: super_class,
353
- members: [],
354
- annotations: [],
355
- location: nil,
356
- comment: nil
357
- )
378
+ outer_decls << decl
379
+ end
358
380
 
359
381
  each_included_module(type_name, mod) do |module_name, module_full_name, _|
360
382
  args = type_args(module_full_name)
@@ -380,9 +402,7 @@ module RBS
380
402
 
381
403
  generate_methods(mod, type_name, decl.members)
382
404
 
383
- @decls << decl
384
-
385
- generate_constants mod
405
+ generate_constants mod, decl.members
386
406
  end
387
407
 
388
408
  def generate_module(mod)
@@ -394,16 +414,23 @@ module RBS
394
414
  end
395
415
 
396
416
  type_name = to_type_name(name)
417
+ outer_decls = ensure_outer_module_declarations(mod)
418
+
419
+ # Check if a declaration exists for the actual class
420
+ decl = outer_decls.detect { |decl| decl.is_a?(AST::Declarations::Module) && decl.name.name == only_name(mod).to_sym }
421
+ unless decl
422
+ decl = AST::Declarations::Module.new(
423
+ name: to_type_name(only_name(mod)),
424
+ type_params: AST::Declarations::ModuleTypeParams.empty,
425
+ self_types: [],
426
+ members: [],
427
+ annotations: [],
428
+ location: nil,
429
+ comment: nil
430
+ )
397
431
 
398
- decl = AST::Declarations::Module.new(
399
- name: type_name,
400
- type_params: AST::Declarations::ModuleTypeParams.empty,
401
- self_types: [],
402
- members: [],
403
- annotations: [],
404
- location: nil,
405
- comment: nil
406
- )
432
+ outer_decls << decl
433
+ end
407
434
 
408
435
  each_included_module(type_name, mod) do |module_name, module_full_name, _|
409
436
  args = type_args(module_full_name)
@@ -429,9 +456,58 @@ module RBS
429
456
 
430
457
  generate_methods(mod, type_name, decl.members)
431
458
 
432
- @decls << decl
459
+ generate_constants mod, decl.members
460
+ end
461
+
462
+ # Generate/find outer module declarations
463
+ # This is broken down into another method to comply with `DRY`
464
+ # This generates/finds declarations in nested form & returns the last array of declarations
465
+ def ensure_outer_module_declarations(mod)
466
+ *outer_module_names, _ = const_name(mod).split(/::/) #=> parent = [A, B], mod = C
467
+ destination = @decls # Copy the entries in ivar @decls, not .dup
468
+
469
+ outer_module_names&.each do |outer_module_name|
470
+ outer_module = @modules.detect { |x| const_name(x) == outer_module_name }
471
+ outer_decl = destination.detect { |decl| decl.is_a?(outer_module.is_a?(Class) ? AST::Declarations::Class : AST::Declarations::Module) && decl.name.name == outer_module_name.to_sym }
472
+
473
+ # Insert AST::Declarations if declarations are not added previously
474
+ unless outer_decl
475
+ if outer_module.is_a?(Class)
476
+ outer_decl = AST::Declarations::Class.new(
477
+ name: to_type_name(outer_module_name),
478
+ type_params: AST::Declarations::ModuleTypeParams.empty,
479
+ super_class: generate_super_class(outer_module),
480
+ members: [],
481
+ annotations: [],
482
+ location: nil,
483
+ comment: nil
484
+ )
485
+ else
486
+ outer_decl = AST::Declarations::Module.new(
487
+ name: to_type_name(outer_module_name),
488
+ type_params: AST::Declarations::ModuleTypeParams.empty,
489
+ self_types: [],
490
+ members: [],
491
+ annotations: [],
492
+ location: nil,
493
+ comment: nil
494
+ )
495
+ end
496
+
497
+ destination << outer_decl
498
+ end
499
+
500
+ destination = outer_decl.members
501
+ end
502
+
503
+ # Return the array of declarations checked out at the end
504
+ destination
505
+ end
433
506
 
434
- generate_constants mod
507
+ # Returns the exact name & not compactly declared name
508
+ def only_name(mod)
509
+ # No nil check because this method is invoked after checking if the module exists
510
+ const_name(mod).split(/::/).last # (A::B::C) => C
435
511
  end
436
512
 
437
513
  def const_name(const)
data/lib/rbs/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RBS
2
- VERSION = "1.2.1"
2
+ VERSION = "1.3.0"
3
3
  end
@@ -80,6 +80,7 @@ module RBS
80
80
  def interface_ancestors: (TypeName, ?building_ancestors: Array[Definition::Ancestor::t]) -> Definition::InstanceAncestors
81
81
 
82
82
  def mixin_ancestors: (Environment::ClassEntry | Environment::ModuleEntry,
83
+ TypeName,
83
84
  included_modules: Array[Definition::Ancestor::Instance]?,
84
85
  included_interfaces:Array[Definition::Ancestor::Instance]?,
85
86
  prepended_modules: Array[Definition::Ancestor::Instance]?,
@@ -87,6 +88,7 @@ module RBS
87
88
  extended_interfaces: Array[Definition::Ancestor::Instance]?) -> void
88
89
 
89
90
  def mixin_ancestors0: (AST::Declarations::Class | AST::Declarations::Module | AST::Declarations::Interface,
91
+ TypeName,
90
92
  align_params: Substitution?,
91
93
  included_modules: Array[Definition::Ancestor::Instance]?,
92
94
  included_interfaces:Array[Definition::Ancestor::Instance]?,
data/sig/errors.rbs CHANGED
@@ -181,4 +181,19 @@ module RBS
181
181
 
182
182
  def location: () -> Location?
183
183
  end
184
+
185
+ class MixinClassError < DefinitionError
186
+ type member = AST::Members::Include | AST::Members::Prepend | AST::Members::Extend
187
+
188
+ attr_reader type_name: TypeName
189
+ attr_reader member: member
190
+
191
+ def initialize: (type_name: TypeName, member: member) -> void
192
+
193
+ def location: () -> Location?
194
+
195
+ def self.check!: (type_name: TypeName, env: Environment, member: member) -> void
196
+
197
+ def mixin_name: () -> String
198
+ end
184
199
  end
data/sig/namespace.rbs CHANGED
@@ -13,7 +13,7 @@ module RBS
13
13
  # RBS::Types::Union
14
14
  # ^^^^^^^^^^^^ Namespace
15
15
  #
16
- # Note that `Namespace` is a RBS specific concept and there is no corresponding concept in Ruby.
16
+ # Note that `Namespace` is an RBS specific concept and there is no corresponding concept in Ruby.
17
17
  #
18
18
  # There are _absolute_ and _relative_ namespaces.
19
19
  #
data/sig/polyfill.rbs CHANGED
@@ -11,24 +11,6 @@ module Gem
11
11
  end
12
12
  end
13
13
 
14
- class OptionParser
15
- def initialize: () ?{ (instance) -> void } -> void
16
-
17
- def on: [T] (*String) { (T) -> void } -> void
18
-
19
- attr_accessor version: String
20
-
21
- attr_accessor banner: String
22
-
23
- def order!: (Array[String]) -> void
24
-
25
- def parse!: (Array[String]) -> void
26
-
27
- def ver: () -> String
28
-
29
- def help: () -> String
30
- end
31
-
32
14
  module Enumerable[unchecked out Elem]
33
15
  def flat_map: [U] () { (Elem) -> Array[U] } -> Array[U]
34
16
  | [U] () { (Elem) -> U } -> Array[U]
data/stdlib/dbm/0/dbm.rbs CHANGED
@@ -61,23 +61,24 @@
61
61
  # puts db['822']
62
62
  #
63
63
  class DBM
64
- include Enumerable[untyped]
64
+ include Enumerable[[String, String]]
65
65
 
66
66
  # Open a dbm database and yields it if a block is given. See also `DBM.new`.
67
67
  #
68
- def self.open: (*untyped) -> ::DBM
68
+ def self.open: (String filename, ?Integer mode, ?Integer flags) -> DBM
69
+ | [T] (String filename, ?Integer mode, ?Integer flags) { (DBM) -> T } -> T
69
70
 
70
71
  public
71
72
 
72
73
  # Return a value from the database by locating the key string provided. If the
73
74
  # key is not found, returns nil.
74
75
  #
75
- def []: (untyped) -> untyped
76
+ def []: (String) -> String?
76
77
 
77
78
  # Stores the specified string value in the database, indexed via the string key
78
79
  # provided.
79
80
  #
80
- def []=: (untyped, untyped) -> untyped
81
+ def []=: (String, String) -> String
81
82
 
82
83
  # Deletes all data from the database.
83
84
  #
@@ -85,7 +86,7 @@ class DBM
85
86
 
86
87
  # Closes the database.
87
88
  #
88
- def close: () -> NilClass
89
+ def close: () -> void
89
90
 
90
91
  # Returns true if the database is closed, false otherwise.
91
92
  #
@@ -93,27 +94,31 @@ class DBM
93
94
 
94
95
  # Deletes an entry from the database.
95
96
  #
96
- def delete: (untyped) -> untyped
97
+ def delete: (String) -> void
97
98
 
98
99
  # Deletes all entries for which the code block returns true. Returns self.
99
100
  #
100
- def delete_if: () ?{ (untyped) -> bool } -> self
101
+ def delete_if: () { (String) -> boolish } -> self
101
102
 
102
103
  # Calls the block once for each [key, value] pair in the database. Returns self.
103
104
  #
104
- def each: (?untyped, ?untyped) -> Enumerator[untyped, ::DBM]
105
+ def each: () { ([String, String]) -> void } -> self
106
+ | () -> Enumerator[[String, String], self]
105
107
 
106
108
  # Calls the block once for each key string in the database. Returns self.
107
109
  #
108
- def each_key: () -> Enumerator[String, ::DBM]
110
+ def each_key: { (String) -> void } -> self
111
+ | () -> Enumerator[String, self]
109
112
 
110
113
  # Calls the block once for each [key, value] pair in the database. Returns self.
111
114
  #
112
- def each_pair: (?untyped, ?untyped) -> Enumerator[untyped, ::DBM]
115
+ def each_pair: () { ([String, String]) -> void } -> self
116
+ | () -> Enumerator[[String, String], self]
113
117
 
114
118
  # Calls the block once for each value string in the database. Returns self.
115
119
  #
116
- def each_value: () -> Enumerator[untyped, ::DBM]
120
+ def each_value: () { (String) -> void } -> self
121
+ | () -> Enumerator[String, self]
117
122
 
118
123
  # Returns true if the database is empty, false otherwise.
119
124
  #
@@ -123,7 +128,7 @@ class DBM
123
128
  # key is not found, returns `ifnone`. If `ifnone` is not given, raises
124
129
  # IndexError.
125
130
  #
126
- def fetch: (*String) -> untyped
131
+ def fetch: (String key, ?String ifnone) -> String
127
132
 
128
133
  # Returns true if the database contains the specified key, false otherwise.
129
134
  #
@@ -132,7 +137,7 @@ class DBM
132
137
  # Returns true if the database contains the specified string value, false
133
138
  # otherwise.
134
139
  #
135
- def has_value?: (untyped) -> bool
140
+ def has_value?: () -> bool
136
141
 
137
142
  # Returns true if the database contains the specified key, false otherwise.
138
143
  #
@@ -141,15 +146,15 @@ class DBM
141
146
  # Returns a Hash (not a DBM database) created by using each value in the
142
147
  # database as a key, with the corresponding key as its value.
143
148
  #
144
- def invert: () -> Hash[untyped, String]
149
+ def invert: () -> Hash[String, String]
145
150
 
146
151
  # Returns the key for the specified value.
147
152
  #
148
- def key: (untyped) -> (String | NilClass)
153
+ def key: (String) -> String?
149
154
 
150
155
  # Returns true if the database contains the specified key, false otherwise.
151
156
  #
152
- def key?: (untyped) -> bool
157
+ def key?: (String) -> bool
153
158
 
154
159
  # Returns an array of all the string keys in the database.
155
160
  #
@@ -161,33 +166,37 @@ class DBM
161
166
 
162
167
  # Returns true if the database contains the specified key, false otherwise.
163
168
  #
164
- def member?: (untyped) -> bool
169
+ def member?: (String) -> bool
165
170
 
166
171
  # Converts the contents of the database to an in-memory Hash, then calls
167
172
  # Hash#reject with the specified code block, returning a new Hash.
168
173
  #
169
- def reject: () -> Hash[untyped, untyped]
174
+ def reject: () { (String, String) -> boolish } -> Hash[String, String]
170
175
 
171
176
  # Deletes all entries for which the code block returns true. Returns self.
172
177
  #
173
- def reject!: () { (String, untyped) -> untyped } -> self
178
+ def reject!: () { (String, String) -> boolish } -> self
174
179
 
175
180
  # Replaces the contents of the database with the contents of the specified
176
181
  # object. Takes any object which implements the each_pair method, including Hash
177
182
  # and DBM objects.
178
183
  #
179
- def replace: (untyped) -> ::DBM
184
+ def replace: (_ReplaceSource) -> ::DBM
185
+
186
+ interface _ReplaceSource
187
+ def each_pair: () { ([String, String]) -> void } -> void
188
+ end
180
189
 
181
190
  # Returns a new array consisting of the [key, value] pairs for which the code
182
191
  # block returns true.
183
192
  #
184
- def select: () { () -> untyped } -> Array[untyped]
193
+ def select: () { ([String, String]) -> boolish } -> Array[[String, String]]
185
194
 
186
195
  # Removes a [key, value] pair from the database, and returns it. If the database
187
196
  # is empty, returns nil. The order in which values are removed/returned is not
188
197
  # guaranteed.
189
198
  #
190
- def shift: () -> Array[untyped]
199
+ def shift: () -> [String, String]?
191
200
 
192
201
  # Returns the number of entries in the database.
193
202
  #
@@ -196,35 +205,39 @@ class DBM
196
205
  # Stores the specified string value in the database, indexed via the string key
197
206
  # provided.
198
207
  #
199
- def store: (String, untyped) -> String
208
+ def store: (String, String) -> String
200
209
 
201
210
  # Converts the contents of the database to an array of [key, value] arrays, and
202
211
  # returns it.
203
212
  #
204
- def to_a: () -> Array[untyped]
213
+ def to_a: () -> Array[[String, String]]
205
214
 
206
215
  # Converts the contents of the database to an in-memory Hash object, and returns
207
216
  # it.
208
217
  #
209
- def to_hash: () -> Hash[String, untyped]
218
+ def to_hash: () -> Hash[String, String]
210
219
 
211
220
  # Updates the database with multiple values from the specified object. Takes any
212
221
  # object which implements the each_pair method, including Hash and DBM objects.
213
222
  #
214
- def update: (untyped) -> ::DBM
223
+ def update: (_UpdateSource) -> ::DBM
224
+
225
+ interface _UpdateSource
226
+ def each_pair: () { ([String, String]) -> void } -> void
227
+ end
215
228
 
216
229
  # Returns true if the database contains the specified string value, false
217
230
  # otherwise.
218
231
  #
219
- def value?: (untyped) -> bool
232
+ def value?: (String) -> bool
220
233
 
221
234
  # Returns an array of all the string values in the database.
222
235
  #
223
- def values: () -> Array[untyped]
236
+ def values: () -> Array[String]
224
237
 
225
238
  # Returns an array containing the values associated with the given keys.
226
239
  #
227
- def values_at: (*String) -> Array[untyped]
240
+ def values_at: (*String) -> Array[String]
228
241
 
229
242
  private
230
243
 
@@ -237,7 +250,7 @@ class DBM
237
250
  #
238
251
  # Flags should be one of READER, WRITER, WRCREAT or NEWDB.
239
252
  #
240
- def initialize: (*untyped) -> self
253
+ def initialize: (String filename, ?Integer mode, ?Integer flags) -> void
241
254
  end
242
255
 
243
256
  # Indicates that dbm_open() should open the database in read/write mode, create