rbs 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 29535fcd236ba4d658d2c975b5084aa58b125203c4aaa1ec4704881b92ed89c7
4
- data.tar.gz: 71e165ea5cb1ccbf1b48e9683201f6058dc7c95c7a7619865bf26af2cb6485ad
3
+ metadata.gz: fe2c03d38ca9869e7c7bdf283f56e61e5ccbad3831b524ba14c6fd31941985e2
4
+ data.tar.gz: d9cc6563f7eb3173410209daeda05a8216d2ade261a3f05d3f258d0782a08e64
5
5
  SHA512:
6
- metadata.gz: 236e10d6a7372a1c9b3c07a343a4620048c3f269f750e74f82539fd819f690475deb52090eec0cf38bc338344d240586f44941339bea7759066f68f90c5a3bdb
7
- data.tar.gz: 8ef6ef34e9b39c310f70138135589611c31c8840fdea06eaa606b5004fc5d6634882ddd169b030dd4140645ad9d18c7a4a796a8bba88cd917ea1a69b461efdd1
6
+ metadata.gz: fb4391906260a8414e2c2ef44ded8fda974c495830fb6c2335204052cba67260f1f0d0fd44dd560c3c05b7cdcaffa20ee24d7d16a529c37f900689bb084ce198
7
+ data.tar.gz: 68cb88ea29edbce815a6887b716f20c640b651628b55b9b3e660e6bc93c218081464888632f9df7bc42da49700c253bc74fb9d01970f7bf13a2425742890431e
@@ -2,6 +2,15 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.11.0 (2020-08-31)
6
+
7
+ * Signature update for `date/datetime` [#367](https://github.com/ruby/rbs/pull/367)
8
+ * Add test double support for runtime type checker [#380](https://github.com/ruby/rbs/pull/380)
9
+ * Add `rbs test` command for runtime type checking [#366](https://github.com/ruby/rbs/pull/366)
10
+ * Fix runtime type checking for record types [#365](https://github.com/ruby/rbs/pull/365)
11
+ * Improve EnvironmentLoader API [#370](https://github.com/ruby/rbs/pull/370)
12
+ * Allow overloading from super methods [#364](https://github.com/ruby/rbs/pull/364)
13
+
5
14
  ## 0.10.0 (2020-08-10)
6
15
 
7
16
  * Signature update for `Zlib`
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gemspec
6
6
  # Development dependencies
7
7
  gem "rake"
8
8
  gem "minitest"
9
+ gem "rspec"
9
10
  gem "racc"
10
11
  gem "rubocop"
11
12
  gem "rubocop-rubycw"
data/README.md CHANGED
@@ -123,7 +123,7 @@ puts singleton.methods[:gsub]
123
123
 
124
124
  ## Development
125
125
 
126
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
126
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
127
127
 
128
128
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
129
129
 
@@ -212,7 +212,7 @@ _method-type_ ::= `(` _parameters_ `) ->` _type_
212
212
 
213
213
  _parameters_ ::= _required-positionals_ _optional-positionals_ _rest-positional_ _trailing-positionals_ _keywords_
214
214
 
215
- _paramater_ ::= _type_ _var-name_ # Parameter with var name
215
+ _parameter_ ::= _type_ _var-name_ # Parameter with var name
216
216
  | _type_ # Parameter without var name
217
217
  _required-positionals_ ::= _parameter_ `,` ...
218
218
  _optional-positionals_ ::= `?` _parameter_ `,` ...
@@ -529,3 +529,16 @@ You can declare a global variable.
529
529
  $LOAD_PATH: Array[String]
530
530
  ```
531
531
 
532
+ ### Comments
533
+
534
+ You can write single line comments. Comments must be on their own line. Comments can lead with whitespace.
535
+
536
+ ```
537
+ # This if interface Foo
538
+ # Usage of Foo is bar
539
+ interface _Foo
540
+ # New foo is a method
541
+ # it will return foo.
542
+ def new: () -> Foo
543
+ end
544
+ ```
@@ -11,17 +11,15 @@ module RBS
11
11
  attr_reader :annotations
12
12
  attr_reader :location
13
13
  attr_reader :comment
14
- attr_reader :attributes
15
14
  attr_reader :overload
16
15
 
17
- def initialize(name:, kind:, types:, annotations:, location:, comment:, attributes:, overload:)
16
+ def initialize(name:, kind:, types:, annotations:, location:, comment:, overload:)
18
17
  @name = name
19
18
  @kind = kind
20
19
  @types = types
21
20
  @annotations = annotations
22
21
  @location = location
23
22
  @comment = comment
24
- @attributes = attributes
25
23
  @overload = overload
26
24
  end
27
25
 
@@ -30,14 +28,13 @@ module RBS
30
28
  other.name == name &&
31
29
  other.kind == kind &&
32
30
  other.types == types &&
33
- other.attributes == attributes &&
34
31
  other.overload == overload
35
32
  end
36
33
 
37
34
  alias eql? ==
38
35
 
39
36
  def hash
40
- self.class.hash ^ name.hash ^ kind.hash ^ types.hash ^ attributes.hash ^ overload.hash
37
+ self.class.hash ^ name.hash ^ kind.hash ^ types.hash ^ overload.hash
41
38
  end
42
39
 
43
40
  def instance?
@@ -52,7 +49,7 @@ module RBS
52
49
  overload
53
50
  end
54
51
 
55
- def update(name: self.name, kind: self.kind, types: self.types, annotations: self.annotations, location: self.location, comment: self.comment, attributes: self.attributes, overload: self.overload)
52
+ def update(name: self.name, kind: self.kind, types: self.types, annotations: self.annotations, location: self.location, comment: self.comment, overload: self.overload)
56
53
  self.class.new(
57
54
  name: name,
58
55
  kind: kind,
@@ -60,7 +57,6 @@ module RBS
60
57
  annotations: annotations,
61
58
  location: location,
62
59
  comment: comment,
63
- attributes: attributes,
64
60
  overload: overload
65
61
  )
66
62
  end
@@ -73,7 +69,6 @@ module RBS
73
69
  annotations: annotations,
74
70
  location: location,
75
71
  comment: comment,
76
- attributes: attributes,
77
72
  overload: overload
78
73
  }.to_json(*a)
79
74
  end
@@ -1,4 +1,5 @@
1
1
  require "optparse"
2
+ require "shellwords"
2
3
 
3
4
  module RBS
4
5
  class CLI
@@ -36,7 +37,7 @@ module RBS
36
37
  @stderr = stderr
37
38
  end
38
39
 
39
- COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse]
40
+ COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test]
40
41
 
41
42
  def library_parse(opts, options:)
42
43
  opts.on("-r LIBRARY", "Load RBS files of the library") do |lib|
@@ -750,5 +751,65 @@ Examples:
750
751
  TypeName.new(name: last, namespace: namespace.parent)
751
752
  end
752
753
  end
754
+
755
+ def test_opt options
756
+ opt_string = options.dirs.map { |dir| "-I #{Shellwords.escape(dir)}"}.concat(options.libs.map { |lib| "-r#{Shellwords.escape(lib)}"}).join(' ')
757
+ opt_string.empty? ? nil : opt_string
758
+ end
759
+
760
+ def run_test(args, options)
761
+ unchecked_classes = []
762
+ targets = []
763
+ sample_size = nil
764
+ double_suite = nil
765
+
766
+ (opts = OptionParser.new do |opts|
767
+ opts.banner = <<EOB
768
+ Usage: rbs [rbs options...] test [test options...] COMMAND
769
+
770
+ Examples:
771
+
772
+ $ rbs test rake test
773
+ $ rbs --log-level=debug test --target SomeModule::* rspec
774
+ $ rbs test --target SomeModule::* --target AnotherModule::* --target SomeClass rake test
775
+
776
+ Options:
777
+ EOB
778
+ opts.on("--target TARGET", "Sets the runtime test target") do |target|
779
+ targets << target
780
+ end
781
+
782
+ opts.on("--sample-size SAMPLE_SIZE", "Sets the sample size") do |size|
783
+ sample_size = size
784
+ end
785
+
786
+ opts.on("--unchecked-class UNCHECKED_CLASS", "Sets the class that would not be checked") do |unchecked_class|
787
+ unchecked_classes << unchecked_class
788
+ end
789
+
790
+ opts.on("--double-suite DOUBLE_SUITE", "Sets the double suite in use (currently supported: rspec | minitest)") do |suite|
791
+ double_suite = suite
792
+ end
793
+
794
+ end).order!(args)
795
+
796
+ if args.length.zero?
797
+ stdout.puts opts.help
798
+ exit 1
799
+ end
800
+
801
+ env_hash = {
802
+ 'RUBYOPT' => "#{ENV['RUBYOPT']} -rrbs/test/setup",
803
+ 'RBS_TEST_OPT' => test_opt(options),
804
+ 'RBS_TEST_LOGLEVEL' => RBS.logger_level,
805
+ 'RBS_TEST_SAMPLE_SIZE' => sample_size,
806
+ 'RBS_TEST_DOUBLE_SUITE' => double_suite,
807
+ 'RBS_TEST_UNCHECKED_CLASSES' => (unchecked_classes.join(',') unless unchecked_classes.empty?),
808
+ 'RBS_TEST_TARGET' => (targets.join(',') unless targets.empty?)
809
+ }
810
+
811
+ system(env_hash, *args)
812
+ $?
813
+ end
753
814
  end
754
815
  end
@@ -45,6 +45,15 @@ module RBS
45
45
  def update(type: self.type, member: self.member, defined_in: self.defined_in, implemented_in: self.implemented_in)
46
46
  TypeDef.new(type: type, member: member, defined_in: defined_in, implemented_in: implemented_in)
47
47
  end
48
+
49
+ def overload?
50
+ case member
51
+ when AST::Members::MethodDefinition
52
+ member.overload?
53
+ else
54
+ false
55
+ end
56
+ end
48
57
  end
49
58
 
50
59
  attr_reader :super_method
@@ -79,9 +88,8 @@ module RBS
79
88
  @annotations ||= @extra_annotations + defs.flat_map(&:annotations)
80
89
  end
81
90
 
82
- # @deprecated
83
- def attributes
84
- []
91
+ def members
92
+ @members ||= defs.map(&:member).uniq
85
93
  end
86
94
 
87
95
  def public?
@@ -569,7 +569,7 @@ module RBS
569
569
  member, visibility = array[0]
570
570
  result[method_name] = [visibility, nil, member]
571
571
 
572
- when array.count {|pair| !pair[0].overload? } == 1
572
+ else
573
573
  visibilities = array.group_by {|pair| pair[1] }
574
574
 
575
575
  if visibilities.size > 1
@@ -583,14 +583,6 @@ module RBS
583
583
 
584
584
  overloads, primary = array.map(&:first).partition(&:overload?)
585
585
  result[method_name] = [array[0][1], nil, *primary, *overloads]
586
-
587
- else
588
- raise InvalidOverloadMethodError.new(
589
- type_name: type_name,
590
- method_name: method_name,
591
- kind: :instance,
592
- members: array.map(&:first)
593
- )
594
586
  end
595
587
  end
596
588
  end
@@ -973,8 +965,15 @@ module RBS
973
965
  Substitution.build([], [])
974
966
  end
975
967
 
968
+ kind = case ancestor
969
+ when Definition::Ancestor::Instance
970
+ :instance
971
+ when Definition::Ancestor::Singleton
972
+ :singleton
973
+ end
974
+
976
975
  current_definition.methods.each do |name, method|
977
- merge_method definition.methods, name, method, sub
976
+ merge_method type_name, definition.methods, name, method, sub, kind: kind
978
977
  end
979
978
 
980
979
  current_definition.instance_variables.each do |name, variable|
@@ -998,13 +997,20 @@ module RBS
998
997
  )
999
998
  end
1000
999
 
1001
- def merge_method(methods, name, method, sub)
1000
+ def merge_method(type_name, methods, name, method, sub, kind:)
1002
1001
  super_method = methods[name]
1003
1002
 
1003
+ defs = if method.defs.all? {|d| d.overload? }
1004
+ raise InvalidOverloadMethodError.new(type_name: type_name, method_name: name, kind: kind, members: method.members) unless super_method
1005
+ method.defs + super_method.defs
1006
+ else
1007
+ method.defs
1008
+ end
1009
+
1004
1010
  methods[name] = Definition::Method.new(
1005
1011
  super_method: super_method,
1006
1012
  accessibility: method.accessibility,
1007
- defs: sub.mapping.empty? ? method.defs : method.defs.map {|defn| defn.update(type: defn.type.sub(sub)) }
1013
+ defs: sub.mapping.empty? ? defs : defs.map {|defn| defn.update(type: defn.type.sub(sub)) }
1008
1014
  )
1009
1015
  end
1010
1016
 
@@ -325,7 +325,6 @@ module RBS
325
325
  comment: member.comment,
326
326
  overload: member.overload?,
327
327
  annotations: member.annotations,
328
- attributes: member.attributes,
329
328
  location: member.location
330
329
  )
331
330
  when AST::Members::AttrAccessor
@@ -75,29 +75,16 @@ module RBS
75
75
  self.class.gem_sig_path(name, version)
76
76
  end
77
77
 
78
- def each_signature(path = nil, immediate: true, &block)
78
+ def each_signature(path, immediate: true, &block)
79
79
  if block_given?
80
- if path
81
- case
82
- when path.file?
83
- if path.extname == ".rbs" || immediate
84
- yield path
85
- end
86
- when path.directory?
87
- path.children.each do |child|
88
- each_signature child, immediate: false, &block
89
- end
80
+ case
81
+ when path.file?
82
+ if path.extname == ".rbs" || immediate
83
+ yield path
90
84
  end
91
- else
92
- paths.each do |path|
93
- case path
94
- when Pathname
95
- each_signature path, immediate: immediate, &block
96
- when LibraryPath
97
- each_signature path.path, immediate: immediate, &block
98
- when GemPath
99
- each_signature path.path, immediate: immediate, &block
100
- end
85
+ when path.directory?
86
+ path.children.each do |child|
87
+ each_signature child, immediate: false, &block
101
88
  end
102
89
  end
103
90
  else
@@ -105,32 +92,65 @@ module RBS
105
92
  end
106
93
  end
107
94
 
108
- def no_builtin!
109
- @no_builtin = true
95
+ def each_library_path
96
+ paths.each do |path|
97
+ case path
98
+ when Pathname
99
+ yield path, path
100
+ when LibraryPath
101
+ yield path, path.path
102
+ when GemPath
103
+ yield path, path.path
104
+ end
105
+ end
106
+ end
107
+
108
+ def no_builtin!(skip = true)
109
+ @no_builtin = skip
110
+ self
110
111
  end
111
112
 
112
113
  def no_builtin?
113
114
  @no_builtin
114
115
  end
115
116
 
116
- def load(env:)
117
- signature_files = []
117
+ def each_decl
118
+ if block_given?
119
+ signature_files = []
118
120
 
119
- unless no_builtin?
120
- signature_files.push(*each_signature(stdlib_root + "builtin"))
121
- end
121
+ unless no_builtin?
122
+ each_signature(stdlib_root + "builtin") do |path|
123
+ signature_files << [:stdlib, path]
124
+ end
125
+ end
122
126
 
123
- each_signature do |path|
124
- signature_files.push path
127
+ each_library_path do |library_path, pathname|
128
+ each_signature(pathname) do |path|
129
+ signature_files << [library_path, path]
130
+ end
131
+ end
132
+
133
+ signature_files.each do |lib_path, file_path|
134
+ buffer = Buffer.new(name: file_path.to_s, content: file_path.read)
135
+ Parser.parse_signature(buffer).each do |decl|
136
+ yield decl, buffer, file_path, lib_path
137
+ end
138
+ end
139
+ else
140
+ enum_for :each_decl
125
141
  end
142
+ end
143
+
144
+ def load(env:)
145
+ loadeds = []
126
146
 
127
- signature_files.each do |file|
128
- buffer = Buffer.new(name: file.to_s, content: file.read)
147
+ each_decl do |decl, buffer, file_path, lib_path|
129
148
  env.buffers.push(buffer)
130
- Parser.parse_signature(buffer).each do |decl|
131
- env << decl
132
- end
149
+ env << decl
150
+ loadeds << [decl, file_path, lib_path]
133
151
  end
152
+
153
+ loadeds
134
154
  end
135
155
  end
136
156
  end
@@ -458,16 +458,14 @@ rule
458
458
  types: val[6],
459
459
  annotations: val[0],
460
460
  location: location,
461
- comment: leading_comment(val[0].first&.location || val[1].first&.location || val[2]&.location || val[3].location),
462
- attributes: val[1].map(&:value),
461
+ comment: leading_comment(val[0].first&.location || val[2]&.location || val[3].location),
463
462
  overload: overload || !!val[2]
464
463
  )
465
464
  }
466
465
 
467
466
  attributes:
468
- { result = [] }
469
467
  | attributes kINCOMPATIBLE {
470
- result = val[0].push(val[1])
468
+ RBS.logger.warn "`incompatible` method attribute is deprecated and ignored."
471
469
  }
472
470
 
473
471
  method_kind: