rbs 3.2.2 → 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 +113 -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 +3 -3
- 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/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 +1 -1
- 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
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
53
|
+
colored_io.puts_green("Installing #{name}:#{version} (#{from})")
|
|
52
54
|
else
|
|
53
55
|
raise
|
|
54
56
|
end
|
data/lib/rbs/diff.rb
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RBS
|
|
4
|
+
class Diff
|
|
5
|
+
def initialize(type_name:, library_options:, after_path: [], before_path: [])
|
|
6
|
+
@type_name = type_name
|
|
7
|
+
@library_options = library_options
|
|
8
|
+
@after_path = after_path
|
|
9
|
+
@before_path = before_path
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def each_diff(&block)
|
|
13
|
+
return to_enum(:each_diff) unless block
|
|
14
|
+
|
|
15
|
+
before_instance_methods, before_singleton_methods, before_constant_children = build_methods(@before_path)
|
|
16
|
+
after_instance_methods, after_singleton_methods, after_constant_children = build_methods(@after_path)
|
|
17
|
+
|
|
18
|
+
each_diff_methods(:instance, before_instance_methods, after_instance_methods, &block)
|
|
19
|
+
each_diff_methods(:singleton, before_singleton_methods, after_singleton_methods, &block)
|
|
20
|
+
|
|
21
|
+
each_diff_constants(before_constant_children, after_constant_children, &block)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def each_diff_methods(kind, before_methods, after_methods)
|
|
27
|
+
all_keys = before_methods.keys.to_set + after_methods.keys.to_set
|
|
28
|
+
all_keys.each do |key|
|
|
29
|
+
before = definition_method_to_s(key, kind, before_methods[key]) or next
|
|
30
|
+
after = definition_method_to_s(key, kind, after_methods[key]) or next
|
|
31
|
+
next if before == after
|
|
32
|
+
|
|
33
|
+
yield before, after
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def each_diff_constants(before_constant_children, after_constant_children)
|
|
38
|
+
all_keys = before_constant_children.keys.to_set + after_constant_children.keys.to_set
|
|
39
|
+
all_keys.each do |key|
|
|
40
|
+
before = constant_to_s(before_constant_children[key]) or next
|
|
41
|
+
after = constant_to_s(after_constant_children[key]) or next
|
|
42
|
+
next if before == after
|
|
43
|
+
|
|
44
|
+
yield before, after
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def build_methods(path)
|
|
49
|
+
env = build_env(path)
|
|
50
|
+
builder = build_builder(env)
|
|
51
|
+
|
|
52
|
+
instance_methods = begin
|
|
53
|
+
builder.build_instance(@type_name).methods
|
|
54
|
+
rescue => e
|
|
55
|
+
RBS.logger.warn("#{path}: (#{e.class}) #{e.message}")
|
|
56
|
+
{}
|
|
57
|
+
end
|
|
58
|
+
singleton_methods = begin
|
|
59
|
+
builder.build_singleton(@type_name).methods
|
|
60
|
+
rescue => e
|
|
61
|
+
RBS.logger.warn("#{path}: (#{e.class}) #{e.message}")
|
|
62
|
+
{}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
constant_children = begin
|
|
66
|
+
constant_resolver = RBS::Resolver::ConstantResolver.new(builder: builder)
|
|
67
|
+
constant_resolver.children(@type_name)
|
|
68
|
+
rescue => e
|
|
69
|
+
RBS.logger.warn("#{path}: (#{e.class}) #{e.message}")
|
|
70
|
+
{}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
[ instance_methods, singleton_methods, constant_children ]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def build_env(path)
|
|
77
|
+
loader = @library_options.loader()
|
|
78
|
+
path&.each do |dir|
|
|
79
|
+
dir_pathname = Pathname(dir)
|
|
80
|
+
loader.add(path: dir_pathname)
|
|
81
|
+
|
|
82
|
+
manifest_pathname = dir_pathname / 'manifest.yaml'
|
|
83
|
+
if manifest_pathname.exist?
|
|
84
|
+
manifest = YAML.safe_load(manifest_pathname.read)
|
|
85
|
+
if manifest['dependencies']
|
|
86
|
+
manifest['dependencies'].each do |dependency|
|
|
87
|
+
loader.add(library: dependency['name'], version: nil)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
Environment.from_loader(loader)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build_builder(env)
|
|
96
|
+
DefinitionBuilder.new(env: env.resolve_type_names)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def definition_method_to_s(key, kind, definition_method)
|
|
100
|
+
if definition_method
|
|
101
|
+
prefix = kind == :instance ? "" : "self."
|
|
102
|
+
|
|
103
|
+
if definition_method.alias_of
|
|
104
|
+
"alias #{prefix}#{key} #{prefix}#{definition_method.alias_of.defs.first.member.name}"
|
|
105
|
+
else
|
|
106
|
+
"def #{prefix}#{key}: #{definition_method.method_types.join(" | ")}"
|
|
107
|
+
end
|
|
108
|
+
else
|
|
109
|
+
+"-"
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def constant_to_s(constant)
|
|
114
|
+
if constant
|
|
115
|
+
"#{constant.name.name}: #{constant.type}"
|
|
116
|
+
else
|
|
117
|
+
+"-"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
data/lib/rbs/environment.rb
CHANGED
|
@@ -441,7 +441,7 @@ module RBS
|
|
|
441
441
|
|
|
442
442
|
when AST::Declarations::Global
|
|
443
443
|
if entry = global_decls[decl.name]
|
|
444
|
-
raise DuplicatedDeclarationError.new(name, decl, entry.decl)
|
|
444
|
+
raise DuplicatedDeclarationError.new(decl.name, decl, entry.decl)
|
|
445
445
|
end
|
|
446
446
|
|
|
447
447
|
global_decls[decl.name] = GlobalEntry.new(name: decl.name, decl: decl, outer: outer)
|
data/lib/rbs/method_type.rb
CHANGED
|
@@ -86,6 +86,9 @@ module RBS
|
|
|
86
86
|
type.each_type(&block)
|
|
87
87
|
self.block&.yield_self do |b|
|
|
88
88
|
b.type.each_type(&block)
|
|
89
|
+
if b.self_type
|
|
90
|
+
yield b.self_type
|
|
91
|
+
end
|
|
89
92
|
end
|
|
90
93
|
else
|
|
91
94
|
enum_for :each_type
|
|
@@ -114,5 +117,25 @@ module RBS
|
|
|
114
117
|
def type_param_names
|
|
115
118
|
type_params.map(&:name)
|
|
116
119
|
end
|
|
120
|
+
|
|
121
|
+
def has_self_type?
|
|
122
|
+
each_type.any? {|type| type.has_self_type? }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def has_classish_type?
|
|
126
|
+
each_type.any? {|type| type.has_classish_type? }
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def with_nonreturn_void?
|
|
130
|
+
if type.with_nonreturn_void?
|
|
131
|
+
true
|
|
132
|
+
else
|
|
133
|
+
if block = block()
|
|
134
|
+
block.type.with_nonreturn_void? || block.self_type&.with_nonreturn_void? || false
|
|
135
|
+
else
|
|
136
|
+
false
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
117
140
|
end
|
|
118
141
|
end
|
data/lib/rbs/prototype/rb.rb
CHANGED
|
@@ -89,8 +89,7 @@ module RBS
|
|
|
89
89
|
body = "\n" if body.empty?
|
|
90
90
|
|
|
91
91
|
comment = AST::Comment.new(string: body, location: nil)
|
|
92
|
-
if
|
|
93
|
-
hash[line - 1] = nil
|
|
92
|
+
if prev_comment = hash.delete(line - 1)
|
|
94
93
|
hash[line] = AST::Comment.new(string: prev_comment.string + comment.string,
|
|
95
94
|
location: nil)
|
|
96
95
|
else
|
|
@@ -362,13 +361,7 @@ module RBS
|
|
|
362
361
|
end
|
|
363
362
|
|
|
364
363
|
when :ITER
|
|
365
|
-
|
|
366
|
-
case method_name
|
|
367
|
-
when :refine
|
|
368
|
-
# ignore
|
|
369
|
-
else
|
|
370
|
-
process_children(node, decls: decls, comments: comments, context: context)
|
|
371
|
-
end
|
|
364
|
+
# ignore
|
|
372
365
|
|
|
373
366
|
when :CDECL
|
|
374
367
|
const_name = case
|
data/lib/rbs/prototype/rbi.rb
CHANGED
|
@@ -246,7 +246,7 @@ module RBS
|
|
|
246
246
|
end
|
|
247
247
|
end
|
|
248
248
|
value_node = node.children.last
|
|
249
|
-
type = if value_node.type == :CALL && value_node.children[1] == :let
|
|
249
|
+
type = if value_node && value_node.type == :CALL && value_node.children[1] == :let
|
|
250
250
|
type_node = each_arg(value_node.children[2]).to_a[1]
|
|
251
251
|
type_of type_node, variables: current_module&.type_params || []
|
|
252
252
|
else
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RBS
|
|
4
|
+
module Prototype
|
|
5
|
+
class Runtime
|
|
6
|
+
module Helpers
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
# Returns the exact name & not compactly declared name
|
|
10
|
+
def only_name(mod)
|
|
11
|
+
# No nil check because this method is invoked after checking if the module exists
|
|
12
|
+
const_name!(mod).split(/::/).last or raise # (A::B::C) => C
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def const_name!(const)
|
|
16
|
+
const_name(const) or raise
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def const_name(const)
|
|
20
|
+
@module_name_method ||= Module.instance_method(:name)
|
|
21
|
+
name = @module_name_method.bind(const).call
|
|
22
|
+
return nil unless name
|
|
23
|
+
|
|
24
|
+
begin
|
|
25
|
+
deprecated, Warning[:deprecated] = Warning[:deprecated], false
|
|
26
|
+
Object.const_get(name)
|
|
27
|
+
rescue NameError
|
|
28
|
+
# Should generate const name if anonymous or internal module (e.g. NameError::message)
|
|
29
|
+
nil
|
|
30
|
+
else
|
|
31
|
+
name
|
|
32
|
+
ensure
|
|
33
|
+
Warning[:deprecated] = deprecated
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def to_type_name(name, full_name: false)
|
|
38
|
+
*prefix, last = name.split(/::/)
|
|
39
|
+
|
|
40
|
+
last or raise
|
|
41
|
+
|
|
42
|
+
if full_name
|
|
43
|
+
if prefix.empty?
|
|
44
|
+
TypeName.new(name: last.to_sym, namespace: Namespace.empty)
|
|
45
|
+
else
|
|
46
|
+
TypeName.new(name: last.to_sym, namespace: Namespace.parse(prefix.join("::")))
|
|
47
|
+
end
|
|
48
|
+
else
|
|
49
|
+
TypeName.new(name: last.to_sym, namespace: Namespace.empty)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def untyped
|
|
54
|
+
@untyped ||= Types::Bases::Any.new(location: nil)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RBS
|
|
4
|
+
module Prototype
|
|
5
|
+
class Runtime
|
|
6
|
+
module Reflection
|
|
7
|
+
def self.object_class(value)
|
|
8
|
+
@object_class ||= Object.instance_method(:class)
|
|
9
|
+
@object_class.bind_call(value)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.constants_of(mod, inherit = true)
|
|
13
|
+
@constants_of ||= Module.instance_method(:constants)
|
|
14
|
+
@constants_of.bind_call(mod, inherit)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'helpers'
|
|
4
|
+
|
|
5
|
+
module RBS
|
|
6
|
+
module Prototype
|
|
7
|
+
class Runtime
|
|
8
|
+
class ValueObjectBase
|
|
9
|
+
include Helpers
|
|
10
|
+
|
|
11
|
+
def initialize(target_class)
|
|
12
|
+
@target_class = target_class
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def build_decl
|
|
16
|
+
decl = AST::Declarations::Class.new(
|
|
17
|
+
name: to_type_name(only_name(@target_class)),
|
|
18
|
+
type_params: [],
|
|
19
|
+
super_class: build_super_class,
|
|
20
|
+
members: [],
|
|
21
|
+
annotations: [],
|
|
22
|
+
location: nil,
|
|
23
|
+
comment: nil
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
add_decl_members(decl)
|
|
27
|
+
|
|
28
|
+
decl
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
# def self.members: () -> [ :foo, :bar ]
|
|
34
|
+
# def members: () -> [ :foo, :bar ]
|
|
35
|
+
def build_s_members
|
|
36
|
+
[:singleton, :instance].map do |kind|
|
|
37
|
+
AST::Members::MethodDefinition.new(
|
|
38
|
+
name: :members,
|
|
39
|
+
overloads: [
|
|
40
|
+
AST::Members::MethodDefinition::Overload.new(
|
|
41
|
+
annotations: [],
|
|
42
|
+
method_type: MethodType.new(
|
|
43
|
+
type: Types::Function.empty(
|
|
44
|
+
Types::Tuple.new(
|
|
45
|
+
types: @target_class.members.map do |member|
|
|
46
|
+
if member.to_s.ascii_only?
|
|
47
|
+
Types::Literal.new(literal: member, location: nil)
|
|
48
|
+
else
|
|
49
|
+
BuiltinNames::Symbol.instance_type
|
|
50
|
+
end
|
|
51
|
+
end,
|
|
52
|
+
location: nil
|
|
53
|
+
)
|
|
54
|
+
),
|
|
55
|
+
type_params: [],
|
|
56
|
+
block: nil,
|
|
57
|
+
location: nil,
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
],
|
|
61
|
+
kind: kind,
|
|
62
|
+
location: nil,
|
|
63
|
+
comment: nil,
|
|
64
|
+
annotations: [],
|
|
65
|
+
overloading: false,
|
|
66
|
+
visibility: nil
|
|
67
|
+
)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# attr_accessor foo: untyped
|
|
72
|
+
def build_member_accessors(ast_members_class)
|
|
73
|
+
@target_class.members.map do |member|
|
|
74
|
+
ast_members_class.new(
|
|
75
|
+
name: member,
|
|
76
|
+
ivar_name: nil,
|
|
77
|
+
type: untyped,
|
|
78
|
+
kind: :instance,
|
|
79
|
+
location: nil,
|
|
80
|
+
comment: nil,
|
|
81
|
+
annotations: []
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
class StructGenerator < ValueObjectBase
|
|
88
|
+
def self.generatable?(target)
|
|
89
|
+
return false unless target < Struct
|
|
90
|
+
# Avoid direct inherited class like `class Option < Struct`
|
|
91
|
+
return false unless target.respond_to?(:members)
|
|
92
|
+
|
|
93
|
+
true
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
CAN_CALL_KEYWORD_INIT_P = Struct.new(:tmp).respond_to?(:keyword_init?)
|
|
99
|
+
|
|
100
|
+
def build_super_class
|
|
101
|
+
AST::Declarations::Class::Super.new(name: TypeName("::Struct"), args: [untyped], location: nil)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def add_decl_members(decl)
|
|
105
|
+
decl.members.concat build_s_new
|
|
106
|
+
decl.members.concat build_s_keyword_init_p
|
|
107
|
+
decl.members.concat build_s_members
|
|
108
|
+
decl.members.concat build_member_accessors(AST::Members::AttrAccessor)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# def self.new: (?untyped foo, ?untyped bar) -> instance
|
|
112
|
+
# | (?foo: untyped, ?bar: untyped) -> instance
|
|
113
|
+
def build_s_new
|
|
114
|
+
[:new, :[]].map do |name|
|
|
115
|
+
new_overloads = []
|
|
116
|
+
|
|
117
|
+
if CAN_CALL_KEYWORD_INIT_P
|
|
118
|
+
case @target_class.keyword_init?
|
|
119
|
+
when false
|
|
120
|
+
new_overloads << build_overload_for_positional_arguments
|
|
121
|
+
when true
|
|
122
|
+
new_overloads << build_overload_for_keyword_arguments
|
|
123
|
+
when nil
|
|
124
|
+
new_overloads << build_overload_for_positional_arguments
|
|
125
|
+
new_overloads << build_overload_for_keyword_arguments
|
|
126
|
+
else
|
|
127
|
+
raise
|
|
128
|
+
end
|
|
129
|
+
else
|
|
130
|
+
new_overloads << build_overload_for_positional_arguments
|
|
131
|
+
new_overloads << build_overload_for_keyword_arguments
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
AST::Members::MethodDefinition.new(
|
|
135
|
+
name: name,
|
|
136
|
+
overloads: new_overloads,
|
|
137
|
+
kind: :singleton,
|
|
138
|
+
location: nil,
|
|
139
|
+
comment: nil,
|
|
140
|
+
annotations: [],
|
|
141
|
+
overloading: false,
|
|
142
|
+
visibility: nil
|
|
143
|
+
)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def build_overload_for_positional_arguments
|
|
148
|
+
AST::Members::MethodDefinition::Overload.new(
|
|
149
|
+
annotations: [],
|
|
150
|
+
method_type: MethodType.new(
|
|
151
|
+
type: Types::Function.empty(Types::Bases::Instance.new(location: nil)).update(
|
|
152
|
+
optional_positionals: @target_class.members.map { |m| Types::Function::Param.new(name: m, type: untyped) },
|
|
153
|
+
),
|
|
154
|
+
type_params: [],
|
|
155
|
+
block: nil,
|
|
156
|
+
location: nil,
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def build_overload_for_keyword_arguments
|
|
162
|
+
AST::Members::MethodDefinition::Overload.new(
|
|
163
|
+
annotations: [],
|
|
164
|
+
method_type: MethodType.new(
|
|
165
|
+
type: Types::Function.empty(Types::Bases::Instance.new(location: nil)).update(
|
|
166
|
+
optional_keywords: @target_class.members.to_h { |m| [m, Types::Function::Param.new(name: nil, type: untyped)] },
|
|
167
|
+
),
|
|
168
|
+
type_params: [],
|
|
169
|
+
block: nil,
|
|
170
|
+
location: nil,
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# def self.keyword_init?: () -> bool?
|
|
176
|
+
def build_s_keyword_init_p
|
|
177
|
+
return [] unless CAN_CALL_KEYWORD_INIT_P
|
|
178
|
+
|
|
179
|
+
return_type = @target_class.keyword_init?.nil? \
|
|
180
|
+
? Types::Bases::Nil.new(location: nil)
|
|
181
|
+
: Types::Literal.new(literal: @target_class.keyword_init?, location: nil)
|
|
182
|
+
type = Types::Function.empty(return_type)
|
|
183
|
+
|
|
184
|
+
[
|
|
185
|
+
AST::Members::MethodDefinition.new(
|
|
186
|
+
name: :keyword_init?,
|
|
187
|
+
overloads: [
|
|
188
|
+
AST::Members::MethodDefinition::Overload.new(
|
|
189
|
+
annotations: [],
|
|
190
|
+
method_type: MethodType.new(
|
|
191
|
+
type: type,
|
|
192
|
+
type_params: [],
|
|
193
|
+
block: nil,
|
|
194
|
+
location: nil,
|
|
195
|
+
)
|
|
196
|
+
)
|
|
197
|
+
],
|
|
198
|
+
kind: :singleton,
|
|
199
|
+
location: nil,
|
|
200
|
+
comment: nil,
|
|
201
|
+
annotations: [],
|
|
202
|
+
overloading: false,
|
|
203
|
+
visibility: nil
|
|
204
|
+
)
|
|
205
|
+
]
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
class DataGenerator < ValueObjectBase
|
|
210
|
+
def self.generatable?(target)
|
|
211
|
+
return false unless RUBY_VERSION >= '3.2'
|
|
212
|
+
return false unless target < Data
|
|
213
|
+
# Avoid direct inherited class like `class Option < Data`
|
|
214
|
+
return false unless target.respond_to?(:members)
|
|
215
|
+
|
|
216
|
+
true
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
private
|
|
220
|
+
|
|
221
|
+
def build_super_class
|
|
222
|
+
AST::Declarations::Class::Super.new(name: TypeName("::Data"), args: [], location: nil)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def add_decl_members(decl)
|
|
226
|
+
decl.members.concat build_s_new
|
|
227
|
+
decl.members.concat build_s_members
|
|
228
|
+
decl.members.concat build_member_accessors(AST::Members::AttrReader)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
# def self.new: (untyped foo, untyped bar) -> instance
|
|
232
|
+
# | (foo: untyped, bar: untyped) -> instance
|
|
233
|
+
def build_s_new
|
|
234
|
+
[:new, :[]].map do |name|
|
|
235
|
+
new_overloads = []
|
|
236
|
+
|
|
237
|
+
new_overloads << AST::Members::MethodDefinition::Overload.new(
|
|
238
|
+
annotations: [],
|
|
239
|
+
method_type: MethodType.new(
|
|
240
|
+
type: Types::Function.empty(Types::Bases::Instance.new(location: nil)).update(
|
|
241
|
+
required_positionals: @target_class.members.map { |m| Types::Function::Param.new(name: m, type: untyped) },
|
|
242
|
+
),
|
|
243
|
+
type_params: [],
|
|
244
|
+
block: nil,
|
|
245
|
+
location: nil,
|
|
246
|
+
)
|
|
247
|
+
)
|
|
248
|
+
new_overloads << AST::Members::MethodDefinition::Overload.new(
|
|
249
|
+
annotations: [],
|
|
250
|
+
method_type: MethodType.new(
|
|
251
|
+
type: Types::Function.empty(Types::Bases::Instance.new(location: nil)).update(
|
|
252
|
+
required_keywords: @target_class.members.to_h { |m| [m, Types::Function::Param.new(name: nil, type: untyped)] },
|
|
253
|
+
),
|
|
254
|
+
type_params: [],
|
|
255
|
+
block: nil,
|
|
256
|
+
location: nil,
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
AST::Members::MethodDefinition.new(
|
|
261
|
+
name: name,
|
|
262
|
+
overloads: new_overloads,
|
|
263
|
+
kind: :singleton,
|
|
264
|
+
location: nil,
|
|
265
|
+
comment: nil,
|
|
266
|
+
annotations: [],
|
|
267
|
+
overloading: false,
|
|
268
|
+
visibility: nil
|
|
269
|
+
)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
end
|