rbs 3.2.2 → 3.3.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (125) 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/CHANGELOG.md +85 -0
  5. data/Gemfile.lock +14 -14
  6. data/README.md +11 -2
  7. data/Rakefile +10 -7
  8. data/Steepfile +7 -7
  9. data/core/basic_object.rbs +7 -7
  10. data/core/binding.rbs +3 -3
  11. data/core/builtin.rbs +171 -5
  12. data/core/constants.rbs +17 -17
  13. data/core/dir.rbs +3 -3
  14. data/core/encoding.rbs +434 -628
  15. data/core/enumerator.rbs +37 -0
  16. data/core/exception.rbs +11 -11
  17. data/core/false_class.rbs +5 -11
  18. data/core/fiber.rbs +3 -3
  19. data/core/file_test.rbs +28 -26
  20. data/core/kernel.rbs +900 -21
  21. data/core/marshal.rbs +24 -14
  22. data/core/match_data.rbs +8 -8
  23. data/core/math.rbs +57 -53
  24. data/core/method.rbs +3 -1
  25. data/core/module.rbs +38 -36
  26. data/core/nil_class.rbs +7 -13
  27. data/core/object.rbs +3 -966
  28. data/core/process.rbs +3 -3
  29. data/core/ractor.rbs +2 -2
  30. data/core/rb_config.rbs +64 -43
  31. data/core/regexp.rbs +3 -3
  32. data/core/signal.rbs +10 -4
  33. data/core/struct.rbs +1 -1
  34. data/core/thread.rbs +7 -7
  35. data/core/thread_group.rbs +9 -9
  36. data/core/true_class.rbs +5 -11
  37. data/core/unbound_method.rbs +56 -7
  38. data/core/warning.rbs +33 -0
  39. data/docs/collection.md +56 -6
  40. data/docs/data_and_struct.md +57 -0
  41. data/docs/stdlib.md +61 -2
  42. data/docs/syntax.md +123 -2
  43. data/ext/rbs_extension/lexer.c +624 -569
  44. data/ext/rbs_extension/lexer.h +1 -0
  45. data/ext/rbs_extension/lexer.re +1 -0
  46. data/ext/rbs_extension/lexstate.c +1 -0
  47. data/ext/rbs_extension/parser.c +6 -0
  48. data/goodcheck.yml +2 -2
  49. data/lib/rbs/annotate/formatter.rb +13 -3
  50. data/lib/rbs/annotate/rdoc_source.rb +10 -1
  51. data/lib/rbs/cli/colored_io.rb +48 -0
  52. data/lib/rbs/cli/diff.rb +80 -0
  53. data/lib/rbs/cli.rb +151 -16
  54. data/lib/rbs/collection/config/lockfile.rb +0 -25
  55. data/lib/rbs/collection/config/lockfile_generator.rb +0 -6
  56. data/lib/rbs/collection/installer.rb +1 -1
  57. data/lib/rbs/collection/sources/git.rb +6 -4
  58. data/lib/rbs/collection/sources/local.rb +7 -5
  59. data/lib/rbs/diff.rb +104 -0
  60. data/lib/rbs/environment.rb +1 -1
  61. data/lib/rbs/method_type.rb +23 -0
  62. data/lib/rbs/prototype/rb.rb +2 -9
  63. data/lib/rbs/prototype/runtime/helpers.rb +59 -0
  64. data/lib/rbs/prototype/runtime/value_object_generator.rb +236 -0
  65. data/lib/rbs/prototype/runtime.rb +234 -150
  66. data/lib/rbs/sorter.rb +144 -117
  67. data/lib/rbs/test/guaranteed.rb +31 -0
  68. data/lib/rbs/test/type_check.rb +4 -4
  69. data/lib/rbs/test.rb +3 -0
  70. data/lib/rbs/types.rb +184 -3
  71. data/lib/rbs/version.rb +1 -1
  72. data/lib/rbs/writer.rb +4 -4
  73. data/lib/rbs.rb +1 -0
  74. data/rbs.gemspec +1 -0
  75. data/sig/annotate/formatter.rbs +2 -2
  76. data/sig/annotate/rdoc_annotater.rbs +1 -1
  77. data/sig/cli/colored_io.rbs +15 -0
  78. data/sig/cli/diff.rbs +21 -0
  79. data/sig/cli.rbs +2 -0
  80. data/sig/collection/config/lockfile.rbs +0 -6
  81. data/sig/diff.rbs +23 -0
  82. data/sig/errors.rbs +1 -5
  83. data/sig/method_types.rbs +6 -0
  84. data/sig/prototype/runtime.rbs +108 -0
  85. data/sig/rdoc/rbs.rbs +4 -0
  86. data/sig/shims/bundler.rbs +5 -0
  87. data/sig/sorter.rbs +23 -5
  88. data/sig/types.rbs +29 -0
  89. data/stdlib/benchmark/0/benchmark.rbs +1 -1
  90. data/stdlib/cgi/0/core.rbs +2 -2
  91. data/stdlib/did_you_mean/0/did_you_mean.rbs +2 -2
  92. data/stdlib/digest/0/digest.rbs +1 -1
  93. data/stdlib/fileutils/0/fileutils.rbs +1 -1
  94. data/stdlib/forwardable/0/forwardable.rbs +4 -4
  95. data/stdlib/io-console/0/io-console.rbs +1 -1
  96. data/stdlib/json/0/json.rbs +37 -0
  97. data/stdlib/logger/0/logger.rbs +2 -2
  98. data/stdlib/net-http/0/manifest.yaml +1 -1
  99. data/stdlib/net-http/0/net-http.rbs +16 -63
  100. data/stdlib/net-protocol/0/manifest.yaml +2 -0
  101. data/stdlib/net-protocol/0/net-protocol.rbs +56 -0
  102. data/stdlib/openssl/0/openssl.rbs +1 -1
  103. data/stdlib/pp/0/manifest.yaml +2 -0
  104. data/stdlib/pp/0/pp.rbs +301 -0
  105. data/stdlib/{yaml → psych}/0/dbm.rbs +3 -3
  106. data/stdlib/psych/0/manifest.yaml +3 -0
  107. data/stdlib/psych/0/psych.rbs +391 -0
  108. data/stdlib/{yaml → psych}/0/store.rbs +2 -2
  109. data/stdlib/rdoc/0/code_object.rbs +55 -0
  110. data/stdlib/rdoc/0/comment.rbs +60 -0
  111. data/stdlib/rdoc/0/context.rbs +153 -0
  112. data/stdlib/rdoc/0/markup.rbs +119 -0
  113. data/stdlib/rdoc/0/parser.rbs +56 -0
  114. data/stdlib/rdoc/0/rdoc.rbs +0 -372
  115. data/stdlib/rdoc/0/ri.rbs +17 -0
  116. data/stdlib/rdoc/0/store.rbs +48 -0
  117. data/stdlib/rdoc/0/top_level.rbs +97 -0
  118. data/stdlib/socket/0/basic_socket.rbs +1 -1
  119. data/stdlib/socket/0/socket.rbs +1 -1
  120. data/stdlib/uri/0/common.rbs +1 -1
  121. data/stdlib/yaml/0/manifest.yaml +1 -2
  122. data/stdlib/yaml/0/yaml.rbs +1 -199
  123. metadata +46 -9
  124. data/sig/shims/pp.rbs +0 -3
  125. 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,8 +436,9 @@ 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
@@ -462,6 +466,30 @@ EOU
462
466
  builder = DefinitionBuilder.new(env: env)
463
467
  validator = Validator.new(env: env, resolver: Resolver::TypeNameResolver.new(env))
464
468
 
469
+ no_self_type_validator = ->(type) {
470
+ # @type var type: Types::t | MethodType
471
+ if type.has_self_type?
472
+ raise "#{type.location}: `self` type is not allowed in this context"
473
+ end
474
+ }
475
+
476
+ no_classish_type_validator = ->(type) {
477
+ # @type var type: Types::t | MethodType
478
+ if type.has_classish_type?
479
+ raise "#{type.location}: `instance` or `class` type is not allowed in this context"
480
+ end
481
+ }
482
+
483
+ void_type_context_validator = ->(type, allowed_here = false) {
484
+ # @type var type: Types::t | MethodType
485
+ if allowed_here
486
+ next if type.is_a?(Types::Bases::Void)
487
+ end
488
+ if type.with_nonreturn_void?
489
+ raise "#{type.location}: `void` type is only allowed in return type or generics parameter"
490
+ end
491
+ }
492
+
465
493
  env.class_decls.each do |name, decl|
466
494
  stdout.puts "Validating class/module definition: `#{name}`..."
467
495
  builder.build_instance(name).each_type do |type|
@@ -471,6 +499,29 @@ EOU
471
499
  validator.validate_type type, context: nil
472
500
  end
473
501
 
502
+ case decl
503
+ when Environment::ClassEntry
504
+ decl.decls.each do |decl|
505
+ if super_class = decl.decl.super_class
506
+ super_class.args.each do |arg|
507
+ void_type_context_validator[arg, true]
508
+ no_self_type_validator[arg]
509
+ no_classish_type_validator[arg]
510
+ end
511
+ end
512
+ end
513
+ when Environment::ModuleEntry
514
+ decl.decls.each do |decl|
515
+ decl.decl.self_types.each do |self_type|
516
+ self_type.args.each do |arg|
517
+ void_type_context_validator[arg, true]
518
+ no_self_type_validator[arg]
519
+ no_classish_type_validator[arg]
520
+ end
521
+ end
522
+ end
523
+ end
524
+
474
525
  d = decl.primary.decl
475
526
 
476
527
  validator.validate_type_params(
@@ -479,11 +530,36 @@ EOU
479
530
  location: d.location&.aref(:type_params)
480
531
  )
481
532
 
533
+ d.type_params.each do |param|
534
+ if ub = param.upper_bound
535
+ void_type_context_validator[ub]
536
+ no_self_type_validator[ub]
537
+ no_classish_type_validator[ub]
538
+ end
539
+ end
540
+
482
541
  decl.decls.each do |d|
483
542
  d.decl.each_member do |member|
484
543
  case member
485
544
  when AST::Members::MethodDefinition
486
545
  validator.validate_method_definition(member, type_name: name)
546
+ member.overloads.each do |ov|
547
+ void_type_context_validator[ov.method_type]
548
+ end
549
+ when AST::Members::Attribute
550
+ void_type_context_validator[member.type]
551
+ when AST::Members::Mixin
552
+ member.args.each do |arg|
553
+ no_self_type_validator[arg]
554
+ unless arg.is_a?(Types::Bases::Void)
555
+ void_type_context_validator[arg, true]
556
+ end
557
+ end
558
+ when AST::Members::Var
559
+ void_type_context_validator[member.type]
560
+ if member.is_a?(AST::Members::ClassVariable)
561
+ no_self_type_validator[member.type]
562
+ end
487
563
  end
488
564
  end
489
565
  end
@@ -510,6 +586,10 @@ EOU
510
586
  case member
511
587
  when AST::Members::MethodDefinition
512
588
  validator.validate_method_definition(member, type_name: name)
589
+ member.overloads.each do |ov|
590
+ void_type_context_validator[ov.method_type]
591
+ no_classish_type_validator[ov.method_type]
592
+ end
513
593
  end
514
594
  end
515
595
  end
@@ -518,11 +598,17 @@ EOU
518
598
  stdout.puts "Validating constant: `#{name}`..."
519
599
  validator.validate_type const.decl.type, context: const.context
520
600
  builder.ensure_namespace!(name.namespace, location: const.decl.location)
601
+ no_self_type_validator[const.decl.type]
602
+ no_classish_type_validator[const.decl.type]
603
+ void_type_context_validator[const.decl.type]
521
604
  end
522
605
 
523
606
  env.global_decls.each do |name, global|
524
607
  stdout.puts "Validating global: `#{name}`..."
525
608
  validator.validate_type global.decl.type, context: nil
609
+ no_self_type_validator[global.decl.type]
610
+ no_classish_type_validator[global.decl.type]
611
+ void_type_context_validator[global.decl.type]
526
612
  end
527
613
 
528
614
  env.type_alias_decls.each do |name, decl|
@@ -531,6 +617,9 @@ EOU
531
617
  validator.validate_type type, context: nil
532
618
  end
533
619
  validator.validate_type_alias(entry: decl)
620
+ no_self_type_validator[decl.decl.type]
621
+ no_classish_type_validator[decl.decl.type]
622
+ void_type_context_validator[decl.decl.type]
534
623
  end
535
624
  end
536
625
 
@@ -644,8 +733,10 @@ EOU
644
733
  require_libs = []
645
734
  relative_libs = []
646
735
  merge = false
736
+ todo = false
647
737
  owners_included = []
648
738
  outline = false
739
+ autoload = false
649
740
 
650
741
  OptionParser.new do |opts|
651
742
  opts.banner = <<EOU
@@ -671,26 +762,62 @@ EOU
671
762
  opts.on("--merge", "Merge generated prototype RBS with existing RBS") do
672
763
  merge = true
673
764
  end
765
+ opts.on("--todo", "Generates only undefined methods compared to objects") do
766
+ Warning.warn("Geneating prototypes with `--todo` option is experimental\n", category: :experimental)
767
+ todo = true
768
+ end
674
769
  opts.on("--method-owner CLASS", "Generate method prototypes if the owner of the method is [CLASS]") do |klass|
675
770
  owners_included << klass
676
771
  end
677
772
  opts.on("--outline", "Generates only module/class/constant declaration (no method definition)") do
678
773
  outline = true
679
774
  end
775
+ opts.on("--autoload", "Load all autoload path") do
776
+ autoload = true
777
+ end
680
778
  end.parse!(args)
681
779
 
682
780
  loader = options.loader()
683
781
  env = Environment.from_loader(loader).resolve_type_names
684
782
 
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")
783
+ # @type var autoloader: ^() { () -> void } -> void
784
+ autoloader = ->(&block) {
785
+ if autoload
786
+ hook = Module.new do
787
+ def autoload(name, path)
788
+ super
789
+ end
790
+ end
791
+ ::Module.prepend(hook)
792
+ ::Kernel.prepend(hook)
793
+
794
+ arguments = []
795
+ TracePoint.new(:call) do |tp|
796
+ base = tp.self.kind_of?(Module) ? tp.self : Kernel
797
+ name = (tp.binding or raise).local_variable_get(:name)
798
+ arguments << [base, name]
799
+ end.enable(target: hook.instance_method(:autoload), &block)
800
+
801
+ arguments.each do |(base, name)|
802
+ begin
803
+ base.const_get(name)
804
+ rescue LoadError, StandardError
805
+ end
806
+ end
807
+ else
808
+ block.call
809
+ end
810
+ }
811
+ autoloader.call do
812
+ require_libs.each do |lib|
813
+ require(lib)
814
+ end
815
+ relative_libs.each do |lib|
816
+ eval("require_relative(lib)", binding, "rbs")
817
+ end
691
818
  end
692
819
 
693
- runtime = Prototype::Runtime.new(patterns: args, env: env, merge: merge, owners_included: owners_included)
820
+ runtime = Prototype::Runtime.new(patterns: args, env: env, merge: merge, todo: todo, owners_included: owners_included)
694
821
  runtime.outline = outline
695
822
 
696
823
  decls = runtime.decls
@@ -827,7 +954,12 @@ EOU
827
954
  output_path = (output_dir + relative_path).sub_ext(".rbs")
828
955
 
829
956
  parser = new_parser[]
830
- parser.parse file_path.read()
957
+ begin
958
+ parser.parse file_path.read()
959
+ rescue SyntaxError
960
+ stdout.puts " ⚠️ Unable to parse due to SyntaxError: `#{file_path}`"
961
+ next
962
+ end
831
963
 
832
964
  if output_path.file?
833
965
  if force
@@ -1136,11 +1268,10 @@ EOB
1136
1268
  # A directory to install the downloaded RBSs
1137
1269
  path: .gem_rbs_collection
1138
1270
 
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
1271
+ # gems:
1272
+ # # If you want to avoid installing rbs files for gems, you can specify them here.
1273
+ # - name: GEM_NAME
1274
+ # ignore: true
1144
1275
  YAML
1145
1276
  stdout.puts "created: #{config_path}"
1146
1277
  when 'clean'
@@ -1259,5 +1390,9 @@ EOB
1259
1390
  end
1260
1391
  end
1261
1392
  end
1393
+
1394
+ def run_diff(argv, library_options)
1395
+ Diff.new(argv: argv, library_options: library_options, stdout: stdout, stderr: stderr).run
1396
+ end
1262
1397
  end
1263
1398
  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
@@ -7,7 +7,7 @@ module RBS
7
7
  include Base
8
8
 
9
9
  attr_reader :path, :full_path
10
-
10
+
11
11
  def initialize(path:, base_directory:)
12
12
  # TODO: resolve relative path from dir of rbs_collection.yaml
13
13
  @path = Pathname(path)
@@ -33,22 +33,24 @@ module RBS
33
33
  from = @full_path.join(name, version)
34
34
  gem_dir = dest.join(name, version)
35
35
 
36
+ colored_io = CLI::ColoredIO.new(stdout: stdout)
37
+
36
38
  case
37
39
  when gem_dir.symlink? && gem_dir.readlink == from
38
- stdout.puts "Using #{name}:#{version} (#{from})"
40
+ colored_io.puts "Using #{name}:#{version} (#{from})"
39
41
  when gem_dir.symlink?
40
42
  prev = gem_dir.readlink
41
43
  gem_dir.unlink
42
44
  _install(from, dest.join(name, version))
43
- stdout.puts "Updating #{name}:#{version} to #{from} from #{prev}"
45
+ colored_io.puts_green("Updating #{name}:#{version} to #{from} from #{prev}")
44
46
  when gem_dir.directory?
45
47
  # TODO: Show version of git source
46
48
  FileUtils.remove_entry_secure(gem_dir.to_s)
47
49
  _install(from, dest.join(name, version))
48
- stdout.puts "Updating #{name}:#{version} from git source"
50
+ colored_io.puts_green("Updating #{name}:#{version} from git source")
49
51
  when !gem_dir.exist?
50
52
  _install(from, dest.join(name, version))
51
- stdout.puts "Installing #{name}:#{version} (#{from})"
53
+ colored_io.puts_green("Installing #{name}:#{version} (#{from})")
52
54
  else
53
55
  raise
54
56
  end