rbs 3.2.0 → 3.3.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.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/comments.yml +1 -1
  3. data/.github/workflows/ruby.yml +7 -2
  4. data/.rubocop.yml +1 -1
  5. data/CHANGELOG.md +134 -0
  6. data/Gemfile +3 -0
  7. data/Gemfile.lock +21 -15
  8. data/README.md +11 -2
  9. data/Rakefile +10 -7
  10. data/Steepfile +7 -7
  11. data/core/basic_object.rbs +7 -7
  12. data/core/binding.rbs +3 -3
  13. data/core/builtin.rbs +171 -5
  14. data/core/constants.rbs +17 -17
  15. data/core/dir.rbs +3 -3
  16. data/core/encoding.rbs +434 -628
  17. data/core/enumerator.rbs +37 -0
  18. data/core/exception.rbs +11 -11
  19. data/core/false_class.rbs +5 -11
  20. data/core/fiber.rbs +5 -5
  21. data/core/file_test.rbs +28 -26
  22. data/core/kernel.rbs +900 -21
  23. data/core/marshal.rbs +24 -14
  24. data/core/match_data.rbs +8 -8
  25. data/core/math.rbs +57 -53
  26. data/core/method.rbs +3 -1
  27. data/core/module.rbs +38 -36
  28. data/core/nil_class.rbs +7 -13
  29. data/core/object.rbs +3 -966
  30. data/core/process.rbs +3 -3
  31. data/core/ractor.rbs +2 -2
  32. data/core/rb_config.rbs +64 -43
  33. data/core/regexp.rbs +3 -3
  34. data/core/set.rbs +3 -2
  35. data/core/signal.rbs +10 -4
  36. data/core/struct.rbs +1 -1
  37. data/core/thread.rbs +7 -7
  38. data/core/thread_group.rbs +9 -9
  39. data/core/true_class.rbs +5 -11
  40. data/core/unbound_method.rbs +56 -7
  41. data/core/warning.rbs +33 -0
  42. data/docs/collection.md +56 -6
  43. data/docs/data_and_struct.md +57 -0
  44. data/docs/stdlib.md +61 -2
  45. data/docs/syntax.md +123 -2
  46. data/ext/rbs_extension/constants.c +73 -72
  47. data/ext/rbs_extension/lexer.c +624 -569
  48. data/ext/rbs_extension/lexer.h +1 -0
  49. data/ext/rbs_extension/lexer.re +1 -0
  50. data/ext/rbs_extension/lexstate.c +1 -0
  51. data/ext/rbs_extension/parser.c +6 -0
  52. data/goodcheck.yml +2 -2
  53. data/lib/rbs/annotate/formatter.rb +13 -3
  54. data/lib/rbs/annotate/rdoc_source.rb +10 -1
  55. data/lib/rbs/cli/colored_io.rb +48 -0
  56. data/lib/rbs/cli/diff.rb +80 -0
  57. data/lib/rbs/cli.rb +169 -17
  58. data/lib/rbs/collection/config/lockfile.rb +0 -25
  59. data/lib/rbs/collection/config/lockfile_generator.rb +0 -6
  60. data/lib/rbs/collection/installer.rb +1 -1
  61. data/lib/rbs/collection/sources/git.rb +6 -4
  62. data/lib/rbs/collection/sources/local.rb +7 -5
  63. data/lib/rbs/diff.rb +121 -0
  64. data/lib/rbs/environment.rb +7 -4
  65. data/lib/rbs/method_type.rb +23 -0
  66. data/lib/rbs/prototype/rb.rb +2 -9
  67. data/lib/rbs/prototype/rbi.rb +1 -1
  68. data/lib/rbs/prototype/runtime/helpers.rb +59 -0
  69. data/lib/rbs/prototype/runtime/reflection.rb +19 -0
  70. data/lib/rbs/prototype/runtime/value_object_generator.rb +275 -0
  71. data/lib/rbs/prototype/runtime.rb +233 -153
  72. data/lib/rbs/resolver/constant_resolver.rb +1 -1
  73. data/lib/rbs/sorter.rb +144 -117
  74. data/lib/rbs/test/guaranteed.rb +31 -0
  75. data/lib/rbs/test/type_check.rb +4 -4
  76. data/lib/rbs/test.rb +3 -0
  77. data/lib/rbs/types.rb +184 -3
  78. data/lib/rbs/version.rb +1 -1
  79. data/lib/rbs/writer.rb +4 -4
  80. data/lib/rbs.rb +1 -0
  81. data/rbs.gemspec +1 -0
  82. data/sig/annotate/formatter.rbs +2 -2
  83. data/sig/annotate/rdoc_annotater.rbs +1 -1
  84. data/sig/cli/colored_io.rbs +15 -0
  85. data/sig/cli/diff.rbs +21 -0
  86. data/sig/cli.rbs +2 -0
  87. data/sig/collection/config/lockfile.rbs +0 -6
  88. data/sig/diff.rbs +23 -0
  89. data/sig/errors.rbs +1 -5
  90. data/sig/method_types.rbs +6 -0
  91. data/sig/prototype/runtime.rbs +166 -0
  92. data/sig/rdoc/rbs.rbs +4 -0
  93. data/sig/shims/bundler.rbs +5 -0
  94. data/sig/sorter.rbs +23 -5
  95. data/sig/types.rbs +29 -0
  96. data/stdlib/benchmark/0/benchmark.rbs +1 -1
  97. data/stdlib/cgi/0/core.rbs +2 -2
  98. data/stdlib/did_you_mean/0/did_you_mean.rbs +2 -2
  99. data/stdlib/digest/0/digest.rbs +1 -1
  100. data/stdlib/fileutils/0/fileutils.rbs +1 -1
  101. data/stdlib/forwardable/0/forwardable.rbs +4 -4
  102. data/stdlib/io-console/0/io-console.rbs +1 -1
  103. data/stdlib/json/0/json.rbs +37 -0
  104. data/stdlib/logger/0/logger.rbs +2 -2
  105. data/stdlib/net-http/0/manifest.yaml +1 -1
  106. data/stdlib/net-http/0/net-http.rbs +16 -63
  107. data/stdlib/net-protocol/0/manifest.yaml +2 -0
  108. data/stdlib/net-protocol/0/net-protocol.rbs +56 -0
  109. data/stdlib/net-smtp/0/manifest.yaml +2 -0
  110. data/stdlib/net-smtp/0/net-smtp.rbs +55 -0
  111. data/stdlib/open-uri/0/manifest.yaml +3 -0
  112. data/stdlib/open-uri/0/open-uri.rbs +341 -0
  113. data/stdlib/openssl/0/openssl.rbs +1 -1
  114. data/stdlib/pp/0/manifest.yaml +2 -0
  115. data/stdlib/pp/0/pp.rbs +301 -0
  116. data/stdlib/{yaml → psych}/0/dbm.rbs +3 -3
  117. data/stdlib/psych/0/manifest.yaml +3 -0
  118. data/stdlib/psych/0/psych.rbs +391 -0
  119. data/stdlib/{yaml → psych}/0/store.rbs +2 -2
  120. data/stdlib/rdoc/0/code_object.rbs +55 -0
  121. data/stdlib/rdoc/0/comment.rbs +60 -0
  122. data/stdlib/rdoc/0/context.rbs +153 -0
  123. data/stdlib/rdoc/0/markup.rbs +119 -0
  124. data/stdlib/rdoc/0/parser.rbs +56 -0
  125. data/stdlib/rdoc/0/rdoc.rbs +0 -372
  126. data/stdlib/rdoc/0/ri.rbs +17 -0
  127. data/stdlib/rdoc/0/store.rbs +48 -0
  128. data/stdlib/rdoc/0/top_level.rbs +97 -0
  129. data/stdlib/socket/0/basic_socket.rbs +1 -1
  130. data/stdlib/socket/0/socket.rbs +1 -1
  131. data/stdlib/uri/0/common.rbs +1 -1
  132. data/stdlib/yaml/0/manifest.yaml +1 -2
  133. data/stdlib/yaml/0/yaml.rbs +1 -199
  134. metadata +49 -7
  135. data/sig/shims/pp.rbs +0 -3
  136. data/sig/shims.rbs +0 -47
@@ -60,6 +60,7 @@ enum TokenType {
60
60
  kVOID, /* void */
61
61
  kUSE, /* use */
62
62
  kAS, /* as */
63
+ k__TODO__, /* __todo__ */
63
64
 
64
65
  tLIDENT, /* Identifiers starting with lower case */
65
66
  tUIDENT, /* Identifiers starting with upper case */
@@ -95,6 +95,7 @@ start:
95
95
  "void" { return next_token(state, kVOID); }
96
96
  "use" { return next_token(state, kUSE); }
97
97
  "as" { return next_token(state, kAS); }
98
+ "__todo__" { return next_token(state, k__TODO__); }
98
99
 
99
100
  dqstring = ["] ("\\"[abefnrstv"\\] | [^"\\\x00])* ["];
100
101
  sqstring = ['] ("\\"['\\] | [^'\x00])* ['];
@@ -59,6 +59,7 @@ static const char *RBS_TOKENTYPE_NAMES[] = {
59
59
  "kVOID", /* void */
60
60
  "kUSE", /* use */
61
61
  "kAS", /* as */
62
+ "k__TODO__", /* __todo__ */
62
63
 
63
64
  "tLIDENT", /* Identifiers starting with lower case */
64
65
  "tUIDENT", /* Identifiers starting with upper case */
@@ -39,6 +39,7 @@
39
39
  case kUNTYPED: \
40
40
  case kUSE: \
41
41
  case kAS: \
42
+ case k__TODO__: \
42
43
  /* nop */
43
44
 
44
45
  typedef struct {
@@ -898,6 +899,11 @@ static VALUE parse_simple(parserstate *state) {
898
899
  return rbs_base_type(RBS_Types_Bases_Void, rbs_location_current_token(state));
899
900
  case kUNTYPED:
900
901
  return rbs_base_type(RBS_Types_Bases_Any, rbs_location_current_token(state));
902
+ case k__TODO__: {
903
+ VALUE type = rbs_base_type(RBS_Types_Bases_Any, rbs_location_current_token(state));
904
+ rb_funcall(type, rb_intern("todo!"), 0);
905
+ return type;
906
+ }
901
907
  case tINTEGER: {
902
908
  VALUE literal = rb_funcall(
903
909
  string_of_loc(state, state->current_token.range.start, state->current_token.range.end),
data/goodcheck.yml CHANGED
@@ -13,9 +13,9 @@ rules:
13
13
  glob:
14
14
  - "{core,stdlib}/**/*.rbs"
15
15
  fail:
16
- - "def `send`: (String | Symbol arg0, *untyped arg1) -> untyped"
16
+ - "def `send`: (interned arg0, *untyped arg1) -> untyped"
17
17
  pass:
18
- - "def `send`: (String | Symbol, *untyped) -> untyped"
18
+ - "def `send`: (interned, *untyped) -> untyped"
19
19
 
20
20
  - id: rbs.prefer_boolish
21
21
  pattern:
@@ -59,10 +59,20 @@ module RBS
59
59
 
60
60
  def self.each_part(doc, &block)
61
61
  if block
62
- if doc.file
63
- yield doc
62
+ document =
63
+ case doc
64
+ when String
65
+ raise
66
+ when RDoc::Comment
67
+ document = doc.parse
68
+ when RDoc::Markup::Document
69
+ document = doc
70
+ end
71
+
72
+ if document.file
73
+ yield document
64
74
  else
65
- doc.each do |d|
75
+ document.each do |d|
66
76
  each_part(d, &block)
67
77
  end
68
78
  end
@@ -47,7 +47,16 @@ module RBS
47
47
  def docs
48
48
  if ds = yield
49
49
  unless ds.empty?
50
- ds.map(&:comment)
50
+ ds.map do |code_object|
51
+ case comment = code_object.comment
52
+ when String
53
+ raise
54
+ when RDoc::Comment
55
+ comment.parse
56
+ when RDoc::Markup::Document
57
+ comment
58
+ end
59
+ end
51
60
  end
52
61
  end
53
62
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ class CLI
5
+ class ColoredIO
6
+ attr_reader :stdout
7
+
8
+ def initialize(stdout:)
9
+ @stdout = stdout
10
+ end
11
+
12
+ def puts_red(string)
13
+ if can_display_colors?
14
+ puts "\e[31m#{string}\e[m"
15
+ else
16
+ puts string
17
+ end
18
+ end
19
+
20
+ def puts_green(string)
21
+ if can_display_colors?
22
+ puts "\e[32m#{string}\e[m"
23
+ else
24
+ puts string
25
+ end
26
+ end
27
+
28
+ def puts(...)
29
+ stdout.puts(...)
30
+ end
31
+
32
+ private
33
+
34
+ # https://github.com/rubygems/rubygems/blob/ed65279100234a17d65d71fe26de5083984ac5b8/bundler/lib/bundler/vendor/thor/lib/thor/shell/color.rb#L99-L109
35
+ def can_display_colors?
36
+ are_colors_supported? && !are_colors_disabled?
37
+ end
38
+
39
+ def are_colors_supported?
40
+ stdout.tty? && ENV["TERM"] != "dumb"
41
+ end
42
+
43
+ def are_colors_disabled?
44
+ !ENV['NO_COLOR'].nil? && !ENV.fetch('NO_COLOR', '').empty?
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ class CLI
5
+ class Diff
6
+ def initialize(argv:, library_options:, stdout: $stdout, stderr: $stderr)
7
+ @format = nil
8
+ @stdout = stdout
9
+ @stderr = stderr
10
+
11
+ # @type var type_name: String?
12
+ type_name = nil
13
+ library_options = library_options
14
+ before_path = []
15
+ after_path = []
16
+
17
+ opt = OptionParser.new do |o|
18
+ o.banner = <<~HELP
19
+ [Experimental] This command is experimental. API and output compatibility is not guaranteed.
20
+
21
+ Usage:
22
+ rbs diff --format markdown --type-name Foo --before before_sig --after after_sig
23
+
24
+ Print diff for rbs environment dir
25
+
26
+ Examples:
27
+
28
+ # Diff dir1 and dir2 for Foo
29
+ $ rbs diff --format markdown --type-name Foo --before dir1 --after dir2
30
+
31
+ # Confirmation of methods related to Time class added by including stdlib/time
32
+ $ rbs diff --format diff --type-name Time --after stdlib/time
33
+ HELP
34
+ o.on("--format NAME") { |arg| @format = arg }
35
+ o.on("--type-name NAME") { |arg| type_name = arg }
36
+ o.on("--before DIR") { |arg| before_path << arg }
37
+ o.on("--after DIR") { |arg| after_path << arg }
38
+ end
39
+ opt.parse!(argv)
40
+
41
+ unless @format && type_name && ["markdown", "diff"].include?(@format)
42
+ @stderr.puts opt.banner
43
+ exit 1
44
+ end
45
+
46
+ @diff = RBS::Diff.new(
47
+ type_name: TypeName(type_name).absolute!,
48
+ library_options: library_options,
49
+ after_path: after_path,
50
+ before_path: before_path
51
+ )
52
+ end
53
+
54
+ def run
55
+ public_send("run_#{@format}")
56
+ end
57
+
58
+ def run_diff
59
+ first = true
60
+ io = RBS::CLI::ColoredIO.new(stdout: @stdout)
61
+ @diff.each_diff do |before, after|
62
+ io.puts if !first
63
+ io.puts_red "- #{before}"
64
+ io.puts_green "+ #{after}"
65
+ first = false
66
+ end
67
+ end
68
+
69
+ def run_markdown
70
+ @stdout.puts "| before | after |"
71
+ @stdout.puts "| --- | --- |"
72
+ @diff.each_diff do |before, after|
73
+ before.gsub!("|", "\\|")
74
+ after.gsub!("|", "\\|")
75
+ @stdout.puts "| `#{before}` | `#{after}` |"
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
data/lib/rbs/cli.rb CHANGED
@@ -8,6 +8,9 @@ require "stringio"
8
8
 
9
9
  module RBS
10
10
  class CLI
11
+ autoload :ColoredIO, 'rbs/cli/colored_io'
12
+ autoload :Diff, 'rbs/cli/diff'
13
+
11
14
  class LibraryOptions
12
15
  attr_accessor :core_root
13
16
  attr_accessor :config_path
@@ -90,7 +93,7 @@ module RBS
90
93
  @stderr = stderr
91
94
  end
92
95
 
93
- COMMANDS = [:ast, :annotate, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test, :collection, :subtract]
96
+ COMMANDS = [:ast, :annotate, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test, :collection, :subtract, :diff]
94
97
 
95
98
  def parse_logging_options(opts)
96
99
  opts.on("--log-level LEVEL", "Specify log level (defaults to `warn`)") do |level|
@@ -433,13 +436,17 @@ EOU
433
436
  stdout.puts " accessibility: #{method.accessibility}"
434
437
  stdout.puts " types:"
435
438
  separator = " "
436
- for type in method.method_types
437
- stdout.puts " #{separator} #{type}"
439
+ length_max = method.method_types.map { |type| type.to_s.length }.max or raise
440
+ method.method_types.each do |type|
441
+ stdout.puts format(" %s %-#{length_max}s at %s", separator, type, type.location)
438
442
  separator = "|"
439
443
  end
440
444
  end
441
445
 
442
446
  def run_validate(args, options)
447
+ stdout = stdout()
448
+ exit_error = false
449
+
443
450
  OptionParser.new do |opts|
444
451
  opts.banner = <<EOU
445
452
  Usage: rbs validate
@@ -452,8 +459,11 @@ Examples:
452
459
  EOU
453
460
 
454
461
  opts.on("--silent") do
455
- @stdout = StringIO.new
462
+ stdout = StringIO.new
456
463
  end
464
+ opts.on("--[no-]exit-error-on-syntax-error", "exit(1) if syntax error is detected") {|bool|
465
+ exit_error = bool
466
+ }
457
467
  end.parse!(args)
458
468
 
459
469
  loader = options.loader()
@@ -462,6 +472,32 @@ EOU
462
472
  builder = DefinitionBuilder.new(env: env)
463
473
  validator = Validator.new(env: env, resolver: Resolver::TypeNameResolver.new(env))
464
474
 
475
+ syntax_errors = [] #: Array[String]
476
+
477
+ no_self_type_validator = ->(type) {
478
+ # @type var type: Types::t | MethodType
479
+ if type.has_self_type?
480
+ syntax_errors << "#{type.location}: `self` type is not allowed in this context"
481
+ end
482
+ }
483
+
484
+ no_classish_type_validator = ->(type) {
485
+ # @type var type: Types::t | MethodType
486
+ if type.has_classish_type?
487
+ syntax_errors << "#{type.location}: `instance` or `class` type is not allowed in this context"
488
+ end
489
+ }
490
+
491
+ void_type_context_validator = ->(type, allowed_here = false) {
492
+ # @type var type: Types::t | MethodType
493
+ if allowed_here
494
+ next if type.is_a?(Types::Bases::Void)
495
+ end
496
+ if type.with_nonreturn_void?
497
+ syntax_errors << "#{type.location}: `void` type is only allowed in return type or generics parameter"
498
+ end
499
+ }
500
+
465
501
  env.class_decls.each do |name, decl|
466
502
  stdout.puts "Validating class/module definition: `#{name}`..."
467
503
  builder.build_instance(name).each_type do |type|
@@ -471,6 +507,29 @@ EOU
471
507
  validator.validate_type type, context: nil
472
508
  end
473
509
 
510
+ case decl
511
+ when Environment::ClassEntry
512
+ decl.decls.each do |decl|
513
+ if super_class = decl.decl.super_class
514
+ super_class.args.each do |arg|
515
+ void_type_context_validator[arg, true]
516
+ no_self_type_validator[arg]
517
+ no_classish_type_validator[arg]
518
+ end
519
+ end
520
+ end
521
+ when Environment::ModuleEntry
522
+ decl.decls.each do |decl|
523
+ decl.decl.self_types.each do |self_type|
524
+ self_type.args.each do |arg|
525
+ void_type_context_validator[arg, true]
526
+ no_self_type_validator[arg]
527
+ no_classish_type_validator[arg]
528
+ end
529
+ end
530
+ end
531
+ end
532
+
474
533
  d = decl.primary.decl
475
534
 
476
535
  validator.validate_type_params(
@@ -479,11 +538,36 @@ EOU
479
538
  location: d.location&.aref(:type_params)
480
539
  )
481
540
 
541
+ d.type_params.each do |param|
542
+ if ub = param.upper_bound
543
+ void_type_context_validator[ub]
544
+ no_self_type_validator[ub]
545
+ no_classish_type_validator[ub]
546
+ end
547
+ end
548
+
482
549
  decl.decls.each do |d|
483
550
  d.decl.each_member do |member|
484
551
  case member
485
552
  when AST::Members::MethodDefinition
486
553
  validator.validate_method_definition(member, type_name: name)
554
+ member.overloads.each do |ov|
555
+ void_type_context_validator[ov.method_type]
556
+ end
557
+ when AST::Members::Attribute
558
+ void_type_context_validator[member.type]
559
+ when AST::Members::Mixin
560
+ member.args.each do |arg|
561
+ no_self_type_validator[arg]
562
+ unless arg.is_a?(Types::Bases::Void)
563
+ void_type_context_validator[arg, true]
564
+ end
565
+ end
566
+ when AST::Members::Var
567
+ void_type_context_validator[member.type]
568
+ if member.is_a?(AST::Members::ClassVariable)
569
+ no_self_type_validator[member.type]
570
+ end
487
571
  end
488
572
  end
489
573
  end
@@ -510,6 +594,10 @@ EOU
510
594
  case member
511
595
  when AST::Members::MethodDefinition
512
596
  validator.validate_method_definition(member, type_name: name)
597
+ member.overloads.each do |ov|
598
+ void_type_context_validator[ov.method_type]
599
+ no_classish_type_validator[ov.method_type]
600
+ end
513
601
  end
514
602
  end
515
603
  end
@@ -518,11 +606,17 @@ EOU
518
606
  stdout.puts "Validating constant: `#{name}`..."
519
607
  validator.validate_type const.decl.type, context: const.context
520
608
  builder.ensure_namespace!(name.namespace, location: const.decl.location)
609
+ no_self_type_validator[const.decl.type]
610
+ no_classish_type_validator[const.decl.type]
611
+ void_type_context_validator[const.decl.type]
521
612
  end
522
613
 
523
614
  env.global_decls.each do |name, global|
524
615
  stdout.puts "Validating global: `#{name}`..."
525
616
  validator.validate_type global.decl.type, context: nil
617
+ no_self_type_validator[global.decl.type]
618
+ no_classish_type_validator[global.decl.type]
619
+ void_type_context_validator[global.decl.type]
526
620
  end
527
621
 
528
622
  env.type_alias_decls.each do |name, decl|
@@ -531,6 +625,18 @@ EOU
531
625
  validator.validate_type type, context: nil
532
626
  end
533
627
  validator.validate_type_alias(entry: decl)
628
+ no_self_type_validator[decl.decl.type]
629
+ no_classish_type_validator[decl.decl.type]
630
+ void_type_context_validator[decl.decl.type]
631
+ end
632
+
633
+ unless syntax_errors.empty?
634
+ syntax_errors.sort!
635
+ syntax_errors.uniq!
636
+ syntax_errors.each do |message|
637
+ self.stdout.puts message
638
+ end
639
+ exit 1 if exit_error
534
640
  end
535
641
  end
536
642
 
@@ -644,8 +750,10 @@ EOU
644
750
  require_libs = []
645
751
  relative_libs = []
646
752
  merge = false
753
+ todo = false
647
754
  owners_included = []
648
755
  outline = false
756
+ autoload = false
649
757
 
650
758
  OptionParser.new do |opts|
651
759
  opts.banner = <<EOU
@@ -671,26 +779,62 @@ EOU
671
779
  opts.on("--merge", "Merge generated prototype RBS with existing RBS") do
672
780
  merge = true
673
781
  end
782
+ opts.on("--todo", "Generates only undefined methods compared to objects") do
783
+ Warning.warn("Geneating prototypes with `--todo` option is experimental\n", category: :experimental)
784
+ todo = true
785
+ end
674
786
  opts.on("--method-owner CLASS", "Generate method prototypes if the owner of the method is [CLASS]") do |klass|
675
787
  owners_included << klass
676
788
  end
677
789
  opts.on("--outline", "Generates only module/class/constant declaration (no method definition)") do
678
790
  outline = true
679
791
  end
792
+ opts.on("--autoload", "Load all autoload path") do
793
+ autoload = true
794
+ end
680
795
  end.parse!(args)
681
796
 
682
797
  loader = options.loader()
683
798
  env = Environment.from_loader(loader).resolve_type_names
684
799
 
685
- require_libs.each do |lib|
686
- require(lib)
687
- end
688
-
689
- relative_libs.each do |lib|
690
- eval("require_relative(lib)", binding, "rbs")
800
+ # @type var autoloader: ^() { () -> void } -> void
801
+ autoloader = ->(&block) {
802
+ if autoload
803
+ hook = Module.new do
804
+ def autoload(name, path)
805
+ super
806
+ end
807
+ end
808
+ ::Module.prepend(hook)
809
+ ::Kernel.prepend(hook)
810
+
811
+ arguments = []
812
+ TracePoint.new(:call) do |tp|
813
+ base = tp.self.kind_of?(Module) ? tp.self : Kernel
814
+ name = (tp.binding or raise).local_variable_get(:name)
815
+ arguments << [base, name]
816
+ end.enable(target: hook.instance_method(:autoload), &block)
817
+
818
+ arguments.each do |(base, name)|
819
+ begin
820
+ base.const_get(name)
821
+ rescue LoadError, StandardError
822
+ end
823
+ end
824
+ else
825
+ block.call
826
+ end
827
+ }
828
+ autoloader.call do
829
+ require_libs.each do |lib|
830
+ require(lib)
831
+ end
832
+ relative_libs.each do |lib|
833
+ eval("require_relative(lib)", binding, "rbs")
834
+ end
691
835
  end
692
836
 
693
- runtime = Prototype::Runtime.new(patterns: args, env: env, merge: merge, owners_included: owners_included)
837
+ runtime = Prototype::Runtime.new(patterns: args, env: env, merge: merge, todo: todo, owners_included: owners_included)
694
838
  runtime.outline = outline
695
839
 
696
840
  decls = runtime.decls
@@ -827,7 +971,12 @@ EOU
827
971
  output_path = (output_dir + relative_path).sub_ext(".rbs")
828
972
 
829
973
  parser = new_parser[]
830
- parser.parse file_path.read()
974
+ begin
975
+ parser.parse file_path.read()
976
+ rescue SyntaxError
977
+ stdout.puts " ⚠️ Unable to parse due to SyntaxError: `#{file_path}`"
978
+ next
979
+ end
831
980
 
832
981
  if output_path.file?
833
982
  if force
@@ -1136,11 +1285,10 @@ EOB
1136
1285
  # A directory to install the downloaded RBSs
1137
1286
  path: .gem_rbs_collection
1138
1287
 
1139
- gems:
1140
- # Skip loading rbs gem's RBS.
1141
- # It's unnecessary if you don't use rbs as a library.
1142
- - name: rbs
1143
- ignore: true
1288
+ # gems:
1289
+ # # If you want to avoid installing rbs files for gems, you can specify them here.
1290
+ # - name: GEM_NAME
1291
+ # ignore: true
1144
1292
  YAML
1145
1293
  stdout.puts "created: #{config_path}"
1146
1294
  when 'clean'
@@ -1259,5 +1407,9 @@ EOB
1259
1407
  end
1260
1408
  end
1261
1409
  end
1410
+
1411
+ def run_diff(argv, library_options)
1412
+ Diff.new(argv: argv, library_options: library_options, stdout: stdout, stderr: stderr).run
1413
+ end
1262
1414
  end
1263
1415
  end
@@ -12,7 +12,6 @@ module RBS
12
12
  @path = path
13
13
  @gemfile_lock_path = gemfile_lock_path
14
14
 
15
- @sources = {}
16
15
  @gems = {}
17
16
  end
18
17
 
@@ -26,27 +25,15 @@ module RBS
26
25
  end
27
26
  end
28
27
 
29
- def each_source(&block)
30
- if block
31
- sources.each_value(&block)
32
- yield Sources::Rubygems.instance
33
- yield Sources::Stdlib.instance
34
- else
35
- enum_for :each_source
36
- end
37
- end
38
-
39
28
  def to_lockfile
40
29
  # @type var data: lockfile_data
41
30
 
42
31
  data = {
43
- "sources" => sources.each_value.sort_by {|s| s.name }.map {|source| source.to_lockfile },
44
32
  "path" => path.to_s,
45
33
  "gems" => gems.each_value.sort_by {|g| g[:name] }.map {|hash| library_data(hash) },
46
34
  "gemfile_lock_path" => gemfile_lock_path.to_s
47
35
  }
48
36
 
49
- data.delete("sources") if sources.empty?
50
37
  data.delete("gems") if gems.empty?
51
38
 
52
39
  data
@@ -60,18 +47,6 @@ module RBS
60
47
 
61
48
  lockfile = Lockfile.new(lockfile_path: lockfile_path, path: path, gemfile_lock_path: gemfile_lock_path)
62
49
 
63
- if sources = data["sources"]
64
- sources.each do |src|
65
- git = Sources::Git.new(
66
- name: src["name"],
67
- revision: src["revision"],
68
- remote: src["remote"],
69
- repo_dir: src["repo_dir"]
70
- )
71
- lockfile.sources[git.name] = git
72
- end
73
- end
74
-
75
50
  if gems = data["gems"]
76
51
  gems.each do |gem|
77
52
  src = gem["source"]
@@ -44,12 +44,6 @@ module RBS
44
44
  path: config.repo_path_data,
45
45
  gemfile_lock_path: definition.lockfile.relative_path_from(lockfile_dir)
46
46
  )
47
- config.sources.each do |source|
48
- case source
49
- when Sources::Git
50
- lockfile.sources[source.name] = source
51
- end
52
- end
53
47
 
54
48
  if with_lockfile && lockfile_path.file?
55
49
  @existing_lockfile = Lockfile.from_lockfile(lockfile_path: lockfile_path, data: YAML.load_file(lockfile_path.to_s))
@@ -25,7 +25,7 @@ module RBS
25
25
  stdout: stdout
26
26
  )
27
27
  end
28
- stdout.puts "It's done! #{selected.size} gems' RBSs now installed."
28
+ CLI::ColoredIO.new(stdout: stdout).puts_green("It's done! #{selected.size} gems' RBSs now installed.")
29
29
  end
30
30
  end
31
31
  end
@@ -45,23 +45,25 @@ module RBS
45
45
 
46
46
  gem_dir = dest.join(name, version)
47
47
 
48
+ colored_io = CLI::ColoredIO.new(stdout: stdout)
49
+
48
50
  case
49
51
  when gem_dir.symlink?
50
- stdout.puts "Updating to #{format_config_entry(name, version)} from a local source"
52
+ colored_io.puts_green("Updating to #{format_config_entry(name, version)} from a local source")
51
53
  gem_dir.unlink
52
54
  _install(dest: dest, name: name, version: version)
53
55
  when gem_dir.directory?
54
56
  prev = load_metadata(dir: gem_dir)
55
57
 
56
58
  if prev == metadata_content(name: name, version: version)
57
- stdout.puts "Using #{format_config_entry(name, version)}"
59
+ colored_io.puts "Using #{format_config_entry(name, version)}"
58
60
  else
59
- stdout.puts "Updating to #{format_config_entry(name, version)} from #{format_config_entry(prev["name"], prev["version"])}"
61
+ colored_io.puts_green("Updating to #{format_config_entry(name, version)} from #{format_config_entry(prev["name"], prev["version"])}")
60
62
  FileUtils.remove_entry_secure(gem_dir.to_s)
61
63
  _install(dest: dest, name: name, version: version)
62
64
  end
63
65
  when !gem_dir.exist?
64
- stdout.puts "Installing #{format_config_entry(name, version)}"
66
+ colored_io.puts_green("Installing #{format_config_entry(name, version)}")
65
67
  _install(dest: dest, name: name, version: version)
66
68
  else
67
69
  raise