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.
- checksums.yaml +4 -4
- data/.github/workflows/comments.yml +1 -1
- data/.github/workflows/ruby.yml +7 -2
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +134 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +21 -15
- data/README.md +11 -2
- data/Rakefile +10 -7
- data/Steepfile +7 -7
- data/core/basic_object.rbs +7 -7
- data/core/binding.rbs +3 -3
- data/core/builtin.rbs +171 -5
- data/core/constants.rbs +17 -17
- data/core/dir.rbs +3 -3
- data/core/encoding.rbs +434 -628
- data/core/enumerator.rbs +37 -0
- data/core/exception.rbs +11 -11
- data/core/false_class.rbs +5 -11
- data/core/fiber.rbs +5 -5
- data/core/file_test.rbs +28 -26
- data/core/kernel.rbs +900 -21
- data/core/marshal.rbs +24 -14
- data/core/match_data.rbs +8 -8
- data/core/math.rbs +57 -53
- data/core/method.rbs +3 -1
- data/core/module.rbs +38 -36
- data/core/nil_class.rbs +7 -13
- data/core/object.rbs +3 -966
- data/core/process.rbs +3 -3
- data/core/ractor.rbs +2 -2
- data/core/rb_config.rbs +64 -43
- data/core/regexp.rbs +3 -3
- data/core/set.rbs +3 -2
- data/core/signal.rbs +10 -4
- data/core/struct.rbs +1 -1
- data/core/thread.rbs +7 -7
- data/core/thread_group.rbs +9 -9
- data/core/true_class.rbs +5 -11
- data/core/unbound_method.rbs +56 -7
- data/core/warning.rbs +33 -0
- data/docs/collection.md +56 -6
- data/docs/data_and_struct.md +57 -0
- data/docs/stdlib.md +61 -2
- data/docs/syntax.md +123 -2
- data/ext/rbs_extension/constants.c +73 -72
- data/ext/rbs_extension/lexer.c +624 -569
- data/ext/rbs_extension/lexer.h +1 -0
- data/ext/rbs_extension/lexer.re +1 -0
- data/ext/rbs_extension/lexstate.c +1 -0
- data/ext/rbs_extension/parser.c +6 -0
- data/goodcheck.yml +2 -2
- data/lib/rbs/annotate/formatter.rb +13 -3
- data/lib/rbs/annotate/rdoc_source.rb +10 -1
- data/lib/rbs/cli/colored_io.rb +48 -0
- data/lib/rbs/cli/diff.rb +80 -0
- data/lib/rbs/cli.rb +169 -17
- data/lib/rbs/collection/config/lockfile.rb +0 -25
- data/lib/rbs/collection/config/lockfile_generator.rb +0 -6
- data/lib/rbs/collection/installer.rb +1 -1
- data/lib/rbs/collection/sources/git.rb +6 -4
- data/lib/rbs/collection/sources/local.rb +7 -5
- data/lib/rbs/diff.rb +121 -0
- data/lib/rbs/environment.rb +7 -4
- data/lib/rbs/method_type.rb +23 -0
- data/lib/rbs/prototype/rb.rb +2 -9
- data/lib/rbs/prototype/rbi.rb +1 -1
- data/lib/rbs/prototype/runtime/helpers.rb +59 -0
- data/lib/rbs/prototype/runtime/reflection.rb +19 -0
- data/lib/rbs/prototype/runtime/value_object_generator.rb +275 -0
- data/lib/rbs/prototype/runtime.rb +233 -153
- data/lib/rbs/resolver/constant_resolver.rb +1 -1
- data/lib/rbs/sorter.rb +144 -117
- data/lib/rbs/test/guaranteed.rb +31 -0
- data/lib/rbs/test/type_check.rb +4 -4
- data/lib/rbs/test.rb +3 -0
- data/lib/rbs/types.rb +184 -3
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +4 -4
- data/lib/rbs.rb +1 -0
- data/rbs.gemspec +1 -0
- data/sig/annotate/formatter.rbs +2 -2
- data/sig/annotate/rdoc_annotater.rbs +1 -1
- data/sig/cli/colored_io.rbs +15 -0
- data/sig/cli/diff.rbs +21 -0
- data/sig/cli.rbs +2 -0
- data/sig/collection/config/lockfile.rbs +0 -6
- data/sig/diff.rbs +23 -0
- data/sig/errors.rbs +1 -5
- data/sig/method_types.rbs +6 -0
- data/sig/prototype/runtime.rbs +166 -0
- data/sig/rdoc/rbs.rbs +4 -0
- data/sig/shims/bundler.rbs +5 -0
- data/sig/sorter.rbs +23 -5
- data/sig/types.rbs +29 -0
- data/stdlib/benchmark/0/benchmark.rbs +1 -1
- data/stdlib/cgi/0/core.rbs +2 -2
- data/stdlib/did_you_mean/0/did_you_mean.rbs +2 -2
- data/stdlib/digest/0/digest.rbs +1 -1
- data/stdlib/fileutils/0/fileutils.rbs +1 -1
- data/stdlib/forwardable/0/forwardable.rbs +4 -4
- data/stdlib/io-console/0/io-console.rbs +1 -1
- data/stdlib/json/0/json.rbs +37 -0
- data/stdlib/logger/0/logger.rbs +2 -2
- data/stdlib/net-http/0/manifest.yaml +1 -1
- data/stdlib/net-http/0/net-http.rbs +16 -63
- data/stdlib/net-protocol/0/manifest.yaml +2 -0
- data/stdlib/net-protocol/0/net-protocol.rbs +56 -0
- data/stdlib/net-smtp/0/manifest.yaml +2 -0
- data/stdlib/net-smtp/0/net-smtp.rbs +55 -0
- data/stdlib/open-uri/0/manifest.yaml +3 -0
- data/stdlib/open-uri/0/open-uri.rbs +341 -0
- data/stdlib/openssl/0/openssl.rbs +1 -1
- data/stdlib/pp/0/manifest.yaml +2 -0
- data/stdlib/pp/0/pp.rbs +301 -0
- data/stdlib/{yaml → psych}/0/dbm.rbs +3 -3
- data/stdlib/psych/0/manifest.yaml +3 -0
- data/stdlib/psych/0/psych.rbs +391 -0
- data/stdlib/{yaml → psych}/0/store.rbs +2 -2
- data/stdlib/rdoc/0/code_object.rbs +55 -0
- data/stdlib/rdoc/0/comment.rbs +60 -0
- data/stdlib/rdoc/0/context.rbs +153 -0
- data/stdlib/rdoc/0/markup.rbs +119 -0
- data/stdlib/rdoc/0/parser.rbs +56 -0
- data/stdlib/rdoc/0/rdoc.rbs +0 -372
- data/stdlib/rdoc/0/ri.rbs +17 -0
- data/stdlib/rdoc/0/store.rbs +48 -0
- data/stdlib/rdoc/0/top_level.rbs +97 -0
- data/stdlib/socket/0/basic_socket.rbs +1 -1
- data/stdlib/socket/0/socket.rbs +1 -1
- data/stdlib/uri/0/common.rbs +1 -1
- data/stdlib/yaml/0/manifest.yaml +1 -2
- data/stdlib/yaml/0/yaml.rbs +1 -199
- metadata +49 -7
- data/sig/shims/pp.rbs +0 -3
- data/sig/shims.rbs +0 -47
data/ext/rbs_extension/lexer.h
CHANGED
data/ext/rbs_extension/lexer.re
CHANGED
|
@@ -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])* ['];
|
data/ext/rbs_extension/parser.c
CHANGED
|
@@ -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`: (
|
|
16
|
+
- "def `send`: (interned arg0, *untyped arg1) -> untyped"
|
|
17
17
|
pass:
|
|
18
|
-
- "def `send`: (
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
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
|
|
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
|
data/lib/rbs/cli/diff.rb
ADDED
|
@@ -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
|
-
|
|
437
|
-
|
|
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
|
-
|
|
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
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
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))
|
|
@@ -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
|
-
|
|
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
|
-
|
|
59
|
+
colored_io.puts "Using #{format_config_entry(name, version)}"
|
|
58
60
|
else
|
|
59
|
-
|
|
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
|
-
|
|
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
|