rbs-dynamic 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/Gemfile +10 -0
- data/README.md +357 -0
- data/Rakefile +8 -0
- data/exe/rbs-dynamic +5 -0
- data/lib/bs/dynamic/trace.rb +1 -0
- data/lib/rbs/dynamic/builder/methods.rb +144 -0
- data/lib/rbs/dynamic/builder/types.rb +194 -0
- data/lib/rbs/dynamic/builder.rb +216 -0
- data/lib/rbs/dynamic/cli.rb +38 -0
- data/lib/rbs/dynamic/config.rb +67 -0
- data/lib/rbs/dynamic/converter/called_method_to_sigunature.rb +78 -0
- data/lib/rbs/dynamic/converter/called_method_to_with_interface.rb +44 -0
- data/lib/rbs/dynamic/converter/trace_to_rbs.rb +144 -0
- data/lib/rbs/dynamic/refine/basic_object_with_kernel.rb +11 -0
- data/lib/rbs/dynamic/refine/each_called_method.rb +34 -0
- data/lib/rbs/dynamic/refine/signature_merger.rb +175 -0
- data/lib/rbs/dynamic/refine/trace_point.rb +211 -0
- data/lib/rbs/dynamic/trace.rb +30 -0
- data/lib/rbs/dynamic/tracer/called_method.rb +256 -0
- data/lib/rbs/dynamic/tracer.rb +11 -0
- data/lib/rbs/dynamic/version.rb +7 -0
- data/lib/rbs/dynamic.rb +49 -0
- data/rbs-dynamic.gemspec +38 -0
- data/sample/csv/sample.rb +17 -0
- data/sample/fizzbuzz/sample.rb +36 -0
- data/sample/fizzbuzz2/sample.rb +66 -0
- data/sig/rbs/dynamic.rbs +6 -0
- metadata +101 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbs"
|
4
|
+
require_relative "../builder.rb"
|
5
|
+
require_relative "../refine/each_called_method.rb"
|
6
|
+
require_relative "./called_method_to_sigunature.rb"
|
7
|
+
require_relative "./called_method_to_with_interface.rb"
|
8
|
+
|
9
|
+
module RBS module Dynamic module Converter
|
10
|
+
class TraceToRBS
|
11
|
+
using RBS::Dynamic::Refine::EachCalledMethod
|
12
|
+
using RBS::Dynamic::Refine::TracePoint::ToRBSType
|
13
|
+
using CalledMethodToMethodSigunature
|
14
|
+
using CalledMethodToWithInterface
|
15
|
+
|
16
|
+
using Module.new {
|
17
|
+
refine Module do
|
18
|
+
def constants_wit_rbs_type(...)
|
19
|
+
constants(...)
|
20
|
+
# Except to ARGF.class
|
21
|
+
.filter_map { |name| [name, const_get(name).to_rbs_type.except_value] if const_get(name).class.name =~ /^\w+$/ }
|
22
|
+
.to_h
|
23
|
+
end
|
24
|
+
|
25
|
+
def include_prepend_modules
|
26
|
+
ancestors = Class === self ? self.ancestors.take_while { _1 != self.superclass } : self.ancestors
|
27
|
+
[ancestors.take_while { _1 != self }.reverse, ancestors.drop_while { _1 != self }.drop(1).reverse]
|
28
|
+
end
|
29
|
+
|
30
|
+
# M1::M2::X => [M1, M1::M2, M1::M2::X]
|
31
|
+
def namespace_paths
|
32
|
+
name.split("::").inject([]) { |result, scope|
|
33
|
+
result << Object.const_get("#{result.last}::#{scope}")
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
}
|
38
|
+
|
39
|
+
attr_reader :called_methods
|
40
|
+
|
41
|
+
def initialize(called_methods)
|
42
|
+
@called_methods = called_methods
|
43
|
+
end
|
44
|
+
|
45
|
+
def convert(
|
46
|
+
root_path: nil,
|
47
|
+
except_build_members: [],
|
48
|
+
include_method_location: false,
|
49
|
+
method_defined_calssses: %i(defined_class receiver_class),
|
50
|
+
use_literal_type: false,
|
51
|
+
with_literal_type: false,
|
52
|
+
use_interface: false,
|
53
|
+
use_interface_method_argument: false,
|
54
|
+
target_classname_pattern: /.*/,
|
55
|
+
ignore_classname_pattern: nil
|
56
|
+
)
|
57
|
+
called_methods_ = called_methods.each_called_method.reject { _1[:block?] }
|
58
|
+
klass_with_called_methods = [
|
59
|
+
if method_defined_calssses.include? :defined_class
|
60
|
+
called_methods_.group_by { _1[:receiver_defined_class] }
|
61
|
+
end,
|
62
|
+
if method_defined_calssses.include? :receiver_class
|
63
|
+
called_methods_.group_by { _1[:receiver_class] }
|
64
|
+
end
|
65
|
+
]
|
66
|
+
.compact
|
67
|
+
.inject { |result, it| result.merge(it) { |key, a, b| a + b } }
|
68
|
+
.select { |klass, _| Module === klass }.reject { |klass, _| klass.nil? || klass.singleton_class? }
|
69
|
+
.to_h { |klass, called_methods|
|
70
|
+
[klass, called_methods.uniq { [_1[:method_id], _1[:arguments], _1[:return_value_class], _1[:called_path], _1[:called_lineno]] }.group_by { _1[:method_id] }]
|
71
|
+
}
|
72
|
+
klasses = klass_with_called_methods.keys
|
73
|
+
|
74
|
+
# Modules / classes that are defined but methods are not called are also defined in RBS
|
75
|
+
non_called_klass = klass_with_called_methods.keys.map { _1.namespace_paths }.flatten \
|
76
|
+
+ klasses.filter_map { Class === _1 && Object != _1.superclass && BasicObject != _1.superclass && _1.superclass } \
|
77
|
+
- klasses
|
78
|
+
|
79
|
+
# non_called_klass += non_called_klass.map { _1.include_prepend_modules }.flatten
|
80
|
+
klass_with_called_methods = non_called_klass.to_h { [_1, {}] }.merge(klass_with_called_methods)
|
81
|
+
# klass_with_called_methods = klass_with_called_methods.merge(non_called_klass.to_h { [_1, {}] })
|
82
|
+
|
83
|
+
# klass_with_called_methods.sort_by { |klass, _| klass.name }.to_h { |klass, name_with_called_methods|
|
84
|
+
klass_with_called_methods
|
85
|
+
.select { |klass, _| target_classname_pattern && target_classname_pattern =~ klass.name }
|
86
|
+
.reject { |klass, _| ignore_classname_pattern && ignore_classname_pattern =~ klass.name }
|
87
|
+
.to_h { |klass, name_with_called_methods|
|
88
|
+
builder = Class === klass ? RBS::Dynamic::Builder::Class.new(klass) : RBS::Dynamic::Builder::Module.new(klass)
|
89
|
+
|
90
|
+
# Add prepend / include
|
91
|
+
# MEMO: Add only the traced module to RBS
|
92
|
+
# TODO: Predefined RBS modules (e.g. core module) other than Trace are not mixin
|
93
|
+
klass.include_prepend_modules.tap { |prepended, included|
|
94
|
+
# prepend
|
95
|
+
prepended.each { |mod|
|
96
|
+
builder.add_prepended_module(mod) if klasses.include? mod
|
97
|
+
} unless except_build_members.include? :prepended_modules
|
98
|
+
|
99
|
+
# include
|
100
|
+
included.each { |mod|
|
101
|
+
builder.add_inclued_module(mod) if klasses.include? mod
|
102
|
+
} unless except_build_members.include? :inclued_modules
|
103
|
+
}
|
104
|
+
|
105
|
+
# Add extend
|
106
|
+
klass.singleton_class.include_prepend_modules.flatten.each { |mod|
|
107
|
+
builder.add_extended_module(mod) if klasses.include? mod
|
108
|
+
} unless except_build_members.include? :extended_modules
|
109
|
+
|
110
|
+
# Add constant variable
|
111
|
+
klass.constants_wit_rbs_type(false).each { |name, type|
|
112
|
+
builder.add_constant_variable(name, type) if name == name.upcase
|
113
|
+
} unless except_build_members.include? :constant_variables
|
114
|
+
|
115
|
+
# Add instance variable
|
116
|
+
name_with_called_methods.map { |_, called_methods| called_methods.map { _1[:instance_variables_rbs_type] } }.flatten.each { |instance_variables_rbs_type|
|
117
|
+
instance_variables_rbs_type.each { |name, type|
|
118
|
+
# TODO: Support use_literal_type and with_literal_type
|
119
|
+
builder.add_instance_variable(name, type.except_value)
|
120
|
+
}
|
121
|
+
} unless except_build_members.include? :instance_variables
|
122
|
+
|
123
|
+
# Add method and singleton method
|
124
|
+
name_with_called_methods.each.with_index(1) { |(name, called_methods), i|
|
125
|
+
called_methods.each.with_index(1) { |called_method, j|
|
126
|
+
if use_interface_method_argument
|
127
|
+
called_method, sub_interfaces = called_method.to_with_interface(defined_interfaces: builder.interface_members)
|
128
|
+
sub_interfaces.map { builder.add_interface_members(_1) }
|
129
|
+
end
|
130
|
+
|
131
|
+
signature = called_method.method_sigunature(root_path: root_path, include_location: include_method_location, use_literal_type: use_literal_type, with_literal_type: with_literal_type)
|
132
|
+
if called_method[:singleton_method?]
|
133
|
+
builder.add_singleton_method(name, **signature) unless except_build_members.include? :singleton_methods
|
134
|
+
else
|
135
|
+
builder.add_method(name, **signature) unless except_build_members.include? :methods
|
136
|
+
end
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
[klass, builder.build]
|
141
|
+
}
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end end end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RBS module Dynamic module Refine
|
4
|
+
module EachCalledMethod
|
5
|
+
refine Hash do
|
6
|
+
def each_called_method(&block)
|
7
|
+
return Enumerator.new { |y|
|
8
|
+
each_called_method { |it| y << it }
|
9
|
+
} unless block
|
10
|
+
|
11
|
+
self[:called_methods].each { |called_method|
|
12
|
+
block.call(called_method)
|
13
|
+
if Hash === called_method
|
14
|
+
called_method.each_called_method(&block)
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
refine Array do
|
21
|
+
using EachCalledMethod
|
22
|
+
|
23
|
+
def each_called_method(&block)
|
24
|
+
return Enumerator.new { |y|
|
25
|
+
each_called_method { |it| y << it }
|
26
|
+
} unless block
|
27
|
+
each { |called_method|
|
28
|
+
block.call(called_method)
|
29
|
+
called_method.each_called_method(&block)
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end end end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
|
4
|
+
require_relative "../builder/types.rb"
|
5
|
+
|
6
|
+
module RBS module Dynamic module Refine
|
7
|
+
module SignatureMerger
|
8
|
+
module AsA
|
9
|
+
refine Object do
|
10
|
+
def as_a
|
11
|
+
[self]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
refine Array do
|
16
|
+
def as_a
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
using AsA
|
22
|
+
|
23
|
+
using Module.new {
|
24
|
+
using RBS::Dynamic::Builder::Types::ToRBSType
|
25
|
+
|
26
|
+
refine Array do
|
27
|
+
# p [1, 2].zip([3, 4]) # => [[1, 3], [2, 4]]
|
28
|
+
# p [1, 2].zip([3, 4, 5, 6]) # => [[1, 3], [2, 4]]
|
29
|
+
# p [1, 2].zip_fill([3, 4, 5, 6]) # => [[1, 3], [2, 4], [nil, 5], [nil, 6]]
|
30
|
+
def zip_fill(other, val = nil)
|
31
|
+
if count < other.count
|
32
|
+
fill(val, count...other.count).zip(other)
|
33
|
+
else
|
34
|
+
zip(other)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def union_params_rbs_type
|
39
|
+
map { |a, b|
|
40
|
+
a ||= {}
|
41
|
+
b ||= {}
|
42
|
+
type = a.fetch(:type, []).as_a + b.fetch(:type, []).as_a
|
43
|
+
{ name: (a[:name] || b[:name]), type: type.map { _1.to_rbs_type }.uniq }
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def equal_type(other)
|
48
|
+
count == Array(other).count && zip(Array(other)).all? { |a, b| a.equal_type(b) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
refine Hash do
|
53
|
+
def equal_type(other)
|
54
|
+
rhs_type = Integer === self[:type] ? [Integer]
|
55
|
+
: String === self[:type] ? [String]
|
56
|
+
: Symbol === self[:type] ? [Symbol]
|
57
|
+
: Array == self[:type] ? [Array] # except args
|
58
|
+
: Hash == self[:type] ? [Hash] # except args
|
59
|
+
: [self[:type], self[:args]]
|
60
|
+
|
61
|
+
lhs_type = Integer === other[:type] ? [Integer]
|
62
|
+
: String === other[:type] ? [String]
|
63
|
+
: Symbol === other[:type] ? [Symbol]
|
64
|
+
: Array == other[:type] ? [Array] # except args
|
65
|
+
: Hash == other[:type] ? [Hash] # except args
|
66
|
+
: [other[:type], other[:args]]
|
67
|
+
|
68
|
+
rhs_type == lhs_type
|
69
|
+
end
|
70
|
+
|
71
|
+
def params
|
72
|
+
slice(:required_positionals, :optional_positionals, :rest_positionals, :required_keywords, :optional_keywords)
|
73
|
+
end
|
74
|
+
|
75
|
+
def params_with_types
|
76
|
+
params.to_h { |k, sigs| [k, sigs&.map { _1[:type].to_rbs_type }] }
|
77
|
+
end
|
78
|
+
|
79
|
+
def param_names_with_num
|
80
|
+
params.to_h { |key, val| [key, val.count] }
|
81
|
+
end
|
82
|
+
|
83
|
+
def return_type
|
84
|
+
fetch(:return_type, []).as_a.map { _1.to_rbs_type }
|
85
|
+
end
|
86
|
+
|
87
|
+
def param_mergeable?(other)
|
88
|
+
param_names_with_num == other.param_names_with_num &&
|
89
|
+
return_type == other.return_type
|
90
|
+
end
|
91
|
+
|
92
|
+
def return_type_mergeable?(other)
|
93
|
+
params_with_types == other.params_with_types
|
94
|
+
end
|
95
|
+
|
96
|
+
def merge_params!(other)
|
97
|
+
other.params.merge(self) { |key, other, current|
|
98
|
+
current.zip_fill(other, {}).union_params_rbs_type
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def merge_params(other)
|
103
|
+
return unless param_mergeable?(other)
|
104
|
+
merge_params!(other)
|
105
|
+
end
|
106
|
+
|
107
|
+
def merge_return_type!(other)
|
108
|
+
merge(return_type: (return_type + other.return_type).uniq)
|
109
|
+
end
|
110
|
+
|
111
|
+
def merge_return_type(other)
|
112
|
+
return unless return_type_mergeable?(other)
|
113
|
+
merge_return_type!(other)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
}
|
117
|
+
|
118
|
+
refine Object do
|
119
|
+
def merge_sig(*)
|
120
|
+
nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
refine Array do
|
125
|
+
def merge_sig(other)
|
126
|
+
(self + other).zip_sig
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
refine Hash do
|
131
|
+
def merge_sig(other)
|
132
|
+
return unless Hash === other
|
133
|
+
|
134
|
+
block_merged = self[:block]&.merge_sig(other[:block])
|
135
|
+
|
136
|
+
if merged = merge_return_type(other)
|
137
|
+
merged.merge(block: block_merged)
|
138
|
+
elsif merged = merge_params(other)
|
139
|
+
merged.merge(block: block_merged)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def merge_sig!(other)
|
144
|
+
return unless Hash === other
|
145
|
+
|
146
|
+
merge_params!(other).merge_return_type!(other)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
refine Array do
|
151
|
+
def push_merge_sig(other)
|
152
|
+
each.with_index { |sig, i|
|
153
|
+
merged = sig.merge_sig(other)
|
154
|
+
if merged
|
155
|
+
self[i] = merged
|
156
|
+
return self
|
157
|
+
end
|
158
|
+
}
|
159
|
+
push(other)
|
160
|
+
end
|
161
|
+
|
162
|
+
def zip_sig
|
163
|
+
inject([]) { |result, sig|
|
164
|
+
result.push_merge_sig(sig)
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
168
|
+
def zip_sig!
|
169
|
+
drop(1).inject(first) { |result, sig|
|
170
|
+
result.merge_sig!(sig)
|
171
|
+
}
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end end end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "./basic_object_with_kernel.rb"
|
4
|
+
|
5
|
+
module RBS module Dynamic module Refine
|
6
|
+
module TracePoint
|
7
|
+
using RBS::Dynamic::Refine::BasicObjectWithKernel
|
8
|
+
|
9
|
+
module ToRBSType
|
10
|
+
refine Symbol do
|
11
|
+
def to_rbs_value
|
12
|
+
self
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
refine Integer do
|
17
|
+
def to_rbs_value
|
18
|
+
self
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
refine String do
|
23
|
+
# No supported literal-string
|
24
|
+
# def to_rbs_value
|
25
|
+
# self
|
26
|
+
# end
|
27
|
+
end
|
28
|
+
|
29
|
+
refine BasicObject do
|
30
|
+
def to_rbs_value
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_rbs_type(cache: [])
|
35
|
+
{ type: Kernel.instance_method(:class).bind(self).call, value: to_rbs_value, args: [] }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
refine Array do
|
40
|
+
def to_rbs_type(cache: [])
|
41
|
+
return { type: Array, value: nil, args: [[]] } if cache.include? __id__
|
42
|
+
{ type: Array, value: nil, args: (empty? ? [[]] : [filter_map { _1.to_rbs_type(cache: cache + [__id__]) }.uniq]) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
refine Hash do
|
47
|
+
def to_rbs_type(cache: [])
|
48
|
+
return { type: Hash, value: nil, args: [[], []] } if cache.include? __id__
|
49
|
+
args = empty? ? [[], []] : [keys.filter_map { _1.to_rbs_type(cache: cache + [__id__]) }.uniq, values.map { _1.to_rbs_type(cache: cache + [__id__]) }]
|
50
|
+
{ type: Hash, value: nil, args: args }
|
51
|
+
end
|
52
|
+
|
53
|
+
def except_value
|
54
|
+
{ type: self[:type], args: self[:args]&.map { |args| args.map { _1.except_value } } || [] }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
refine Range do
|
59
|
+
def to_rbs_type(*)
|
60
|
+
return { type: Range, value: nil, args: [[self.begin.to_rbs_type, self.end.to_rbs_type]] }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
refine ::TracePoint do
|
66
|
+
using ToRBSType
|
67
|
+
using Module.new {
|
68
|
+
refine Module do
|
69
|
+
def original_classname
|
70
|
+
if singleton_class?
|
71
|
+
self.superclass.name
|
72
|
+
else
|
73
|
+
self.name
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
refine Hash do
|
79
|
+
def to_arg_s
|
80
|
+
if self[:op] == :key
|
81
|
+
"#{self[:name]}: #{self[:value].inspect}"
|
82
|
+
else
|
83
|
+
"#{self[:name]} = #{self[:value].inspect}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
}
|
88
|
+
|
89
|
+
def receiver
|
90
|
+
self.self
|
91
|
+
end
|
92
|
+
|
93
|
+
def original_classname
|
94
|
+
if singleton_class?
|
95
|
+
if result = self.inspect[/#<Class:([^#].*)>/, 1]
|
96
|
+
result
|
97
|
+
else
|
98
|
+
self.ancestors.superclass
|
99
|
+
end
|
100
|
+
else
|
101
|
+
self.name
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def block?
|
106
|
+
method_id.nil? || defined_class.nil?
|
107
|
+
end
|
108
|
+
|
109
|
+
def singleton_method?
|
110
|
+
defined_class&.singleton_class? || (Module === receiver)
|
111
|
+
end
|
112
|
+
|
113
|
+
def receiver_class
|
114
|
+
singleton_method? ? receiver : receiver.class
|
115
|
+
end
|
116
|
+
|
117
|
+
def receiver_defined_class
|
118
|
+
return defined_class unless singleton_method?
|
119
|
+
return defined_class unless (Module === receiver)
|
120
|
+
receiver.ancestors.find { _1.methods(false).include?(method_id) || _1.private_methods(false).include?(method_id) } || defined_class
|
121
|
+
end
|
122
|
+
|
123
|
+
def argument_param(name)
|
124
|
+
value = binding.local_variable_get(name)
|
125
|
+
{ name: name, type: value.class, rbs_type: value.to_rbs_type, value_object_id: value.__id__ }
|
126
|
+
end
|
127
|
+
|
128
|
+
def arguments
|
129
|
+
parameters.map { |op, name|
|
130
|
+
if op == :opt && name.nil?
|
131
|
+
{ op: op, type: NilClass, rbs_type: { type: NilClass } }
|
132
|
+
elsif op == :rest && name.nil? || name == :*
|
133
|
+
{ op: op, type: Array, rbs_type: [].to_rbs_type }
|
134
|
+
elsif op == :keyrest && name.nil? || name == :**
|
135
|
+
{ op: op, type: Hash, rbs_type: {}.to_rbs_type }
|
136
|
+
elsif op == :block && name.nil? || name == :&
|
137
|
+
{ op: op, type: Proc, rbs_type: { type: Proc } }
|
138
|
+
elsif name.nil?
|
139
|
+
{ op: op, type: NilClass, rbs_type: { type: NilClass } }
|
140
|
+
else
|
141
|
+
{ op: op, name: name }.merge(argument_param(name))
|
142
|
+
end
|
143
|
+
}
|
144
|
+
end
|
145
|
+
|
146
|
+
def arguments_with_value
|
147
|
+
parameters.map { |op, name|
|
148
|
+
{ op: op, name: name, value: binding.local_variable_get(name) }
|
149
|
+
}
|
150
|
+
end
|
151
|
+
|
152
|
+
def visibility
|
153
|
+
return nil if block?
|
154
|
+
|
155
|
+
if singleton_method?
|
156
|
+
if receiver.singleton_class.private_method_defined?(method_id)
|
157
|
+
:private
|
158
|
+
elsif receiver.singleton_class.protected_method_defined?(method_id)
|
159
|
+
:protected
|
160
|
+
else
|
161
|
+
:public
|
162
|
+
end
|
163
|
+
else
|
164
|
+
if receiver.class.private_method_defined?(method_id)
|
165
|
+
:private
|
166
|
+
elsif receiver.class.protected_method_defined?(method_id)
|
167
|
+
:protected
|
168
|
+
else
|
169
|
+
:public
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def instance_variables_class
|
175
|
+
binding.eval("::Kernel.instance_method(:instance_variables).bind(self).call.to_h { [_1, ::Kernel.instance_method(:instance_variable_get).bind(self).call(_1).class] }")
|
176
|
+
end
|
177
|
+
|
178
|
+
def instance_variables_rbs_type
|
179
|
+
binding.eval("::Kernel.instance_method(:instance_variables).bind(self).call.to_h { [_1, ::Kernel.instance_method(:instance_variable_get).bind(self).call(_1)] }").to_h { [_1, _2.to_rbs_type] }
|
180
|
+
end
|
181
|
+
|
182
|
+
def meta
|
183
|
+
{
|
184
|
+
method_id: method_id,
|
185
|
+
defined_class: defined_class,
|
186
|
+
receiver_class: receiver_class,
|
187
|
+
receiver_defined_class: receiver_defined_class,
|
188
|
+
receiver_object_id: receiver.__id__,
|
189
|
+
callee_id: callee_id,
|
190
|
+
arguments: arguments,
|
191
|
+
lineno: lineno,
|
192
|
+
path: path,
|
193
|
+
visibility: visibility,
|
194
|
+
singleton_method?: singleton_method?,
|
195
|
+
}
|
196
|
+
end
|
197
|
+
|
198
|
+
def method_sigunature
|
199
|
+
if defined_class.nil?
|
200
|
+
"-> (#{arguments_with_value.map(&:to_arg_s).join(", ")}) {}"
|
201
|
+
elsif defined_class.singleton_class?
|
202
|
+
"#{defined_class.original_classname}.#{method_id}(#{arguments_with_value.map(&:to_arg_s).join(", ")})"
|
203
|
+
elsif defined_class == Object
|
204
|
+
"#{method_id}(#{arguments_with_value.map(&:to_arg_s).join(", ")})"
|
205
|
+
else
|
206
|
+
"#{defined_class.original_classname}##{method_id}(#{arguments_with_value.map(&:to_arg_s).join(", ")})"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end end end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "rbs"
|
2
|
+
require_relative "../dynamic.rb"
|
3
|
+
|
4
|
+
$rbs_dynamic_tracer = RBS::Dynamic::Tracer::CalledMethod.new
|
5
|
+
$rbs_dynamic_tracer.enable
|
6
|
+
|
7
|
+
END {
|
8
|
+
$rbs_dynamic_tracer.ignore_rbs_dynamic_trace { $rbs_dynamic_tracer.disable }
|
9
|
+
called_methods = $rbs_dynamic_tracer.called_methods
|
10
|
+
|
11
|
+
puts "# RBS dynamic trace #{RBS::Dynamic::VERSION}"
|
12
|
+
puts
|
13
|
+
|
14
|
+
config = RBS::Dynamic::Config.new($rbs_dynamic_option)
|
15
|
+
decls = RBS::Dynamic::Converter::TraceToRBS.new(called_methods).convert(
|
16
|
+
root_path: config.root_path,
|
17
|
+
except_build_members: config.except_build_members,
|
18
|
+
method_defined_calssses: config.method_defined_calssses,
|
19
|
+
include_method_location: config.show_method_location?,
|
20
|
+
use_literal_type: config.use_literal_type?,
|
21
|
+
with_literal_type: config.with_literal_type?,
|
22
|
+
use_interface_method_argument: config.use_interface_method_argument?,
|
23
|
+
target_classname_pattern: config.target_classname_pattern,
|
24
|
+
ignore_classname_pattern: config.ignore_classname_pattern
|
25
|
+
).values
|
26
|
+
stdout = StringIO.new
|
27
|
+
writer = RBS::Writer.new(out: stdout)
|
28
|
+
writer.write(decls)
|
29
|
+
puts stdout.string
|
30
|
+
}
|