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,194 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbs"
|
4
|
+
# require_relative "./../refine/signature_merger.rb"
|
5
|
+
|
6
|
+
module RBS module Dynamic module Builder
|
7
|
+
class Types
|
8
|
+
BOOL = RBS::Types::Bases::Bool.new(location: nil)
|
9
|
+
VOID = RBS::Types::Bases::Void.new(location: nil)
|
10
|
+
ANY = RBS::Types::Bases::Any.new(location: nil)
|
11
|
+
|
12
|
+
module ToRBSType
|
13
|
+
refine Object do
|
14
|
+
def to_rbs_type
|
15
|
+
{ type: self, args: [] }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
refine Hash do
|
20
|
+
def to_rbs_type
|
21
|
+
self
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
using ToRBSType
|
26
|
+
|
27
|
+
module RBSTypeMerger
|
28
|
+
refine Object do
|
29
|
+
def merge_type(*)
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
refine Hash do
|
35
|
+
def merge_type(other)
|
36
|
+
return unless Hash === other
|
37
|
+
return unless self[:type] == other[:type]
|
38
|
+
return unless self[:args].count == other[:args].count
|
39
|
+
{ type: self[:type], value: [self[:value], other[:value]].flatten.compact.uniq, args: self[:args].zip(other[:args]).map(&:flatten).map(&:uniq) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
refine Array do
|
44
|
+
def push_merge_type(other)
|
45
|
+
each.with_index { |type, i|
|
46
|
+
merged = type.merge_type(other)
|
47
|
+
if merged
|
48
|
+
self[i] = merged
|
49
|
+
return self
|
50
|
+
end
|
51
|
+
}
|
52
|
+
push(other)
|
53
|
+
end
|
54
|
+
|
55
|
+
def zip_type
|
56
|
+
inject([]) { |result, type|
|
57
|
+
result.push_merge_type(type)
|
58
|
+
}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
using RBSTypeMerger
|
63
|
+
|
64
|
+
using Module.new {
|
65
|
+
refine Object do
|
66
|
+
def type(*)
|
67
|
+
RBS::Types::Literal.new(
|
68
|
+
literal: self,
|
69
|
+
location: nil
|
70
|
+
)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
refine Class do
|
75
|
+
def type(*args)
|
76
|
+
RBS::Types::ClassInstance.new(
|
77
|
+
args: args.map { Array === _1 && _1.empty? ? ANY : Types.new(_1).build },
|
78
|
+
location: nil,
|
79
|
+
name: name
|
80
|
+
)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
refine NilClass do
|
85
|
+
def type(*)
|
86
|
+
RBS::Types::Bases::Nil.new(location: nil)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
refine Hash do
|
91
|
+
def type
|
92
|
+
self[:type].type(*self[:args])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
refine RBS::Types::Bases::Base do
|
97
|
+
def |(other)
|
98
|
+
RBS::Types::Union.new(
|
99
|
+
types: [self, other],
|
100
|
+
location: nil
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
def type
|
105
|
+
self
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
refine RBS::Types::Literal do
|
110
|
+
def |(other)
|
111
|
+
RBS::Types::Union.new(
|
112
|
+
types: [self, other],
|
113
|
+
location: nil
|
114
|
+
)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
refine RBS::Types::Application do
|
119
|
+
def type(*)
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
def |(other)
|
124
|
+
RBS::Types::Union.new(
|
125
|
+
types: [self, other],
|
126
|
+
location: nil
|
127
|
+
)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
refine RBS::Types::Union do
|
132
|
+
def |(other)
|
133
|
+
RBS::Types::Union.new(
|
134
|
+
types: (types + [other]),
|
135
|
+
location: nil
|
136
|
+
)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
refine Array do
|
141
|
+
def union_type
|
142
|
+
map { _1.type }.inject { _1 | _2 }
|
143
|
+
end
|
144
|
+
end
|
145
|
+
}
|
146
|
+
|
147
|
+
attr_reader :types
|
148
|
+
|
149
|
+
def initialize(type)
|
150
|
+
@types = case type
|
151
|
+
when nil
|
152
|
+
[nil]
|
153
|
+
when Hash
|
154
|
+
[type]
|
155
|
+
else
|
156
|
+
Array(type)
|
157
|
+
end.map(&:to_rbs_type).uniq.zip_type
|
158
|
+
end
|
159
|
+
|
160
|
+
def build
|
161
|
+
if optional?
|
162
|
+
RBS::Types::Optional.new(
|
163
|
+
type: (target_types - [NIL_RBS_TYPE, NILCLASS_RBS_TYPE]).union_type,
|
164
|
+
location: nil
|
165
|
+
)
|
166
|
+
else
|
167
|
+
target_types.union_type
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
NILCLASS_RBS_TYPE = NilClass.to_rbs_type
|
172
|
+
NIL_RBS_TYPE = nil.to_rbs_type
|
173
|
+
|
174
|
+
TRUECLASS_RBS_TYPE = TrueClass.to_rbs_type
|
175
|
+
TRUE_RBS_TYPE = true.to_rbs_type
|
176
|
+
|
177
|
+
FALSECLASS_RBS_TYPE = FalseClass.to_rbs_type
|
178
|
+
FALSE_RBS_TYPE = false.to_rbs_type
|
179
|
+
|
180
|
+
def optional?
|
181
|
+
!!types.group_by { _1 == NIL_RBS_TYPE || _1 == NILCLASS_RBS_TYPE }.values.then { |opt, other| opt&.size&.>=(1) && other&.size&.>=(1) }
|
182
|
+
end
|
183
|
+
|
184
|
+
def in_bool?
|
185
|
+
0 < types.count { _1 == TRUE_RBS_TYPE || _1 == TRUECLASS_RBS_TYPE } && 0 < types.count { _1 == FALSE_RBS_TYPE || _1 == FALSECLASS_RBS_TYPE }
|
186
|
+
end
|
187
|
+
|
188
|
+
def target_types
|
189
|
+
(types + types.flat_map { Array(_1[:value]).map { |value| { type: value, args: [] } } })
|
190
|
+
.tap { break _1 - [NIL_RBS_TYPE, NILCLASS_RBS_TYPE] if optional? }
|
191
|
+
.tap { break _1 - [TRUE_RBS_TYPE, TRUECLASS_RBS_TYPE, FALSE_RBS_TYPE, FALSECLASS_RBS_TYPE] + [BOOL] if in_bool? }
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end end end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbs"
|
4
|
+
require_relative "./builder/types.rb"
|
5
|
+
require_relative "./builder/methods.rb"
|
6
|
+
|
7
|
+
module RBS module Dynamic module Builder
|
8
|
+
class Base
|
9
|
+
attr_reader :interface_members
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@inclued_modules = []
|
13
|
+
@prepended_modules = []
|
14
|
+
@extended_modules = []
|
15
|
+
@constant_variables = Hash.new { |h, name| h[name] = [] }
|
16
|
+
@instance_variables = Hash.new { |h, name| h[name] = [] }
|
17
|
+
@methods = Hash.new { |h, name| h[name] = Methods.new(name, kind: :instance) }
|
18
|
+
@singleton_methods = Hash.new { |h, name| h[name] = Methods.new(name, kind: :singleton) }
|
19
|
+
@other_members = []
|
20
|
+
@interface_members = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_inclued_module(mod)
|
24
|
+
@inclued_modules << mod
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_prepended_module(mod)
|
28
|
+
@prepended_modules << mod
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_extended_module(mod)
|
32
|
+
@extended_modules << mod
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_constant_variable(name, type)
|
36
|
+
@constant_variables[name] << type
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_instance_variable(name, type)
|
40
|
+
@instance_variables[name] << type
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_singleton_method(name, sig)
|
44
|
+
@singleton_methods[name] << sig
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_method(name, sig = {})
|
48
|
+
@methods[name] << sig
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_member(member)
|
52
|
+
@other_members << member
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_interface_members(member)
|
56
|
+
@interface_members << member
|
57
|
+
end
|
58
|
+
|
59
|
+
def build_members
|
60
|
+
[
|
61
|
+
*build_inclued_modules,
|
62
|
+
*build_prepended_modules,
|
63
|
+
*build_extended_modules,
|
64
|
+
*build_constant_variables,
|
65
|
+
*build_singleton_methods,
|
66
|
+
*build_methods,
|
67
|
+
*build_instance_variables,
|
68
|
+
*@interface_members.map(&:build),
|
69
|
+
*@other_members
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
def build_inclued_modules
|
74
|
+
@inclued_modules.map { |mod|
|
75
|
+
RBS::AST::Members::Include.new(
|
76
|
+
name: mod.name,
|
77
|
+
args: [],
|
78
|
+
annotations: [],
|
79
|
+
location: nil,
|
80
|
+
comment: nil
|
81
|
+
)
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def build_prepended_modules
|
86
|
+
@prepended_modules.map { |mod|
|
87
|
+
RBS::AST::Members::Prepend.new(
|
88
|
+
name: mod.name,
|
89
|
+
args: [],
|
90
|
+
annotations: [],
|
91
|
+
location: nil,
|
92
|
+
comment: nil
|
93
|
+
)
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
def build_extended_modules
|
98
|
+
@extended_modules.map { |mod|
|
99
|
+
RBS::AST::Members::Extend.new(
|
100
|
+
name: mod.name,
|
101
|
+
args: [],
|
102
|
+
annotations: [],
|
103
|
+
location: nil,
|
104
|
+
comment: nil
|
105
|
+
)
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def build_constant_variables
|
110
|
+
@constant_variables.map { |name, types|
|
111
|
+
RBS::AST::Members::InstanceVariable.new(
|
112
|
+
name: name,
|
113
|
+
type: Types.new(types.flatten).build,
|
114
|
+
location: nil,
|
115
|
+
comment: nil
|
116
|
+
)
|
117
|
+
}
|
118
|
+
end
|
119
|
+
|
120
|
+
def build_instance_variables
|
121
|
+
@instance_variables.map { |name, types|
|
122
|
+
RBS::AST::Declarations::Constant.new(
|
123
|
+
name: name,
|
124
|
+
type: Types.new(types.flatten).build,
|
125
|
+
location: nil,
|
126
|
+
comment: nil
|
127
|
+
)
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
def build_singleton_methods
|
132
|
+
@singleton_methods.values.map(&:build)
|
133
|
+
end
|
134
|
+
|
135
|
+
def build_methods
|
136
|
+
@methods.values.map(&:build)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
private_constant :Base
|
140
|
+
|
141
|
+
class Module < Base
|
142
|
+
attr_reader :module
|
143
|
+
|
144
|
+
def initialize(module_)
|
145
|
+
super()
|
146
|
+
@module = module_
|
147
|
+
end
|
148
|
+
|
149
|
+
def build
|
150
|
+
RBS::AST::Declarations::Module.new(
|
151
|
+
name: self.module.name,
|
152
|
+
type_params: [],
|
153
|
+
self_types: [],
|
154
|
+
members: build_members,
|
155
|
+
location: nil,
|
156
|
+
annotations: [],
|
157
|
+
comment: nil
|
158
|
+
)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class Class < Base
|
163
|
+
attr_reader :klass
|
164
|
+
|
165
|
+
def initialize(klass)
|
166
|
+
super()
|
167
|
+
@klass = klass
|
168
|
+
end
|
169
|
+
|
170
|
+
def build
|
171
|
+
RBS::AST::Declarations::Class.new(
|
172
|
+
name: klass.name,
|
173
|
+
type_params: [],
|
174
|
+
super_class: build_super_class,
|
175
|
+
members: build_members,
|
176
|
+
location: nil,
|
177
|
+
annotations: [],
|
178
|
+
comment: nil
|
179
|
+
)
|
180
|
+
end
|
181
|
+
|
182
|
+
def build_super_class
|
183
|
+
::RBS::AST::Declarations::Class::Super.new(
|
184
|
+
name: klass.superclass.name,
|
185
|
+
args: [],
|
186
|
+
location: nil
|
187
|
+
) unless klass.superclass&.name.nil? || Object == klass.superclass
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
class Interface < Base
|
192
|
+
attr_reader :name
|
193
|
+
attr_reader :methods
|
194
|
+
|
195
|
+
def initialize(name)
|
196
|
+
super()
|
197
|
+
@name = name
|
198
|
+
end
|
199
|
+
|
200
|
+
def build
|
201
|
+
RBS::AST::Declarations::Interface.new(
|
202
|
+
name: @name,
|
203
|
+
type_params: [],
|
204
|
+
members: build_members,
|
205
|
+
annotations: [],
|
206
|
+
location: nil,
|
207
|
+
comment: nil
|
208
|
+
)
|
209
|
+
end
|
210
|
+
|
211
|
+
def eql?(other)
|
212
|
+
self.methods.map { |_, method| [method.name, method.kind, method.sigs] } ==
|
213
|
+
other.methods.map { |_, method| [method.name, method.kind, method.sigs] }
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end end end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require "thor"
|
3
|
+
require_relative "../dynamic.rb"
|
4
|
+
|
5
|
+
module RBS module Dynamic
|
6
|
+
class CLI < Thor
|
7
|
+
desc "version", "show version"
|
8
|
+
def version
|
9
|
+
puts "rbs dynamic version #{RBS::Dynamic::VERSION}"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "trace [filename]", ""
|
13
|
+
option :"root-path", type: :string, default: Dir.pwd, desc: "Rooting path. Default: current dir"
|
14
|
+
option :"target-filepath-pattern", type: :string, default: ".*", desc: "Target filepath pattern. e.g. hoge\\|foo\\|bar. Default '.*'"
|
15
|
+
option :"ignore-filepath-pattern", type: :string, default: nil, desc: "Ignore filepath pattern. Priority over `target-filepath-pattern`. e.g. hoge\\|foo\\|bar. Default ''"
|
16
|
+
option :"target-classname-pattern", type: :string, default: ".*", desc: "Target class name pattern. e.g. RBS::Dynamic. Default '.*'"
|
17
|
+
option :"ignore-classname-pattern", type: :string, default: nil, desc: "Ignore class name pattern. Priority over `target-classname-pattern`. e.g. PP\\|PrettyPrint. Default ''"
|
18
|
+
option :"ignore-class_members", type: :array, enum: %w(inclued_modules prepended_modules extended_modules constant_variables instance_variables singleton_methods methods)
|
19
|
+
option :"method-defined-calsses", type: :array, enum: %w(defined_class receiver_class), desc: "Which class defines method type. Default: defined_class and receiver_class"
|
20
|
+
option :"show-method-location", type: :boolean, default: false, desc: "Show source_location and called_location in method comments. Default: no"
|
21
|
+
option :"use-literal_type", type: :boolean, default: false, desc: "Integer and Symbol as literal types. e.g func(:hoge, 42). Default: no"
|
22
|
+
option :"with-literal_type", type: :boolean, default: false, desc: "Integer and Symbol with literal types. e.g func(Symbol | :hoge | :foo). Default: no"
|
23
|
+
option :"use-interface_method_argument", type: :boolean, default: false, desc: "Define method arguments in interface. Default: no"
|
24
|
+
option :"stdout", type: :boolean, default: false, desc: "stdout at runtime. Default: no"
|
25
|
+
option :"trace-c_api-method", type: :boolean, default: false, desc: "Trace C API method. Default: no"
|
26
|
+
def trace(filename)
|
27
|
+
decls = RBS::Dynamic.trace(**options) {
|
28
|
+
load filename
|
29
|
+
}.values
|
30
|
+
stdout = StringIO.new
|
31
|
+
writer = RBS::Writer.new(out: stdout)
|
32
|
+
writer.write(decls)
|
33
|
+
puts "# RBS dynamic trace #{RBS::Dynamic::VERSION}"
|
34
|
+
puts
|
35
|
+
puts stdout.string
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RBS module Dynamic
|
4
|
+
class Config
|
5
|
+
attr_reader :options
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def except_build_members
|
12
|
+
ignore_class_members
|
13
|
+
end
|
14
|
+
|
15
|
+
def root_path
|
16
|
+
options["root-path"] || options[:root_path] || Dir.pwd
|
17
|
+
end
|
18
|
+
|
19
|
+
def target_filepath_pattern
|
20
|
+
options["target-filepath-pattern"] || options[:target_filepath_pattern] || /.*/
|
21
|
+
end
|
22
|
+
|
23
|
+
def ignore_filepath_pattern
|
24
|
+
options["ignore-filepath-pattern"] || options[:ignore_filepath_pattern]
|
25
|
+
end
|
26
|
+
|
27
|
+
def target_classname_pattern
|
28
|
+
Regexp.new(options["target-classname-pattern"] || options[:target_classname_pattern] || /.*/)
|
29
|
+
end
|
30
|
+
|
31
|
+
def ignore_classname_pattern
|
32
|
+
(options["ignore-classname-pattern"] || options[:ignore_classname_pattern])&.then { Regexp.new(_1) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def ignore_class_members
|
36
|
+
(options["ignore-class_members"] || options[:ignore_class_members] || []).map(&:to_sym)
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_defined_calssses
|
40
|
+
(options["method-defined-calsses"] || options[:method_defined_calssses] || %i(defined_class receiver_class)).map(&:to_sym)
|
41
|
+
end
|
42
|
+
|
43
|
+
def show_method_location?
|
44
|
+
options["show-method-location"] || options[:show_method_location] || false
|
45
|
+
end
|
46
|
+
|
47
|
+
def use_literal_type?
|
48
|
+
options["use-literal_type"] || options[:use_literal_type] || false
|
49
|
+
end
|
50
|
+
|
51
|
+
def with_literal_type?
|
52
|
+
options["with-literal_type"] || options[:with_literal_type] || false
|
53
|
+
end
|
54
|
+
|
55
|
+
def use_interface_method_argument?
|
56
|
+
options["use-interface_method_argument"] || options[:use_interface_method_argument] || false
|
57
|
+
end
|
58
|
+
|
59
|
+
def trace_c_api_method?
|
60
|
+
options["trace-c_api-method"] || options[:trace_c_api_method] || false
|
61
|
+
end
|
62
|
+
|
63
|
+
def stdout?
|
64
|
+
(options["stdout"] || options[:stdout]).then { _1.nil? ? true : _1 }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rbs"
|
4
|
+
require_relative "../refine/trace_point.rb"
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
module RBS module Dynamic module Converter
|
8
|
+
module CalledMethodToMethodSigunature
|
9
|
+
using RBS::Dynamic::Refine::TracePoint::ToRBSType
|
10
|
+
|
11
|
+
using Module.new {
|
12
|
+
refine String do
|
13
|
+
def relative_path(base_directory)
|
14
|
+
delete_prefix(base_directory)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
refine Hash do
|
19
|
+
def except(*keys)
|
20
|
+
slice(*self.keys - keys)
|
21
|
+
end unless method_defined?(:except)
|
22
|
+
|
23
|
+
def value_to_type
|
24
|
+
merge(type: self[:value] || self[:type]).except(:value)
|
25
|
+
end
|
26
|
+
|
27
|
+
def type_to_rbs_type(use_literal_type: false, with_literal_type: false)
|
28
|
+
if use_literal_type
|
29
|
+
merge(type: self[:rbs_type].value_to_type).except(:op, :rbs_type, :value_object_id)
|
30
|
+
elsif with_literal_type
|
31
|
+
merge(type: self[:rbs_type]).except(:op, :rbs_type, :value_object_id)
|
32
|
+
else
|
33
|
+
merge(type: self[:rbs_type].except_value).except(:op, :rbs_type, :value_object_id)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
}
|
38
|
+
|
39
|
+
refine Array do
|
40
|
+
def type_to_rbs_type(use_literal_type: false, with_literal_type: false)
|
41
|
+
map { _1.type_to_rbs_type(use_literal_type: use_literal_type, with_literal_type: with_literal_type) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
refine Hash do
|
46
|
+
def method_sigunature(root_path: nil, include_location: false, use_literal_type: false, with_literal_type: false)
|
47
|
+
opt = { use_literal_type: use_literal_type, with_literal_type: with_literal_type }
|
48
|
+
visibility = self[:visibility] if self[:visibility] != :public
|
49
|
+
|
50
|
+
req_opt = self[:arguments].take_while { _1[:op] != :rest }.to_a
|
51
|
+
rest, *other = self[:arguments].drop_while { _1[:op] != :rest }.to_a
|
52
|
+
req_opt ||= []
|
53
|
+
rest ||= []
|
54
|
+
{
|
55
|
+
required_positionals: req_opt.select { _1[:op] == :req }.type_to_rbs_type(**opt),
|
56
|
+
optional_positionals: req_opt.select { _1[:op] == :opt }.type_to_rbs_type(**opt),
|
57
|
+
rest_positionals: self[:arguments].select { _1[:op] == :rest }.type_to_rbs_type(**opt),
|
58
|
+
trailing_positionals: other.select { _1[:op] == :req }.type_to_rbs_type(**opt),
|
59
|
+
required_keywords: self[:arguments].select { _1[:op] == :keyreq }.type_to_rbs_type(**opt),
|
60
|
+
optional_keywords: self[:arguments].select { _1[:op] == :key }.type_to_rbs_type(**opt),
|
61
|
+
rest_keywords: self[:arguments].select { _1[:op] == :keyrest }.type_to_rbs_type(**opt),
|
62
|
+
block: self[:block].map { _1.method_sigunature(include_location: false, **opt) },
|
63
|
+
source_location: ("#{self[:path].relative_path(root_path)}:#{self[:lineno]}" if include_location),
|
64
|
+
reference_location: ("#{self[:called_path].relative_path(root_path)}:#{self[:called_lineno]}" if include_location)
|
65
|
+
}.merge(
|
66
|
+
return_type: (if use_literal_type
|
67
|
+
self[:return_value_rbs_type].value_to_type
|
68
|
+
elsif with_literal_type
|
69
|
+
self[:return_value_rbs_type]
|
70
|
+
else
|
71
|
+
self[:return_value_rbs_type].except_value
|
72
|
+
end),
|
73
|
+
visibility: visibility
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end end end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
require_relative "./called_method_to_sigunature.rb"
|
5
|
+
|
6
|
+
module RBS module Dynamic module Converter
|
7
|
+
module CalledMethodToWithInterface
|
8
|
+
using CalledMethodToMethodSigunature
|
9
|
+
refine Hash do
|
10
|
+
def to_with_interface(defined_interfaces: [])
|
11
|
+
self.dup.then { |called_method|
|
12
|
+
interfaces = called_method[:arguments].each.with_index(1).inject([]) { |interfaces, (argument, i)|
|
13
|
+
called_methods = called_method[:called_methods].select { _1[:receiver_object_id] == argument[:value_object_id] }
|
14
|
+
next interfaces if called_methods.empty?
|
15
|
+
|
16
|
+
interface = RBS::Dynamic::Builder::Interface.new("dummy_name")
|
17
|
+
sub_interfaces = called_methods.map { |called_method|
|
18
|
+
called_method, sub_interfaces = called_method.to_with_interface(defined_interfaces: defined_interfaces + interfaces)
|
19
|
+
# Non support nexted defined interface in RBS
|
20
|
+
# sub_interfaces.map { interface.add_member(_1.build) }
|
21
|
+
interface.add_method(called_method[:method_id], **called_method.method_sigunature)
|
22
|
+
sub_interfaces
|
23
|
+
}.flatten
|
24
|
+
interfaces += sub_interfaces
|
25
|
+
|
26
|
+
unless interface_ = (defined_interfaces + interfaces).find { _1.eql? interface }
|
27
|
+
interface_name = "_Interface_have__#{called_methods.map { _1[:method_id] }.uniq.join("__")}__#{(defined_interfaces + interfaces).count + 1}"
|
28
|
+
# except #+ #== #hoge? methods
|
29
|
+
.gsub(/[^[:alnum:]_]/, "")
|
30
|
+
interface.instance_exec { @name = interface_name }
|
31
|
+
interfaces << interface
|
32
|
+
end
|
33
|
+
|
34
|
+
argument[:rbs_type][:type] = RBS::Types::Interface.new(name: (interface_ || interface).name, args: [], location: nil)
|
35
|
+
|
36
|
+
interfaces
|
37
|
+
}
|
38
|
+
|
39
|
+
[called_method, interfaces]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end end end
|