rbs 0.10.0 → 0.11.0

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: 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: