rbs 0.7.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: d175f17e9f1226e0cb0d37c2167b3b52b0e736661d1406937922194c68adfd54
4
- data.tar.gz: 204d38937da751f3ea15dfd64370e379689e54f264b63be54e6c4843c4827579
3
+ metadata.gz: fe2c03d38ca9869e7c7bdf283f56e61e5ccbad3831b524ba14c6fd31941985e2
4
+ data.tar.gz: d9cc6563f7eb3173410209daeda05a8216d2ade261a3f05d3f258d0782a08e64
5
5
  SHA512:
6
- metadata.gz: 242ffa432db2a94a59636be87e261411c0bf465ac170b6f5b52955cb671d2c70e6eaed7dc74b489868117fcaa360df33c16ed6e2e472edd96663491c1211d793
7
- data.tar.gz: 6ccb639e3a73a7e4794f906e9e125dd173d0406198a11511592e3c3492126c31a5ff1798010087fb19d4eb053ba46140e42f869b913ae3b7aaee20303ef3f92c
6
+ metadata.gz: fb4391906260a8414e2c2ef44ded8fda974c495830fb6c2335204052cba67260f1f0d0fd44dd560c3c05b7cdcaffa20ee24d7d16a529c37f900689bb084ce198
7
+ data.tar.gz: 68cb88ea29edbce815a6887b716f20c640b651628b55b9b3e660e6bc93c218081464888632f9df7bc42da49700c253bc74fb9d01970f7bf13a2425742890431e
@@ -2,6 +2,40 @@
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
+
14
+ ## 0.10.0 (2020-08-10)
15
+
16
+ * Signature update for `Zlib`
17
+ * Make "no type checker installed" message a debug print [#363](https://github.com/ruby/rbs/pull/363)
18
+ * Print `...` for overloading method definitions [#362](https://github.com/ruby/rbs/pull/362)
19
+ * Allow missing method implementation in Ruby code [#359](https://github.com/ruby/rbs/pull/359)
20
+ * Runtime testing improvements [#356](https://github.com/ruby/rbs/pull/356)
21
+
22
+ ## 0.9.1 (2020-08-04)
23
+
24
+ * Ensure using Module#name [#354](https://github.com/ruby/rbs/pull/354)
25
+ * Fix runtime test setup [#353](https://github.com/ruby/rbs/pull/353)
26
+
27
+ ## 0.9.0 (2020-08-03)
28
+
29
+ * Fix signature validation [#351](https://github.com/ruby/rbs/pull/351), [#352](https://github.com/ruby/rbs/pull/352)
30
+ * Parsing performance improvement [#350](https://github.com/ruby/rbs/pull/350)
31
+
32
+ ## 0.8.0 (2020-08-01)
33
+
34
+ * Signature updates for `Enumerator` and `PTY`
35
+ * Fix prototype rb/rbi error handling [#349](https://github.com/ruby/rbs/pull/349)
36
+ * Runtime test improvements [#344](https://github.com/ruby/rbs/pull/344), [#343](https://github.com/ruby/rbs/pull/343)
37
+ * Add `...` syntax [#342](https://github.com/ruby/rbs/pull/342)
38
+
5
39
  ## 0.7.0 (2020-07-20)
6
40
 
7
41
  * Add `DefinitionBuilder#one_instance_ancestors` and `DefinitionBuilder#one_singleton_ancestors` [#341](https://github.com/ruby/rbs/pull/341)
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
+ ```
@@ -22,6 +22,12 @@ module RBS
22
22
  def to_json(*a)
23
23
  { string: string, location: location }.to_json(*a)
24
24
  end
25
+
26
+ def concat(string:, location:)
27
+ @string.concat string
28
+ @location.concat location
29
+ self
30
+ end
25
31
  end
26
32
  end
27
33
  end
@@ -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|
@@ -66,6 +67,10 @@ module RBS
66
67
  opts
67
68
  end
68
69
 
70
+ def has_parser?
71
+ defined?(RubyVM::AbstractSyntaxTree)
72
+ end
73
+
69
74
  def run(args)
70
75
  options = LibraryOptions.new
71
76
 
@@ -409,6 +414,7 @@ EOU
409
414
  env.constant_decls.each do |name, const|
410
415
  stdout.puts "Validating constant: `#{name}`..."
411
416
  validator.validate_type const.decl.type, context: const.context
417
+ builder.ensure_namespace!(name.namespace, location: const.decl.location)
412
418
  end
413
419
 
414
420
  env.global_decls.each do |name, global|
@@ -418,7 +424,9 @@ EOU
418
424
 
419
425
  env.alias_decls.each do |name, decl|
420
426
  stdout.puts "Validating alias: `#{name}`..."
421
- validator.validate_type decl.decl.type, context: decl.context
427
+ builder.expand_alias(name).tap do |type|
428
+ validator.validate_type type, context: [Namespace.root]
429
+ end
422
430
  end
423
431
  end
424
432
 
@@ -599,12 +607,18 @@ EOU
599
607
  end
600
608
 
601
609
  def run_prototype_file(format, args)
610
+ availability = unless has_parser?
611
+ "\n** This command does not work on this interpreter (#{RUBY_ENGINE}) **\n"
612
+ end
613
+
602
614
  opts = OptionParser.new
603
615
  opts.banner = <<EOU
604
616
  Usage: rbs prototype #{format} [options...] [files...]
605
-
617
+ #{availability}
606
618
  Generate RBS prototype from source code.
607
- It parses specified Ruby code and and generates RBS prototypes.
619
+ It parses specified Ruby code and and generates RBS prototypes.
620
+
621
+ It only works on MRI because it parses Ruby code with `RubyVM::AbstractSyntaxTree`.
608
622
 
609
623
  Examples:
610
624
 
@@ -613,6 +627,11 @@ Examples:
613
627
  EOU
614
628
  opts.parse!(args)
615
629
 
630
+ unless has_parser?
631
+ stdout.puts "Not supported on this interpreter (#{RUBY_ENGINE})."
632
+ exit 1
633
+ end
634
+
616
635
  if args.empty?
617
636
  stdout.puts opts
618
637
  return nil
@@ -732,5 +751,65 @@ Examples:
732
751
  TypeName.new(name: last, namespace: namespace.parent)
733
752
  end
734
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
735
814
  end
736
815
  end
@@ -45,16 +45,27 @@ 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
51
60
  attr_reader :defs
52
61
  attr_reader :accessibility
62
+ attr_reader :extra_annotations
53
63
 
54
- def initialize(super_method:, defs:, accessibility:)
64
+ def initialize(super_method:, defs:, accessibility:, annotations: [])
55
65
  @super_method = super_method
56
66
  @defs = defs
57
67
  @accessibility = accessibility
68
+ @extra_annotations = annotations
58
69
  end
59
70
 
60
71
  def defined_in
@@ -74,12 +85,11 @@ module RBS
74
85
  end
75
86
 
76
87
  def annotations
77
- @annotations ||= defs.flat_map(&:annotations)
88
+ @annotations ||= @extra_annotations + defs.flat_map(&:annotations)
78
89
  end
79
90
 
80
- # @deprecated
81
- def attributes
82
- []
91
+ def members
92
+ @members ||= defs.map(&:member).uniq
83
93
  end
84
94
 
85
95
  def public?
@@ -385,9 +385,18 @@ module RBS
385
385
  end
386
386
  end
387
387
 
388
+ def ensure_namespace!(namespace, location:)
389
+ namespace.ascend do |ns|
390
+ unless ns.empty?
391
+ NoTypeFoundError.check!(ns.to_type_name, env: env, location: location)
392
+ end
393
+ end
394
+ end
395
+
388
396
  def build_instance(type_name)
389
397
  try_cache type_name, cache: instance_cache do
390
398
  entry = env.class_decls[type_name] or raise "Unknown name for build_instance: #{type_name}"
399
+ ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location)
391
400
 
392
401
  case entry
393
402
  when Environment::ClassEntry, Environment::ModuleEntry
@@ -434,6 +443,7 @@ module RBS
434
443
  def build_singleton(type_name)
435
444
  try_cache type_name, cache: singleton_cache do
436
445
  entry = env.class_decls[type_name] or raise "Unknown name for build_singleton: #{type_name}"
446
+ ensure_namespace!(type_name.namespace, location: entry.decls[0].decl.location)
437
447
 
438
448
  case entry
439
449
  when Environment::ClassEntry, Environment::ModuleEntry
@@ -559,7 +569,7 @@ module RBS
559
569
  member, visibility = array[0]
560
570
  result[method_name] = [visibility, nil, member]
561
571
 
562
- when array.count {|pair| !pair[0].overload? } == 1
572
+ else
563
573
  visibilities = array.group_by {|pair| pair[1] }
564
574
 
565
575
  if visibilities.size > 1
@@ -573,14 +583,6 @@ module RBS
573
583
 
574
584
  overloads, primary = array.map(&:first).partition(&:overload?)
575
585
  result[method_name] = [array[0][1], nil, *primary, *overloads]
576
-
577
- else
578
- raise InvalidOverloadMethodError.new(
579
- type_name: type_name,
580
- method_name: method_name,
581
- kind: :instance,
582
- members: array.map(&:first)
583
- )
584
586
  end
585
587
  end
586
588
  end
@@ -924,7 +926,8 @@ module RBS
924
926
  implemented_in: nil
925
927
  )
926
928
  end,
927
- accessibility: :public
929
+ accessibility: :public,
930
+ annotations: [AST::Annotation.new(location: nil, string: "rbs:test:target")]
928
931
  )
929
932
  end
930
933
  end
@@ -962,8 +965,15 @@ module RBS
962
965
  Substitution.build([], [])
963
966
  end
964
967
 
968
+ kind = case ancestor
969
+ when Definition::Ancestor::Instance
970
+ :instance
971
+ when Definition::Ancestor::Singleton
972
+ :singleton
973
+ end
974
+
965
975
  current_definition.methods.each do |name, method|
966
- merge_method definition.methods, name, method, sub
976
+ merge_method type_name, definition.methods, name, method, sub, kind: kind
967
977
  end
968
978
 
969
979
  current_definition.instance_variables.each do |name, variable|
@@ -987,13 +997,20 @@ module RBS
987
997
  )
988
998
  end
989
999
 
990
- def merge_method(methods, name, method, sub)
1000
+ def merge_method(type_name, methods, name, method, sub, kind:)
991
1001
  super_method = methods[name]
992
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
+
993
1010
  methods[name] = Definition::Method.new(
994
1011
  super_method: super_method,
995
1012
  accessibility: method.accessibility,
996
- 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)) }
997
1014
  )
998
1015
  end
999
1016
 
@@ -1020,6 +1037,7 @@ module RBS
1020
1037
  try_cache(type_name, cache: interface_cache) do
1021
1038
  entry = env.interface_decls[type_name] or raise "Unknown name for build_interface: #{type_name}"
1022
1039
  declaration = entry.decl
1040
+ ensure_namespace!(type_name.namespace, location: declaration.location)
1023
1041
 
1024
1042
  self_type = Types::Interface.new(
1025
1043
  name: type_name,
@@ -1111,6 +1129,7 @@ module RBS
1111
1129
 
1112
1130
  def expand_alias(type_name)
1113
1131
  entry = env.alias_decls[type_name] or raise "Unknown name for expand_alias: #{type_name}"
1132
+ ensure_namespace!(type_name.namespace, location: entry.decl.location)
1114
1133
  entry.decl.type
1115
1134
  end
1116
1135
  end