rbs 3.0.3 → 3.1.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: 7a5d2a9cd76c2802e303f61813f418c15a2fc131b23f1eb8e90a92f409efcf37
4
- data.tar.gz: d008724c5628a0c21b153a6ae99dadf7604ee90ad4caa210e07bbad974f91894
3
+ metadata.gz: ae81eb182ddb9f708925c47a5c98adcf0535ec1ddd7ff06127ba2602f076daf9
4
+ data.tar.gz: f791c1e0d14b1407ec6ae8ecb0deec2f9c5069852b67d716243a9262b4d49831
5
5
  SHA512:
6
- metadata.gz: 4c903cc9f9b536281e0632aff0cae6d520856152bdf33b1d8fc34b2dd8e5caab93af6aaa1387eb7433b430d2d90dafcd5557c7aeba0b043d6ab340bc22d36dcb
7
- data.tar.gz: 1913b79a1bb5b6510734aaca4aee8fa1759dae851486662ee5055040b8d70554b9466d061cc53c971ade8d76d75312486fe39cea5b1f4c7d3bfa333501fb56da
6
+ metadata.gz: 11b754b36d8a1c903538638774e1b51fa6abb08370ae1009d0c0c389a12b72cd222b2706e543dc89bf66f889b0eb60598a32473ee7cf52517410161259c098c8
7
+ data.tar.gz: 4f3694a3bec4492b4b885cf22d1ecf2c8e3408fc55609db45081de6865d2925ec31c7bccfb05258198b390c34f3348fe0ffc33f8f47b82cfba44f1fb3d393b43
data/CHANGELOG.md CHANGED
@@ -2,6 +2,49 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 3.1.0 (2023-04-26)
6
+
7
+ ### Signature updates
8
+
9
+ * `Module#attr_*` methods ([#1300](https://github.com/ruby/rbs/pull/1300))
10
+ * `Object#define_singleton_method` ([#1299](https://github.com/ruby/rbs/pull/1299))
11
+ * `String#scan` ([#1297](https://github.com/ruby/rbs/pull/1297))
12
+ * Removed `Gem.datadir` ([#1273](https://github.com/ruby/rbs/pull/1273))
13
+
14
+ ### Language updates
15
+
16
+ ### Library changes
17
+
18
+ * Use fenced code block instead of indented one in .rbs files ([#1312](https://github.com/ruby/rbs/pull/1312))
19
+ * Fix single use clause `:type_name` location ([#1307](https://github.com/ruby/rbs/pull/1307))
20
+ * Fix `InvalidOverloadMethodError` on overloading extended method ([#1294](https://github.com/ruby/rbs/pull/1294))
21
+ * Fix super class of `NoTypeFoundError` from `BaseError` to `DefinitionError` ([#1290](https://github.com/ruby/rbs/pull/1290))
22
+ * Support `#detailed_message` for `NonregularTypeAliasError`, `CyclicTypeParameterBound`, `InconsistentClassModuleAliasError` and `CyclicClassAliasDefinitionError` ([#1289](https://github.com/ruby/rbs/pull/1289))
23
+ * Implement `rbs subtract` command ([#1287](https://github.com/ruby/rbs/pull/1287))
24
+ * Support `#detailed_message` for `InvalidVarianceAnnotationError`, `RecursiveAliasDefinitionError`, `MixinClassError` and `RecursiveTypeAliasError` ([#1285](https://github.com/ruby/rbs/pull/1285))
25
+ * Support `#detailed_message` for `NoTypeError`, `InheritModuleError`, `NoSelfTypeFoundError` and `NoMixinFoundError` ([#1280](https://github.com/ruby/rbs/pull/1280))
26
+ * Validate duplicate type aliases ([#1279](https://github.com/ruby/rbs/pull/1279))
27
+ * Add `-e`, `--type`, and `--method-type` options to `rbs parse` ([#1252](https://github.com/ruby/rbs/pull/1252))
28
+
29
+ #### rbs prototype
30
+
31
+ * Convert `include` in `class << self` to `extend` by `prototype rb` ([#1255](https://github.com/ruby/rbs/pull/1255))
32
+
33
+ #### rbs collection
34
+
35
+ * Skip loading `#gemspec` gems via RBS collection ([#1319](https://github.com/ruby/rbs/pull/1319))
36
+
37
+ ### Miscellaneous
38
+
39
+ * Run `bundle install` automatically in `bin/steep` ([#1308](https://github.com/ruby/rbs/pull/1308))
40
+ * Fix warnings ([#1314](https://github.com/ruby/rbs/pull/1314))
41
+
42
+ ## 3.0.4 (2023-03-13)
43
+
44
+ ### Library changes
45
+
46
+ * Add missing implementation to support class/module alias ([#1271](https://github.com/ruby/rbs/pull/1271))
47
+
5
48
  ## 3.0.3 (2023-03-07)
6
49
 
7
50
  ### Library changes
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbs (3.0.3)
4
+ rbs (3.1.0)
5
5
 
6
6
  PATH
7
7
  remote: test/assets/test-gem
@@ -11,8 +11,8 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- addressable (2.8.0)
15
- public_suffix (>= 2.0.2, < 5.0)
14
+ addressable (2.8.4)
15
+ public_suffix (>= 2.0.2, < 6.0)
16
16
  ast (2.4.2)
17
17
  dbm (1.1.0)
18
18
  debase (0.2.5.beta2)
@@ -27,12 +27,12 @@ GEM
27
27
  rainbow (>= 3.0, < 4.0)
28
28
  strong_json (>= 1.1, < 2.2)
29
29
  json (2.6.3)
30
- json-schema (3.0.0)
30
+ json-schema (4.0.0)
31
31
  addressable (>= 2.8)
32
32
  marcel (1.0.2)
33
- minitest (5.17.0)
33
+ minitest (5.18.0)
34
34
  parallel (1.22.1)
35
- parser (3.2.1.0)
35
+ parser (3.2.2.0)
36
36
  ast (~> 2.4.1)
37
37
  power_assert (2.0.2)
38
38
  prime (0.1.2)
@@ -40,14 +40,14 @@ GEM
40
40
  singleton
41
41
  psych (4.0.6)
42
42
  stringio
43
- public_suffix (4.0.7)
43
+ public_suffix (5.0.1)
44
44
  rainbow (3.1.1)
45
45
  rake (13.0.6)
46
46
  rake-compiler (1.2.1)
47
47
  rake
48
48
  rdoc (6.4.0)
49
49
  psych (>= 4.0.0)
50
- regexp_parser (2.7.0)
50
+ regexp_parser (2.8.0)
51
51
  rexml (3.2.5)
52
52
  rspec (3.12.0)
53
53
  rspec-core (~> 3.12.0)
@@ -62,25 +62,25 @@ GEM
62
62
  diff-lcs (>= 1.2.0, < 2.0)
63
63
  rspec-support (~> 3.12.0)
64
64
  rspec-support (3.12.0)
65
- rubocop (1.45.1)
65
+ rubocop (1.50.2)
66
66
  json (~> 2.3)
67
67
  parallel (~> 1.10)
68
68
  parser (>= 3.2.0.0)
69
69
  rainbow (>= 2.2.2, < 4.0)
70
70
  regexp_parser (>= 1.8, < 3.0)
71
71
  rexml (>= 3.2.5, < 4.0)
72
- rubocop-ast (>= 1.24.1, < 2.0)
72
+ rubocop-ast (>= 1.28.0, < 2.0)
73
73
  ruby-progressbar (~> 1.7)
74
74
  unicode-display_width (>= 2.4.0, < 3.0)
75
- rubocop-ast (1.26.0)
75
+ rubocop-ast (1.28.0)
76
76
  parser (>= 3.2.1.0)
77
77
  rubocop-rubycw (0.1.6)
78
78
  rubocop (~> 1.0)
79
79
  ruby-debug-ide (0.7.3)
80
80
  rake (>= 0.8.1)
81
- ruby-progressbar (1.11.0)
81
+ ruby-progressbar (1.13.0)
82
82
  singleton (0.1.1)
83
- stackprof (0.2.23)
83
+ stackprof (0.2.25)
84
84
  stringio (3.0.4)
85
85
  strong_json (2.1.2)
86
86
  tempfile (0.1.3)
data/Steepfile CHANGED
@@ -9,7 +9,7 @@ target :lib do
9
9
  "lib/rbs/test.rb"
10
10
  )
11
11
 
12
- library "set", "pathname", "json", "logger", "monitor", "tsort", "uri", 'dbm', 'pstore', 'singleton', 'shellwords', 'fileutils', 'find', 'digest'
12
+ library "set", "pathname", "json", "logger", "monitor", "tsort", "uri", 'dbm', 'pstore', 'singleton', 'shellwords', 'fileutils', 'find', 'digest', 'abbrev'
13
13
  signature 'stdlib/yaml/0'
14
14
  signature "stdlib/strscan/0/"
15
15
  signature "stdlib/optparse/0/"
data/core/io/buffer.rbs CHANGED
@@ -541,13 +541,11 @@ class IO
541
541
 
542
542
  # <!--
543
543
  # rdoc-file=io_buffer.c
544
- # - read(io, [length, [offset]]) -> read length or -errno
544
+ # - read(io, length, [offset]) -> read length or -errno
545
545
  # -->
546
546
  # Read at most `length` bytes from `io` into the buffer, starting at `offset`.
547
547
  # If an error occurs, return `-errno`.
548
548
  #
549
- # If `length` is not given, read until the end of the buffer.
550
- #
551
549
  # If `offset` is not given, read from the beginning of the buffer.
552
550
  #
553
551
  # If `length` is 0, read nothing.
data/core/module.rbs CHANGED
@@ -284,7 +284,7 @@ class Module < Object
284
284
  # end
285
285
  # Mod.instance_methods.sort #=> [:one, :one=, :two, :two=]
286
286
  #
287
- def attr_accessor: (*Symbol | String arg0) -> Array[Symbol]
287
+ def attr_accessor: (*Object::name arg0) -> Array[Symbol]
288
288
 
289
289
  # <!--
290
290
  # rdoc-file=object.c
@@ -298,7 +298,7 @@ class Module < Object
298
298
  # in turn. String arguments are converted to symbols. Returns an array of
299
299
  # defined method names as symbols.
300
300
  #
301
- def attr_reader: (*Symbol | String arg0) -> Array[Symbol]
301
+ def attr_reader: (*Object::name arg0) -> Array[Symbol]
302
302
 
303
303
  # <!--
304
304
  # rdoc-file=object.c
@@ -309,7 +309,7 @@ class Module < Object
309
309
  # *symbol*`.id2name`. String arguments are converted to symbols. Returns an
310
310
  # array of defined method names as symbols.
311
311
  #
312
- def attr_writer: (*Symbol | String arg0) -> Array[Symbol]
312
+ def attr_writer: (*Object::name arg0) -> Array[Symbol]
313
313
 
314
314
  # <!--
315
315
  # rdoc-file=load.c
@@ -1629,5 +1629,5 @@ class Module < Object
1629
1629
  # `attr_reader(name)` but deprecated. Returns an array of defined method names
1630
1630
  # as symbols.
1631
1631
  #
1632
- def attr: (*Symbol | String arg0) -> Array[Symbol]
1632
+ def attr: (*Object::name arg0) -> Array[Symbol]
1633
1633
  end
data/core/object.rbs CHANGED
@@ -205,8 +205,8 @@ class Object < BasicObject
205
205
  # chris.define_singleton_method(:greet) {|greeting| "#{greeting}, I'm Chris!" }
206
206
  # chris.greet("Hi") #=> "Hi, I'm Chris!"
207
207
  #
208
- def define_singleton_method: (Symbol, Method | UnboundMethod) -> Symbol
209
- | (Symbol) { (*untyped) -> untyped } -> Symbol
208
+ def define_singleton_method: (name, Method | UnboundMethod) -> Symbol
209
+ | (name) { (*untyped) -> untyped } -> Symbol
210
210
 
211
211
  # <!--
212
212
  # rdoc-file=io.c
@@ -261,15 +261,6 @@ module Gem
261
261
  #
262
262
  def self.data_home: () -> String
263
263
 
264
- # <!--
265
- # rdoc-file=lib/rubygems.rb
266
- # - datadir(gem_name)
267
- # -->
268
- # The path to the data directory specified by the gem name. If the package is
269
- # not available as a gem, return nil.
270
- #
271
- def self.datadir: (String gem_name) -> String?
272
-
273
264
  # <!--
274
265
  # rdoc-file=lib/rubygems/defaults.rb
275
266
  # - default_bindir()
data/core/string.rbs CHANGED
@@ -2600,8 +2600,10 @@ class String
2600
2600
  # <<cruel>> <<world>>
2601
2601
  # rceu lowlr
2602
2602
  #
2603
- def scan: (Regexp | string pattern) -> Array[String | Array[String]]
2604
- | (Regexp | string pattern) { (String | Array[String]) -> void } -> self
2603
+ def scan: (Regexp pattern) -> Array[String | Array[String]]
2604
+ | (Regexp pattern) { (String | Array[String]) -> void } -> self
2605
+ | (string pattern) -> Array[String]
2606
+ | (string pattern) { (String) -> void } -> self
2605
2607
 
2606
2608
  # <!--
2607
2609
  # rdoc-file=string.c
@@ -2649,13 +2649,9 @@ void parse_use_clauses(parserstate *state, VALUE clauses) {
2649
2649
 
2650
2650
  VALUE location = rbs_new_location(state->buffer, clause_range);
2651
2651
  rbs_loc *loc = rbs_check_location(location);
2652
- rbs_loc_add_required_child(loc, rb_intern("type_name"), state->current_token.range);
2653
- if (!null_range_p(keyword_range)) {
2654
- rbs_loc_add_optional_child(loc, rb_intern("keyword"), keyword_range);
2655
- }
2656
- if (!null_range_p(new_name_range)) {
2657
- rbs_loc_add_optional_child(loc, rb_intern("new_name"), new_name_range);
2658
- }
2652
+ rbs_loc_add_required_child(loc, rb_intern("type_name"), type_name_range);
2653
+ rbs_loc_add_optional_child(loc, rb_intern("keyword"), keyword_range);
2654
+ rbs_loc_add_optional_child(loc, rb_intern("new_name"), new_name_range);
2659
2655
 
2660
2656
  rb_ary_push(clauses, rbs_ast_directives_use_single_clause(type_name, new_name, location));
2661
2657
 
@@ -2739,7 +2735,7 @@ VALUE parse_signature(parserstate *state) {
2739
2735
  }
2740
2736
 
2741
2737
  static VALUE
2742
- rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables)
2738
+ rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof)
2743
2739
  {
2744
2740
  parserstate *parser = alloc_parser(buffer, FIX2INT(start_pos), FIX2INT(end_pos), variables);
2745
2741
 
@@ -2749,13 +2745,17 @@ rbsparser_parse_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, V
2749
2745
 
2750
2746
  VALUE type = parse_type(parser);
2751
2747
 
2748
+ if (RB_TEST(require_eof)) {
2749
+ parser_advance_assert(parser, pEOF);
2750
+ }
2751
+
2752
2752
  free_parser(parser);
2753
2753
 
2754
2754
  return type;
2755
2755
  }
2756
2756
 
2757
2757
  static VALUE
2758
- rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables)
2758
+ rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end_pos, VALUE variables, VALUE require_eof)
2759
2759
  {
2760
2760
  parserstate *parser = alloc_parser(buffer, FIX2INT(start_pos), FIX2INT(end_pos), variables);
2761
2761
 
@@ -2765,6 +2765,10 @@ rbsparser_parse_method_type(VALUE self, VALUE buffer, VALUE start_pos, VALUE end
2765
2765
 
2766
2766
  VALUE method_type = parse_method_type(parser);
2767
2767
 
2768
+ if (RB_TEST(require_eof)) {
2769
+ parser_advance_assert(parser, pEOF);
2770
+ }
2771
+
2768
2772
  free_parser(parser);
2769
2773
 
2770
2774
  return method_type;
@@ -2782,7 +2786,7 @@ rbsparser_parse_signature(VALUE self, VALUE buffer, VALUE end_pos)
2782
2786
 
2783
2787
  void rbs__init_parser(void) {
2784
2788
  RBS_Parser = rb_define_class_under(RBS, "Parser", rb_cObject);
2785
- rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 4);
2786
- rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 4);
2789
+ rb_define_singleton_method(RBS_Parser, "_parse_type", rbsparser_parse_type, 5);
2790
+ rb_define_singleton_method(RBS_Parser, "_parse_method_type", rbsparser_parse_method_type, 5);
2787
2791
  rb_define_singleton_method(RBS_Parser, "_parse_signature", rbsparser_parse_signature, 2);
2788
2792
  }
data/lib/rbs/cli.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require "open3"
4
4
  require "optparse"
5
5
  require "shellwords"
6
+ require "abbrev"
7
+ require "stringio"
6
8
 
7
9
  module RBS
8
10
  class CLI
@@ -88,7 +90,7 @@ module RBS
88
90
  @stderr = stderr
89
91
  end
90
92
 
91
- COMMANDS = [:ast, :annotate, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test, :collection]
93
+ COMMANDS = [:ast, :annotate, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test, :collection, :subtract]
92
94
 
93
95
  def parse_logging_options(opts)
94
96
  opts.on("--log-level LEVEL", "Specify log level (defaults to `warn`)") do |level|
@@ -230,6 +232,19 @@ EOB
230
232
  end
231
233
  end
232
234
  end
235
+
236
+ env.class_alias_decls.each do |name, entry|
237
+ case entry
238
+ when Environment::ModuleAliasEntry
239
+ if list.include?(:module)
240
+ stdout.puts "#{name} (module alias)"
241
+ end
242
+ when Environment::ClassAliasEntry
243
+ if list.include?(:class)
244
+ stdout.puts "#{name} (class alias)"
245
+ end
246
+ end
247
+ end
233
248
  end
234
249
 
235
250
  if list.include?(:interface)
@@ -272,7 +287,10 @@ EOU
272
287
  builder = DefinitionBuilder::AncestorBuilder.new(env: env)
273
288
  type_name = TypeName(args[0]).absolute!
274
289
 
275
- if env.class_decls.key?(type_name)
290
+ case env.constant_entry(type_name)
291
+ when Environment::ClassEntry, Environment::ModuleEntry, Environment::ClassAliasEntry, Environment::ModuleAliasEntry
292
+ type_name = env.normalize_module_name(type_name)
293
+
276
294
  ancestors = case kind
277
295
  when :instance
278
296
  builder.instance_ancestors(type_name)
@@ -334,7 +352,7 @@ EOU
334
352
  builder = DefinitionBuilder.new(env: env)
335
353
  type_name = TypeName(args[0]).absolute!
336
354
 
337
- if env.class_decls.key?(type_name)
355
+ if env.module_name?(type_name)
338
356
  definition = case kind
339
357
  when :instance
340
358
  builder.build_instance(type_name)
@@ -388,7 +406,7 @@ EOU
388
406
  type_name = TypeName(args[0]).absolute!
389
407
  method_name = args[1].to_sym
390
408
 
391
- unless env.class_decls.key?(type_name)
409
+ unless env.module_name?(type_name)
392
410
  stdout.puts "Cannot find class: #{type_name}"
393
411
  return
394
412
  end
@@ -434,7 +452,6 @@ Examples:
434
452
  EOU
435
453
 
436
454
  opts.on("--silent") do
437
- require "stringio"
438
455
  @stdout = StringIO.new
439
456
  end
440
457
  end.parse!(args)
@@ -904,6 +921,10 @@ Options:
904
921
  end
905
922
 
906
923
  def run_parse(args, options)
924
+ parse_method = :parse_signature
925
+ # @type var e_code: String?
926
+ e_code = nil
927
+
907
928
  OptionParser.new do |opts|
908
929
  opts.banner = <<-EOB
909
930
  Usage: rbs parse [files...]
@@ -913,22 +934,35 @@ Parse given RBS files and print syntax errors.
913
934
  Examples:
914
935
 
915
936
  $ rbs parse sig/app/models.rbs sig/app/controllers.rbs
937
+
938
+ Options:
916
939
  EOB
917
- end.parse!(args)
918
940
 
919
- loader = options.loader()
941
+ opts.on('-e CODE', 'One line RBS script to parse') { |e| e_code = e }
942
+ opts.on('--type', 'Parse code as a type') { |e| parse_method = :parse_type }
943
+ opts.on('--method-type', 'Parse code as a method type') { |e| parse_method = :parse_method_type }
944
+ end.parse!(args)
920
945
 
921
946
  syntax_error = false
922
- args.each do |path|
947
+ bufs = args.flat_map do |path|
923
948
  path = Pathname(path)
924
- loader.each_file(path, skip_hidden: false, immediate: true) do |file_path|
925
- RBS.logger.info "Parsing #{file_path}..."
926
- buffer = Buffer.new(content: file_path.read, name: file_path)
927
- Parser.parse_signature(buffer)
928
- rescue RBS::ParsingError => ex
929
- stdout.puts ex.message
930
- syntax_error = true
949
+ FileFinder.each_file(path, skip_hidden: false, immediate: true).map do |file_path|
950
+ Buffer.new(content: file_path.read, name: file_path)
951
+ end
952
+ end
953
+ bufs << Buffer.new(content: e_code, name: '-e') if e_code
954
+
955
+ bufs.each do |buf|
956
+ RBS.logger.info "Parsing #{buf.name}..."
957
+ case parse_method
958
+ when :parse_signature
959
+ Parser.parse_signature(buf)
960
+ else
961
+ Parser.public_send(parse_method, buf, require_eof: true)
931
962
  end
963
+ rescue RBS::ParsingError => ex
964
+ stdout.puts ex.message
965
+ syntax_error = true
932
966
  end
933
967
 
934
968
  exit 1 if syntax_error
@@ -1062,7 +1096,8 @@ EOB
1062
1096
  config_path = options.config_path or raise
1063
1097
  lock_path = Collection::Config.to_lockfile_path(config_path)
1064
1098
 
1065
- case args[0]
1099
+ subcommand = Abbrev.abbrev(['install', 'update', 'help'])[args[0]] || args[0]
1100
+ case subcommand
1066
1101
  when 'install'
1067
1102
  unless params[:frozen]
1068
1103
  Collection::Config.generate_lockfile(config_path: config_path, definition: Bundler.definition)
@@ -1138,5 +1173,80 @@ EOB
1138
1173
  opts.on('--frozen') if args[0] == 'install'
1139
1174
  end
1140
1175
  end
1176
+
1177
+ def run_subtract(args, _)
1178
+ write_to_file = false
1179
+ # @type var subtrahend_paths: Array[String]
1180
+ subtrahend_paths = []
1181
+
1182
+ opts = OptionParser.new do |opts|
1183
+ opts.banner = <<~HELP
1184
+ Usage:
1185
+ rbs subtract [options...] minuend.rbs [minuend2.rbs, ...] subtrahend.rbs
1186
+ rbs subtract [options...] minuend.rbs [minuend2.rbs, ...] --subtrahend subtrahend_1.rbs --subtrahend subtrahend_2.rbs
1187
+
1188
+ Remove duplications between RBS files.
1189
+
1190
+ Examples:
1191
+
1192
+ # Generate RBS files from the codebase.
1193
+ $ rbs prototype rb lib/ > generated.rbs
1194
+
1195
+ # Write more descrictive types by hand.
1196
+ $ $EDITOR handwritten.rbs
1197
+
1198
+ # Remove hand-written method definitions from generated.rbs.
1199
+ $ rbs subtract --write generated.rbs handwritten.rbs
1200
+
1201
+ Options:
1202
+ HELP
1203
+ opts.on('-w', '--write', 'Overwrite files directry') { write_to_file = true }
1204
+ opts.on('--subtrahend=PATH', '') { |path| subtrahend_paths << path }
1205
+ opts.parse!(args)
1206
+ end
1207
+
1208
+ if subtrahend_paths.empty?
1209
+ *minuend_paths, subtrahend_path = args
1210
+ unless subtrahend_path
1211
+ stdout.puts opts.help
1212
+ exit 1
1213
+ end
1214
+ subtrahend_paths << subtrahend_path
1215
+ else
1216
+ minuend_paths = args
1217
+ end
1218
+
1219
+ if minuend_paths.empty?
1220
+ stdout.puts opts.help
1221
+ exit 1
1222
+ end
1223
+
1224
+ subtrahend = Environment.new.tap do |env|
1225
+ loader = EnvironmentLoader.new(core_root: nil)
1226
+ subtrahend_paths.each do |path|
1227
+ loader.add(path: Pathname(path))
1228
+ end
1229
+ loader.load(env: env)
1230
+ end
1231
+
1232
+ minuend_paths.each do |minuend_path|
1233
+ FileFinder.each_file(Pathname(minuend_path), immediate: true, skip_hidden: true) do |rbs_path|
1234
+ buf = Buffer.new(name: rbs_path, content: rbs_path.read)
1235
+ _, dirs, decls = Parser.parse_signature(buf)
1236
+ subtracted = Subtractor.new(decls, subtrahend).call
1237
+
1238
+ io = StringIO.new
1239
+ w = Writer.new(out: io)
1240
+ w.write(dirs)
1241
+ w.write(subtracted)
1242
+
1243
+ if write_to_file
1244
+ rbs_path.write(io.string)
1245
+ else
1246
+ stdout.puts(io.string)
1247
+ end
1248
+ end
1249
+ end
1250
+ end
1141
1251
  end
1142
1252
  end
@@ -76,7 +76,7 @@ module RBS
76
76
  end
77
77
 
78
78
  if spec = gem_hash[dep.name]
79
- assign_gem(name: dep.name, version: spec.version, ignored_gems: ignored_gems, src_data: nil)
79
+ assign_gem(name: dep.name, version: spec.version, ignored_gems: ignored_gems, src_data: nil, skip: dep.source.is_a?(Bundler::Source::Gemspec))
80
80
  end
81
81
  end
82
82
 
@@ -91,43 +91,45 @@ module RBS
91
91
  end
92
92
  end
93
93
 
94
- private def assign_gem(name:, version:, src_data:, ignored_gems:)
94
+ private def assign_gem(name:, version:, src_data:, ignored_gems:, skip: false)
95
95
  return if ignored_gems.include?(name)
96
96
  return if lockfile.gems.key?(name)
97
97
 
98
- # @type var locked: Lockfile::library?
98
+ unless skip
99
+ # @type var locked: Lockfile::library?
99
100
 
100
- if existing_lockfile
101
- locked = existing_lockfile.gems[name]
102
- end
101
+ if existing_lockfile
102
+ locked = existing_lockfile.gems[name]
103
+ end
103
104
 
104
- # If rbs_collection.lock.yaml contain the gem, use it.
105
- # Else find the gem from gem_collection.
106
- unless locked
107
- source =
108
- if src_data
109
- Sources.from_config_entry(src_data, base_directory: config.config_path.dirname)
110
- else
111
- find_source(name: name)
105
+ # If rbs_collection.lock.yaml contain the gem, use it.
106
+ # Else find the gem from gem_collection.
107
+ unless locked
108
+ source =
109
+ if src_data
110
+ Sources.from_config_entry(src_data, base_directory: config.config_path.dirname)
111
+ else
112
+ find_source(name: name)
113
+ end
114
+
115
+ if source
116
+ installed_version = version
117
+ best_version = find_best_version(version: installed_version, versions: source.versions(name))
118
+
119
+ locked = {
120
+ name: name,
121
+ version: best_version.to_s,
122
+ source: source,
123
+ }
112
124
  end
113
-
114
- if source
115
- installed_version = version
116
- best_version = find_best_version(version: installed_version, versions: source.versions(name))
117
-
118
- locked = {
119
- name: name,
120
- version: best_version.to_s,
121
- source: source,
122
- }
123
125
  end
124
- end
125
126
 
126
- if locked
127
- lockfile.gems[name] = locked
127
+ if locked
128
+ lockfile.gems[name] = locked
128
129
 
129
- locked[:source].dependencies_of(locked[:name], locked[:version])&.each do |dep|
130
- assign_stdlib(name: dep["name"], from_gem: name)
130
+ locked[:source].dependencies_of(locked[:name], locked[:version])&.each do |dep|
131
+ assign_stdlib(name: dep["name"], from_gem: name)
132
+ end
131
133
  end
132
134
  end
133
135
 
@@ -239,14 +239,6 @@ module RBS
239
239
  definition.class_variables.merge!(defn.class_variables)
240
240
  end
241
241
 
242
- all_interfaces = one_ancestors.each_extended_interface.flat_map do |interface|
243
- other_interfaces = ancestor_builder.interface_ancestors(interface.name).ancestors #: Array[Definition::Ancestor::Instance]
244
- other_interfaces = other_interfaces.select {|ancestor| ancestor.source }
245
- [interface, *other_interfaces]
246
- end
247
- interface_methods = interface_methods(all_interfaces)
248
- import_methods(definition, type_name, methods, interface_methods, Substitution.new)
249
-
250
242
  one_ancestors.each_extended_module do |mod|
251
243
  mod.args.each do |arg|
252
244
  validate_type_presence(arg)
@@ -256,7 +248,12 @@ module RBS
256
248
  define_instance(definition, mod.name, subst)
257
249
  end
258
250
 
259
- interface_methods = interface_methods(one_ancestors.each_extended_interface.to_a)
251
+ all_interfaces = one_ancestors.each_extended_interface.flat_map do |interface|
252
+ other_interfaces = ancestor_builder.interface_ancestors(interface.name).ancestors #: Array[Definition::Ancestor::Instance]
253
+ other_interfaces = other_interfaces.select {|ancestor| ancestor.source }
254
+ [interface, *other_interfaces]
255
+ end
256
+ interface_methods = interface_methods(all_interfaces)
260
257
  import_methods(definition, type_name, methods, interface_methods, Substitution.new)
261
258
 
262
259
  entry.decls.each do |d|
@@ -365,7 +365,7 @@ module RBS
365
365
  name = decl.name.with_prefix(namespace)
366
366
 
367
367
  if interface_entry = interface_decls[name]
368
- DuplicatedDeclarationError.new(name, decl, interface_entry.decl)
368
+ raise DuplicatedDeclarationError.new(name, decl, interface_entry.decl)
369
369
  end
370
370
 
371
371
  interface_decls[name] = InterfaceEntry.new(name: name, decl: decl, outer: outer)
@@ -374,7 +374,7 @@ module RBS
374
374
  name = decl.name.with_prefix(namespace)
375
375
 
376
376
  if entry = type_alias_decls[name]
377
- DuplicatedDeclarationError.new(name, decl, entry.decl)
377
+ raise DuplicatedDeclarationError.new(name, decl, entry.decl)
378
378
  end
379
379
 
380
380
  type_alias_decls[name] = TypeAliasEntry.new(name: name, decl: decl, outer: outer)