rbs 0.7.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: 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