rbs 0.5.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -0
  3. data/Gemfile +2 -0
  4. data/Rakefile +2 -3
  5. data/docs/stdlib.md +0 -2
  6. data/docs/syntax.md +6 -3
  7. data/goodcheck.yml +65 -0
  8. data/lib/rbs.rb +1 -0
  9. data/lib/rbs/ast/comment.rb +6 -0
  10. data/lib/rbs/ast/declarations.rb +44 -6
  11. data/lib/rbs/cli.rb +21 -3
  12. data/lib/rbs/constant_table.rb +1 -1
  13. data/lib/rbs/definition_builder.rb +290 -124
  14. data/lib/rbs/environment.rb +50 -37
  15. data/lib/rbs/errors.rb +68 -25
  16. data/lib/rbs/factory.rb +14 -0
  17. data/lib/rbs/location.rb +15 -0
  18. data/lib/rbs/parser.y +89 -28
  19. data/lib/rbs/prototype/rb.rb +2 -2
  20. data/lib/rbs/prototype/rbi.rb +1 -1
  21. data/lib/rbs/prototype/runtime.rb +1 -1
  22. data/lib/rbs/substitution.rb +6 -2
  23. data/lib/rbs/test.rb +82 -3
  24. data/lib/rbs/test/errors.rb +5 -1
  25. data/lib/rbs/test/hook.rb +133 -259
  26. data/lib/rbs/test/observer.rb +17 -0
  27. data/lib/rbs/test/setup.rb +37 -20
  28. data/lib/rbs/test/setup_helper.rb +29 -0
  29. data/lib/rbs/test/spy.rb +0 -321
  30. data/lib/rbs/test/tester.rb +118 -0
  31. data/lib/rbs/test/type_check.rb +42 -5
  32. data/lib/rbs/validator.rb +4 -0
  33. data/lib/rbs/version.rb +1 -1
  34. data/lib/rbs/writer.rb +2 -2
  35. data/schema/decls.json +21 -10
  36. data/stdlib/builtin/enumerable.rbs +2 -2
  37. data/stdlib/builtin/proc.rbs +1 -2
  38. data/stdlib/json/json.rbs +6 -0
  39. data/stdlib/logger/formatter.rbs +23 -0
  40. data/stdlib/logger/log_device.rbs +39 -0
  41. data/stdlib/logger/logger.rbs +507 -0
  42. data/stdlib/logger/period.rbs +7 -0
  43. data/stdlib/logger/severity.rbs +8 -0
  44. data/stdlib/pty/pty.rbs +159 -0
  45. metadata +13 -3
  46. data/lib/rbs/test/test_helper.rb +0 -180
@@ -34,56 +34,49 @@ module RBS
34
34
 
35
35
  def insert(decl:, outer:)
36
36
  decls << D.new(decl: decl, outer: outer)
37
+ @primary = nil
37
38
  end
38
39
 
39
- def type_params
40
- primary.decl.type_params
41
- end
42
- end
40
+ def validate_type_params
41
+ unless decls.empty?
42
+ hd_decl, *tl_decls = decls
43
+ hd_params = hd_decl.decl.type_params
44
+ hd_names = hd_params.params.map(&:name)
43
45
 
44
- class ModuleEntry < MultiEntry
45
- def insert(decl:, outer:)
46
- unless decl.is_a?(AST::Declarations::Module)
47
- raise MixedClassModuleDeclarationError.new(name: name, decl: decl)
48
- end
46
+ tl_decls.each do |tl_decl|
47
+ tl_params = tl_decl.decl.type_params
49
48
 
50
- unless decls.empty?
51
- names = decls[0].decl.type_params.each.map(&:name)
52
- unless names.size == decl.type_params.each.size && decls[0].decl.type_params == decl.type_params.rename_to(names)
53
- raise GenericParameterMismatchError.new(name: name, decl: decl)
49
+ unless hd_params.size == tl_params.size && hd_params == tl_params.rename_to(hd_names)
50
+ raise GenericParameterMismatchError.new(name: name, decl: tl_decl.decl)
51
+ end
54
52
  end
55
53
  end
54
+ end
56
55
 
57
- super(decl: decl, outer: outer)
56
+ def type_params
57
+ primary.decl.type_params
58
58
  end
59
+ end
59
60
 
60
- def primary
61
- @primary ||= decls.find {|d| d.decl.self_type } || decls.first
61
+ class ModuleEntry < MultiEntry
62
+ def self_types
63
+ decls.flat_map do |d|
64
+ d.decl.self_types
65
+ end.uniq
62
66
  end
63
67
 
64
- def self_type
65
- primary.decl.self_type
68
+ def primary
69
+ @primary ||= begin
70
+ validate_type_params
71
+ decls.first
72
+ end
66
73
  end
67
74
  end
68
75
 
69
76
  class ClassEntry < MultiEntry
70
- def insert(decl:, outer:)
71
- unless decl.is_a?(AST::Declarations::Class)
72
- raise MixedClassModuleDeclarationError.new(name: name, decl: decl)
73
- end
74
-
75
- unless decls.empty?
76
- names = decls[0].decl.type_params.each.map(&:name)
77
- unless names.size == decl.type_params.each.size && decls[0].decl.type_params == decl.type_params.rename_to(names)
78
- raise GenericParameterMismatchError.new(name: name, decl: decl)
79
- end
80
- end
81
-
82
- super(decl: decl, outer: outer)
83
- end
84
-
85
77
  def primary
86
78
  @primary ||= begin
79
+ validate_type_params
87
80
  decls.find {|d| d.decl.super_class } || decls.first
88
81
  end
89
82
  end
@@ -133,7 +126,7 @@ module RBS
133
126
 
134
127
  def cache_name(cache, name:, decl:, outer:)
135
128
  if cache.key?(name)
136
- raise DuplicatedDeclarationError.new(name, decl, cache[name])
129
+ raise DuplicatedDeclarationError.new(name, decl, cache[name].decl)
137
130
  end
138
131
 
139
132
  cache[name] = SingleEntry.new(name: name, decl: decl, outer: outer)
@@ -157,7 +150,18 @@ module RBS
157
150
  end
158
151
  end
159
152
 
160
- class_decls[name].insert(decl: decl, outer: outer)
153
+ existing_entry = class_decls[name]
154
+
155
+ case
156
+ when decl.is_a?(AST::Declarations::Module) && existing_entry.is_a?(ModuleEntry)
157
+ # OK
158
+ when decl.is_a?(AST::Declarations::Class) && existing_entry.is_a?(ClassEntry)
159
+ # OK
160
+ else
161
+ raise DuplicatedDeclarationError.new(name, decl, existing_entry.primary.decl)
162
+ end
163
+
164
+ existing_entry.insert(decl: decl, outer: outer)
161
165
 
162
166
  prefix = outer + [decl]
163
167
  ns = name.to_namespace
@@ -255,8 +259,12 @@ module RBS
255
259
  AST::Declarations::Module.new(
256
260
  name: decl.name.with_prefix(prefix),
257
261
  type_params: decl.type_params,
258
- self_type: decl.self_type&.yield_self do |self_type|
259
- absolute_type(resolver, self_type, context: context)
262
+ self_types: decl.self_types.map do |module_self|
263
+ AST::Declarations::Module::Self.new(
264
+ name: absolute_type_name(resolver, module_self.name, context: context),
265
+ args: module_self.args.map {|type| absolute_type(resolver, type, context: context) },
266
+ location: module_self.location
267
+ )
260
268
  end,
261
269
  members: decl.members.map do |member|
262
270
  case member
@@ -406,5 +414,10 @@ module RBS
406
414
  absolute_type_name(resolver, name, context: context)
407
415
  end
408
416
  end
417
+
418
+ def inspect
419
+ ivars = %i[@buffers @declarations @class_decls @interface_decls @alias_decls @constant_decls @global_decls]
420
+ "\#<RBS::Environment #{ivars.map { |iv| "#{iv}=(#{instance_variable_get(iv).size} items)"}.join(' ')}>"
421
+ end
409
422
  end
410
423
  end
@@ -125,6 +125,74 @@ module RBS
125
125
  end
126
126
  end
127
127
 
128
+ class NoSuperclassFoundError < StandardError
129
+ attr_reader :type_name
130
+ attr_reader :location
131
+
132
+ def initialize(type_name:, location:)
133
+ @type_name = type_name
134
+ @location = location
135
+
136
+ super "#{Location.to_string location}: Could not find super class: #{type_name}"
137
+ end
138
+
139
+ def self.check!(type_name, env:, location:)
140
+ env.class_decls.key?(type_name) or raise new(type_name: type_name, location: location)
141
+ end
142
+ end
143
+
144
+ class NoSelfTypeFoundError < StandardError
145
+ attr_reader :type_name
146
+ attr_reader :location
147
+
148
+ def initialize(type_name:, location:)
149
+ @type_name = type_name
150
+ @location = location
151
+
152
+ super "#{Location.to_string location}: Could not find self type: #{type_name}"
153
+ end
154
+
155
+ def self.check!(self_type, env:)
156
+ type_name = self_type.name
157
+
158
+ dic = case
159
+ when type_name.class?
160
+ env.class_decls
161
+ when type_name.interface?
162
+ env.interface_decls
163
+ end
164
+
165
+ dic.key?(type_name) or raise new(type_name: type_name, location: self_type.location)
166
+ end
167
+ end
168
+
169
+ class NoMixinFoundError < StandardError
170
+ attr_reader :type_name
171
+ attr_reader :member
172
+
173
+ def initialize(type_name:, member:)
174
+ @type_name = type_name
175
+ @member = member
176
+
177
+ super "#{Location.to_string location}: Could not find mixin: #{type_name}"
178
+ end
179
+
180
+ def location
181
+ member.location
182
+ end
183
+
184
+ def self.check!(type_name, env:, member:)
185
+ dic = case
186
+ when type_name.class?
187
+ env.class_decls
188
+ when type_name.interface?
189
+ env.interface_decls
190
+ end
191
+
192
+ dic.key?(type_name) or raise new(type_name: type_name, member: member)
193
+ end
194
+ end
195
+
128
196
  class DuplicatedMethodDefinitionError < StandardError
129
197
  attr_reader :decl
130
198
  attr_reader :location
@@ -187,17 +255,6 @@ module RBS
187
255
  end
188
256
  end
189
257
 
190
- class MixedClassModuleDeclarationError < StandardError
191
- attr_reader :name
192
- attr_reader :decl
193
-
194
- def initialize(name:, decl:)
195
- @name = name
196
- @decl = decl
197
- super "#{Location.to_string decl.location}: Both class and module declarations: #{name}"
198
- end
199
- end
200
-
201
258
  class SuperclassMismatchError < StandardError
202
259
  attr_reader :name
203
260
  attr_reader :entry
@@ -209,20 +266,6 @@ module RBS
209
266
  end
210
267
  end
211
268
 
212
- class ModuleSelfTypeMismatchError < StandardError
213
- attr_reader :name
214
- attr_reader :entry
215
- attr_reader :location
216
-
217
- def initialize(name:, entry:, location:)
218
- @name = name
219
- @entry = entry
220
- @location = location
221
-
222
- super "#{Location.to_string location}: Module self type mismatch: #{name}"
223
- end
224
- end
225
-
226
269
  class InconsistentMethodVisibilityError < StandardError
227
270
  attr_reader :type_name
228
271
  attr_reader :method_name
@@ -0,0 +1,14 @@
1
+ module RBS
2
+ class Factory
3
+ def type_name(string)
4
+ absolute = string.start_with?("::")
5
+
6
+ *path, name = string.delete_prefix("::").split("::").map(&:to_sym)
7
+
8
+ TypeName.new(
9
+ name: name,
10
+ namespace: Namespace.new(path: path, absolute: absolute)
11
+ )
12
+ end
13
+ end
14
+ end
@@ -77,6 +77,21 @@ module RBS
77
77
  locations.inject {|l1, l2| l1 + l2 }
78
78
  end
79
79
 
80
+ def concat(*others)
81
+ others.each { |other| self << other }
82
+ self
83
+ end
84
+
85
+ def <<(other)
86
+ if other
87
+ raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
88
+ @end_pos = other.end_pos
89
+ @source = nil
90
+ @end_loc = nil
91
+ end
92
+ self
93
+ end
94
+
80
95
  def pred?(loc)
81
96
  loc.is_a?(Location) &&
82
97
  loc.name == name &&
@@ -4,9 +4,9 @@ class RBS::Parser
4
4
  tANNOTATION
5
5
  tSTRING tSYMBOL tINTEGER tWRITE_ATTR
6
6
  kLPAREN kRPAREN kLBRACKET kRBRACKET kLBRACE kRBRACE
7
- kVOID kNIL kTRUE kFALSE kANY kUNTYPED kTOP kBOT kSELF kSELFQ kINSTANCE kCLASS kBOOL kSINGLETON kTYPE kDEF kMODULE kSUPER
7
+ kVOID kNIL kTRUE kFALSE kANY kUNTYPED kTOP kBOT kSELF kSELFQ kINSTANCE kCLASS kBOOL kSINGLETON kTYPE kDEF kMODULE
8
8
  kPRIVATE kPUBLIC kALIAS
9
- kCOLON kCOLON2 kCOMMA kBAR kAMP kHAT kARROW kQUESTION kEXCLAMATION kSTAR kSTAR2 kFATARROW kEQ kDOT kLT
9
+ kCOLON kCOLON2 kCOMMA kBAR kAMP kHAT kARROW kQUESTION kEXCLAMATION kSTAR kSTAR2 kFATARROW kEQ kDOT kDOT3 kLT
10
10
  kINTERFACE kEND kINCLUDE kEXTEND kATTRREADER kATTRWRITER kATTRACCESSOR tOPERATOR tQUOTEDMETHOD tQUOTEDIDENT
11
11
  kPREPEND kEXTENSION kINCOMPATIBLE
12
12
  type_TYPE type_SIGNATURE type_METHODTYPE tEOF
@@ -106,28 +106,28 @@ rule
106
106
  }
107
107
 
108
108
  module_decl:
109
- annotations kMODULE start_new_scope class_name module_type_params module_self_type class_members kEND {
109
+ annotations kMODULE start_new_scope class_name module_type_params colon_module_self_types class_members kEND {
110
110
  reset_variable_scope
111
111
 
112
112
  location = val[1].location + val[7].location
113
113
  result = Declarations::Module.new(
114
114
  name: val[3].value,
115
115
  type_params: val[4]&.value || Declarations::ModuleTypeParams.empty,
116
- self_type: val[5],
116
+ self_types: val[5],
117
117
  members: val[6],
118
118
  annotations: val[0],
119
119
  location: location,
120
120
  comment: leading_comment(val[0].first&.location || location)
121
121
  )
122
122
  }
123
- | annotations kMODULE start_new_scope tUKEYWORD type class_members kEND {
123
+ | annotations kMODULE start_new_scope tUKEYWORD module_self_types class_members kEND {
124
124
  reset_variable_scope
125
125
 
126
126
  location = val[1].location + val[6].location
127
127
  result = Declarations::Module.new(
128
128
  name: val[3].value,
129
129
  type_params: Declarations::ModuleTypeParams.empty,
130
- self_type: val[4],
130
+ self_types: val[4],
131
131
  members: val[5],
132
132
  annotations: val[0],
133
133
  location: location,
@@ -135,12 +135,50 @@ rule
135
135
  )
136
136
  }
137
137
 
138
- module_self_type:
139
- { result = nil }
140
- | kCOLON type {
138
+ colon_module_self_types:
139
+ { result = [] }
140
+ | kCOLON module_self_types {
141
141
  result = val[1]
142
142
  }
143
143
 
144
+ module_self_types:
145
+ module_self_type {
146
+ result = [val[0]]
147
+ }
148
+ | module_self_types kCOMMA module_self_type {
149
+ result = val[0].push(val[2])
150
+ }
151
+
152
+ module_self_type:
153
+ qualified_name kLBRACKET type_list kRBRACKET {
154
+ name = val[0].value
155
+ args = val[2]
156
+ location = val[0].location + val[3].location
157
+
158
+ case
159
+ when name.class?
160
+ result = Declarations::Module::Self.new(name: name, args: args, location: location)
161
+ when name.interface?
162
+ result = Declarations::Module::Self.new(name: name, args: args, location: location)
163
+ else
164
+ raise SemanticsError.new("Module self type should be instance or interface", subject: val[0], location: val[0].location)
165
+ end
166
+ }
167
+ | qualified_name {
168
+ name = val[0].value
169
+ args = []
170
+ location = val[0].location
171
+
172
+ case
173
+ when name.class?
174
+ result = Declarations::Module::Self.new(name: name, args: args, location: location)
175
+ when name.interface?
176
+ result = Declarations::Module::Self.new(name: name, args: args, location: location)
177
+ else
178
+ raise SemanticsError.new("Module self type should be instance or interface", subject: val[0], location: val[0].location)
179
+ end
180
+ }
181
+
144
182
  class_members:
145
183
  { result = [] }
146
184
  | class_members class_member {
@@ -387,7 +425,12 @@ rule
387
425
  comment: leading_comment(val[0].first&.location || location))
388
426
  }
389
427
 
390
- overload: { result = nil } | kOVERLOAD
428
+ overload:
429
+ { result = nil }
430
+ | kOVERLOAD {
431
+ RBS.logger.warn "`overload def` syntax is deprecated. Use `...` syntax instead."
432
+ result = val[0]
433
+ }
391
434
 
392
435
  method_member:
393
436
  annotations attributes overload kDEF method_kind def_name method_types {
@@ -400,15 +443,24 @@ rule
400
443
  type
401
444
  end
402
445
  end
446
+
447
+ last_type = val[6].last
448
+ if last_type.is_a?(LocatedValue) && last_type.value == :dot3
449
+ overload = true
450
+ val[6].pop
451
+ else
452
+ overload = false
453
+ end
454
+
403
455
  result = Members::MethodDefinition.new(
404
456
  name: val[5].value,
405
457
  kind: val[4],
406
- types: types,
458
+ types: val[6],
407
459
  annotations: val[0],
408
460
  location: location,
409
461
  comment: leading_comment(val[0].first&.location || val[1].first&.location || val[2]&.location || val[3].location),
410
462
  attributes: val[1].map(&:value),
411
- overload: !!val[2]
463
+ overload: overload || !!val[2]
412
464
  )
413
465
  }
414
466
 
@@ -425,7 +477,7 @@ rule
425
477
 
426
478
  method_types:
427
479
  method_type { result = [val[0]] }
428
- | kSUPER { result = [LocatedValue.new(value: :super, location: val[0].location)] }
480
+ | kDOT3 { result = [LocatedValue.new(value: :dot3, location: val[0].location)] }
429
481
  | method_type kBAR method_types {
430
482
  result = val[2].unshift(val[0])
431
483
  }
@@ -482,7 +534,7 @@ rule
482
534
 
483
535
  method_name:
484
536
  tOPERATOR
485
- | kAMP | kHAT | kSTAR | kLT | kEXCLAMATION | kSTAR2 | kBAR | kOUT | kIN
537
+ | kAMP | kHAT | kSTAR | kLT | kEXCLAMATION | kSTAR2 | kBAR
486
538
  | method_name0
487
539
  | method_name0 kQUESTION {
488
540
  unless val[0].location.pred?(val[1].location)
@@ -510,7 +562,7 @@ rule
510
562
  kCLASS | kVOID | kNIL | kTRUE | kFALSE | kANY | kUNTYPED | kTOP | kBOT | kINSTANCE | kBOOL | kSINGLETON
511
563
  | kTYPE | kMODULE | kPRIVATE | kPUBLIC | kEND | kINCLUDE | kEXTEND | kPREPEND
512
564
  | kATTRREADER | kATTRACCESSOR | kATTRWRITER | kDEF | kEXTENSION | kSELF | kINCOMPATIBLE
513
- | kUNCHECKED | kINTERFACE | kSUPER | kALIAS | kOUT | kIN | kOVERLOAD
565
+ | kUNCHECKED | kINTERFACE | kALIAS | kOUT | kIN | kOVERLOAD
514
566
 
515
567
  module_type_params:
516
568
  { result = nil }
@@ -1030,6 +1082,7 @@ def initialize(type, buffer:, eof_re:)
1030
1082
  @eof = false
1031
1083
  @bound_variables_stack = []
1032
1084
  @comments = {}
1085
+ @ascii_only = buffer.content.ascii_only?
1033
1086
  end
1034
1087
 
1035
1088
  def start_merged_variables_scope
@@ -1111,20 +1164,19 @@ def leading_comment(location)
1111
1164
  end
1112
1165
 
1113
1166
  def push_comment(string, location)
1114
- new_comment = AST::Comment.new(string: string+"\n", location: location)
1115
-
1116
- if (prev_comment = leading_comment(location)) && prev_comment.location.start_column == location.start_column
1117
- @comments.delete prev_comment.location.end_line
1118
- new_comment = AST::Comment.new(string: prev_comment.string + new_comment.string,
1119
- location: prev_comment.location + new_comment.location)
1167
+ if (comment = leading_comment(location)) && comment.location.start_column == location.start_column
1168
+ comment.concat(string: "#{string}\n", location: location)
1169
+ @comments[comment.location.end_line] = comment
1170
+ else
1171
+ new_comment = AST::Comment.new(string: "#{string}\n", location: location)
1172
+ @comments[new_comment.location.end_line] = new_comment
1120
1173
  end
1121
-
1122
- @comments[new_comment.location.end_line] = new_comment
1123
1174
  end
1124
1175
 
1125
1176
  def new_token(type, value = input.matched)
1126
- start_index = input.charpos - input.matched.size
1127
- end_index = input.charpos
1177
+ charpos = charpos(input)
1178
+ start_index = charpos - input.matched.size
1179
+ end_index = charpos
1128
1180
 
1129
1181
  location = RBS::Location.new(buffer: buffer,
1130
1182
  start_pos: start_index,
@@ -1133,6 +1185,14 @@ def new_token(type, value = input.matched)
1133
1185
  [type, LocatedValue.new(location: location, value: value)]
1134
1186
  end
1135
1187
 
1188
+ def charpos(scanner)
1189
+ if @ascii_only
1190
+ scanner.pos
1191
+ else
1192
+ scanner.charpos
1193
+ end
1194
+ end
1195
+
1136
1196
  def empty_params_result
1137
1197
  [
1138
1198
  [],
@@ -1170,7 +1230,6 @@ KEYWORDS = {
1170
1230
  "attr_reader" => :kATTRREADER,
1171
1231
  "attr_writer" => :kATTRWRITER,
1172
1232
  "attr_accessor" => :kATTRACCESSOR,
1173
- "super" => :kSUPER,
1174
1233
  "public" => :kPUBLIC,
1175
1234
  "private" => :kPRIVATE,
1176
1235
  "alias" => :kALIAS,
@@ -1219,6 +1278,7 @@ PUNCTS = {
1219
1278
  "!" => :kEXCLAMATION,
1220
1279
  "**" => :kSTAR2,
1221
1280
  "*" => :kSTAR,
1281
+ "..." => :kDOT3,
1222
1282
  "." => :kDOT,
1223
1283
  "<" => :kLT,
1224
1284
  "-@" => :tOPERATOR,
@@ -1250,8 +1310,9 @@ def next_token
1250
1310
  when input.scan(/\s+/)
1251
1311
  # skip
1252
1312
  when input.scan(/#(( *)|( ?(?<string>.*)))\n/)
1253
- start_index = input.charpos - input.matched.size
1254
- end_index = input.charpos-1
1313
+ charpos = charpos(input)
1314
+ start_index = charpos - input.matched.size
1315
+ end_index = charpos-1
1255
1316
 
1256
1317
  location = RBS::Location.new(buffer: buffer,
1257
1318
  start_pos: start_index,