orthoses 1.7.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -3
- data/lib/orthoses/attribute.rb +28 -55
- data/lib/orthoses/builder.rb +7 -3
- data/lib/orthoses/constant.rb +0 -1
- data/lib/orthoses/content/duplication_checker.rb +67 -35
- data/lib/orthoses/content/environment.rb +1 -1
- data/lib/orthoses/content.rb +20 -13
- data/lib/orthoses/create_file_by_name.rb +38 -7
- data/lib/orthoses/lazy_trace_point.rb +37 -43
- data/lib/orthoses/missing_name.rb +81 -0
- data/lib/orthoses/mixin.rb +29 -34
- data/lib/orthoses/rbs_prototype_runtime.rb +23 -4
- data/lib/orthoses/trace/attribute.rb +26 -8
- data/lib/orthoses/utils.rb +2 -2
- data/lib/orthoses/version.rb +1 -1
- data/lib/orthoses.rb +1 -0
- data/sig/orthoses/_call.rbs +1 -1
- data/sig/orthoses/_middle_ware.rbs +1 -1
- data/sig/orthoses/attribute/hook.rbs +1 -1
- data/sig/orthoses/attribute.rbs +3 -3
- data/sig/orthoses/autoload/hook.rbs +1 -1
- data/sig/orthoses/autoload.rbs +2 -1
- data/sig/orthoses/builder/call_logable.rbs +1 -1
- data/sig/orthoses/builder.rbs +7 -4
- data/sig/orthoses/call_tracer/capturable.rbs +1 -1
- data/sig/orthoses/call_tracer/capture.rbs +2 -2
- data/sig/orthoses/call_tracer/lazy.rbs +4 -2
- data/sig/orthoses/call_tracer.rbs +3 -1
- data/sig/orthoses/const_load_error.rbs +4 -1
- data/sig/orthoses/constant.rbs +3 -3
- data/sig/orthoses/content/array_io.rbs +2 -1
- data/sig/orthoses/content/duplication_checker.rbs +10 -3
- data/sig/orthoses/content/environment.rbs +11 -6
- data/sig/orthoses/content/header_builder.rbs +3 -1
- data/sig/orthoses/content.rbs +7 -1
- data/sig/orthoses/create_file_by_name.rbs +8 -3
- data/sig/orthoses/delegate_class/hook.rbs +1 -1
- data/sig/orthoses/delegate_class.rbs +2 -2
- data/sig/orthoses/filter.rbs +4 -3
- data/sig/orthoses/lazy_trace_point/method_added_hook.rbs +6 -0
- data/sig/orthoses/lazy_trace_point/signleton_method_added_hook.rbs +5 -0
- data/sig/orthoses/lazy_trace_point.rbs +7 -7
- data/sig/orthoses/load_rbs.rbs +3 -3
- data/sig/orthoses/missing_name/missing_class.rbs +8 -0
- data/sig/orthoses/missing_name/missing_module.rbs +8 -0
- data/sig/orthoses/missing_name.rbs +7 -0
- data/sig/orthoses/mixin/hook.rbs +2 -2
- data/sig/orthoses/mixin.rbs +6 -4
- data/sig/orthoses/name_space_error.rbs +1 -1
- data/sig/orthoses/object_space_all.rbs +2 -2
- data/sig/orthoses/outputable/avoid_recursive_ancestor_error.rbs +2 -2
- data/sig/orthoses/outputable/constantizable_filter.rbs +2 -1
- data/sig/orthoses/outputable/uniq_content_body.rbs +2 -1
- data/sig/orthoses/outputable.rbs +3 -1
- data/sig/orthoses/path_helper.rbs +3 -1
- data/sig/orthoses/pp.rbs +2 -1
- data/sig/orthoses/rbs_prototype_rb.rbs +6 -4
- data/sig/orthoses/rbs_prototype_runtime.rbs +10 -3
- data/sig/orthoses/sort.rbs +2 -1
- data/sig/orthoses/store.rbs +2 -1
- data/sig/orthoses/tap.rbs +3 -2
- data/sig/orthoses/trace/attribute/hook.rbs +11 -0
- data/sig/orthoses/trace/attribute.rbs +4 -1
- data/sig/orthoses/trace/method/info.rbs +1 -1
- data/sig/orthoses/trace/method.rbs +6 -1
- data/sig/orthoses/trace/targetable.rbs +1 -1
- data/sig/orthoses/trace.rbs +3 -1
- data/sig/orthoses/utils/type_list.rbs +2 -1
- data/sig/orthoses/utils/underscore.rbs +1 -1
- data/sig/orthoses/utils.rbs +4 -2
- data/sig/orthoses/walk.rbs +3 -3
- data/sig/orthoses/writer.rbs +3 -2
- data/sig/orthoses.rbs +6 -6
- metadata +9 -21
- data/Gemfile +0 -16
- data/Gemfile.lock +0 -86
- data/examples/minitest/Rakefile +0 -56
- data/examples/rack-test/Gemfile +0 -8
- data/examples/rack-test/Gemfile.lock +0 -30
- data/examples/rack-test/Rakefile +0 -7
- data/examples/rack-test/generate.rb +0 -31
- data/examples/rack-test/out/rack/test/cookie.rbs +0 -28
- data/examples/rack-test/out/rack/test/cookie_jar.rbs +0 -28
- data/examples/rack-test/out/rack/test/fake_app.rbs +0 -13
- data/examples/rack-test/out/rack/test/input_rewinder.rbs +0 -8
- data/examples/rack-test/out/rack/test/methods.rbs +0 -98
- data/examples/rack-test/out/rack/test/session.rbs +0 -186
- data/examples/rack-test/out/rack/test/uploaded_file.rbs +0 -18
- data/examples/rack-test/out/rack/test/utils.rbs +0 -112
- data/examples/rack-test/out/rack/test.rbs +0 -3
- data/examples/simple_middleware.rb +0 -11
- data/examples/simple_middleware.rbs +0 -7
- data/orthoses.gemspec +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dd4d2682b08812b2f8fa633aa299702d38fd509439e4e2ac0b8751a64358b32a
|
4
|
+
data.tar.gz: 28118eed7d772c490670f83277ccdabc4d2938ca329f5051f8aebd40be1f08a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f4262320cb3d9ef5304cbdb53af7cb0e0895bac03e7d98697cf38fc73dabc25b579c6fd4a213ae5c0d97d1763f88dabde2f7f1e6455a084c424ef6b042a3acb
|
7
|
+
data.tar.gz: 35e2b8378b602ad6b853ba7f543d807aab514d0f2a7d8b931230912084d40c7222e45d09cfe4b3eddd614f62bcce578cac2b6e14dac08f5578089ecbb7d7895c
|
data/README.md
CHANGED
@@ -29,11 +29,13 @@ For example, You can write script in Rakefile.
|
|
29
29
|
require 'orthoses'
|
30
30
|
|
31
31
|
namespace :rbs do
|
32
|
-
desc "build RBS to sig/
|
32
|
+
desc "build RBS to sig/orthoses"
|
33
33
|
task :build do
|
34
34
|
Orthoses::Builder.new do
|
35
35
|
use Orthoses::CreateFileByName,
|
36
|
-
|
36
|
+
depth: 1,
|
37
|
+
to: "sig/orthoses",
|
38
|
+
rmtree: true,
|
37
39
|
header: "# !!! GENERATED CODE !!!"
|
38
40
|
use Orthoses::Filter do |name, _content|
|
39
41
|
path, _lineno = Object.const_source_location(name)
|
@@ -53,7 +55,7 @@ namespace :rbs do
|
|
53
55
|
end
|
54
56
|
```
|
55
57
|
|
56
|
-
Then, you can see the result files under `sig/
|
58
|
+
Then, you can see the result files under `sig/orthoses`.
|
57
59
|
|
58
60
|
## Utils
|
59
61
|
|
@@ -177,6 +179,11 @@ Sort signatures by class/module.
|
|
177
179
|
|
178
180
|
Trace the argument and return value objects when the method is actually called and determine the type.
|
179
181
|
|
182
|
+
## Orthoses::MissingName
|
183
|
+
|
184
|
+
Completes undefined class/module names.
|
185
|
+
If it is unknown whether it is a class or a module, it is defined as an empty module, and if it is a superclass, it is defined as an empty class.
|
186
|
+
|
180
187
|
## Development
|
181
188
|
|
182
189
|
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/orthoses/attribute.rb
CHANGED
@@ -1,98 +1,71 @@
|
|
1
1
|
module Orthoses
|
2
2
|
class Attribute
|
3
|
+
CALL_GRAPH = {}
|
4
|
+
|
3
5
|
module Hook
|
4
6
|
def attr(*names)
|
7
|
+
(CALL_GRAPH[self]||=[]) << [:attr, names]
|
5
8
|
super
|
6
9
|
end
|
7
10
|
|
8
11
|
def attr_accessor(*names)
|
12
|
+
(CALL_GRAPH[self]||=[]) << [:attr_accessor, names]
|
9
13
|
super
|
10
14
|
end
|
11
15
|
|
12
16
|
def attr_reader(*names)
|
17
|
+
(CALL_GRAPH[self]||=[]) << [:attr_reader, names]
|
13
18
|
super
|
14
19
|
end
|
15
20
|
|
16
21
|
def attr_writer(*names)
|
22
|
+
(CALL_GRAPH[self]||=[]) << [:attr_writer, names]
|
17
23
|
super
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
21
27
|
def initialize(loader)
|
28
|
+
CALL_GRAPH.clear
|
22
29
|
@loader = loader
|
23
30
|
end
|
24
31
|
|
25
32
|
def call
|
26
33
|
::Module.prepend(Hook)
|
27
34
|
|
28
|
-
|
29
|
-
attr_accessor = CallTracer.new
|
30
|
-
attr_reader = CallTracer.new
|
31
|
-
attr_writer = CallTracer.new
|
32
|
-
|
33
|
-
store = attr.trace(Hook.instance_method(:attr)) do
|
34
|
-
attr_accessor.trace(Hook.instance_method(:attr_accessor)) do
|
35
|
-
attr_reader.trace(Hook.instance_method(:attr_reader)) do
|
36
|
-
attr_writer.trace(Hook.instance_method(:attr_writer)) do
|
37
|
-
@loader.call
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
35
|
+
store = @loader.call
|
42
36
|
|
43
|
-
|
44
|
-
m =
|
37
|
+
CALL_GRAPH.dup.each do |base_mod, calls|
|
38
|
+
m = base_mod.to_s.match(/#<Class:([\w:]+)>/)
|
45
39
|
if m && m[1]
|
46
40
|
receiver_name = m[1]
|
47
41
|
prefix = "self."
|
48
42
|
else
|
49
|
-
receiver_name = Utils.module_name(
|
43
|
+
receiver_name = Utils.module_name(base_mod) or next
|
50
44
|
prefix = nil
|
51
45
|
end
|
52
46
|
content = store[receiver_name]
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
47
|
+
|
48
|
+
calls.each do |(a, names)|
|
49
|
+
case a
|
50
|
+
when :attr
|
51
|
+
if names[1].equal?(true)
|
52
|
+
content << "attr_accessor #{prefix}#{names[0]}: untyped"
|
53
|
+
elsif names[1].equal?(false)
|
54
|
+
content << "attr_reader #{prefix}#{names[0]}: untyped"
|
55
|
+
else
|
56
|
+
names.each do |name|
|
57
|
+
content << "attr_reader #{prefix}#{name}: untyped"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
else
|
61
|
+
names.each do |name|
|
62
|
+
content << "#{a} #{prefix}#{name}: untyped"
|
63
|
+
end
|
61
64
|
end
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
65
|
-
each_definition(attr_accessor) do |receiver_name, name|
|
66
|
-
store[receiver_name] << "attr_accessor #{name}: untyped"
|
67
|
-
end
|
68
|
-
each_definition(attr_reader) do |receiver_name, name|
|
69
|
-
store[receiver_name] << "attr_reader #{name}: untyped"
|
70
|
-
end
|
71
|
-
each_definition(attr_writer) do |receiver_name, name|
|
72
|
-
store[receiver_name] << "attr_writer #{name}: untyped"
|
73
|
-
end
|
74
|
-
|
75
68
|
store
|
76
69
|
end
|
77
|
-
|
78
|
-
private
|
79
|
-
|
80
|
-
def each_definition(call_tracer)
|
81
|
-
call_tracer.captures.each do |capture|
|
82
|
-
m = capture.method.receiver.to_s.match(/#<Class:([\w:]+)>/)
|
83
|
-
names = capture.argument[:names]
|
84
|
-
if m && m[1]
|
85
|
-
receiver_name = m[1]
|
86
|
-
names.each do |name|
|
87
|
-
yield [receiver_name, "self.#{name}"]
|
88
|
-
end
|
89
|
-
else
|
90
|
-
receiver_name = Utils.module_name(capture.method.receiver) or next
|
91
|
-
names.each do |name|
|
92
|
-
yield [receiver_name, name]
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
70
|
end
|
98
71
|
end
|
data/lib/orthoses/builder.rb
CHANGED
@@ -13,7 +13,7 @@ module Orthoses
|
|
13
13
|
class Builder
|
14
14
|
def initialize(&block)
|
15
15
|
@use = []
|
16
|
-
@
|
16
|
+
@runner = nil
|
17
17
|
instance_eval(&block) if block
|
18
18
|
end
|
19
19
|
|
@@ -37,7 +37,11 @@ module Orthoses
|
|
37
37
|
|
38
38
|
def run(loader)
|
39
39
|
use Store
|
40
|
-
|
40
|
+
reset_runner(loader)
|
41
|
+
end
|
42
|
+
|
43
|
+
def reset_runner(loader)
|
44
|
+
@runner = proc do
|
41
45
|
Orthoses.logger.info("[loader].call start")
|
42
46
|
loader.call.tap do
|
43
47
|
Orthoses.logger.info("[loader].call end")
|
@@ -46,7 +50,7 @@ module Orthoses
|
|
46
50
|
end
|
47
51
|
|
48
52
|
def to_loader
|
49
|
-
@use.reverse.inject(@
|
53
|
+
@use.reverse.inject(@runner) { |current, next_proc| next_proc[current] }
|
50
54
|
end
|
51
55
|
|
52
56
|
def call
|
data/lib/orthoses/constant.rb
CHANGED
@@ -4,71 +4,103 @@ module Orthoses
|
|
4
4
|
class DuplicationChecker
|
5
5
|
def initialize(decl, env: nil)
|
6
6
|
@decl = decl
|
7
|
-
@
|
7
|
+
@known_env = env || Utils.rbs_environment
|
8
|
+
@builder = RBS::DefinitionBuilder.new(env: @known_env)
|
9
|
+
@uniq_map = {}
|
8
10
|
end
|
9
11
|
|
10
12
|
def update_decl
|
11
13
|
return unless @decl.respond_to?(:members)
|
12
14
|
|
13
|
-
|
14
|
-
drop_set_method_definition
|
15
|
-
|
15
|
+
uniq_members
|
16
|
+
drop_set_method_definition
|
17
|
+
drop_by_singleton_instance
|
18
|
+
drop_known_method_definition
|
19
|
+
drop_known_const_definition
|
16
20
|
|
17
|
-
@decl.members.replace(uniq_map.values)
|
21
|
+
@decl.members.replace(@uniq_map.values)
|
22
|
+
|
23
|
+
@uniq_map.clear
|
18
24
|
end
|
19
25
|
|
20
26
|
private
|
21
27
|
|
22
28
|
def uniq_members
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
Orthoses.logger.info("#{@decl.name} \"#{member.location.source}\" was droped since duplication")
|
34
|
-
end
|
29
|
+
@decl.members.each do |member|
|
30
|
+
if member.instance_of?(RBS::AST::Members::MethodDefinition) && member.overloading?
|
31
|
+
# avoid to duplicate and keep order
|
32
|
+
@uniq_map[Object.new] = member
|
33
|
+
else
|
34
|
+
key = member_key(member)
|
35
|
+
drop_member = @uniq_map[key]
|
36
|
+
@uniq_map[key] = member
|
37
|
+
if drop_member
|
38
|
+
Orthoses.logger.info("#{@decl.name} \"#{member.location.source}\" was droped since duplication")
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
38
42
|
end
|
39
43
|
|
40
|
-
def
|
41
|
-
|
44
|
+
def drop_by_singleton_instance
|
45
|
+
singleton_instances = @uniq_map.values.select { |v| v.instance_of?(RBS::AST::Members::MethodDefinition) && v.kind == :singleton_instance }
|
46
|
+
singleton_instances.each do |member|
|
47
|
+
@uniq_map.delete([member.class, member.name, :instance])
|
48
|
+
@uniq_map.delete([member.class, member.name, :singleton])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def drop_set_method_definition
|
53
|
+
attr_accessors = @uniq_map.values.grep(RBS::AST::Members::AttrAccessor)
|
42
54
|
attr_accessors.each do |member|
|
43
|
-
uniq_map.delete([RBS::AST::Members::MethodDefinition, :"#{member.name}=", member.kind])
|
55
|
+
@uniq_map.delete([RBS::AST::Members::MethodDefinition, :"#{member.name}=", member.kind])
|
44
56
|
end
|
45
57
|
end
|
46
58
|
|
47
|
-
def drop_known_method_definition
|
59
|
+
def drop_known_method_definition
|
48
60
|
decl_name = @decl.name.absolute!
|
49
|
-
if m_entry = @
|
61
|
+
if m_entry = @known_env.class_decls[decl_name]
|
50
62
|
m_entry.decls.each do |d|
|
51
|
-
d
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
63
|
+
drop_known_method_definition_recur(d)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def drop_known_method_definition_recur(d)
|
69
|
+
d.decl.members.each do |member|
|
70
|
+
case member
|
71
|
+
when RBS::AST::Members::MethodDefinition
|
72
|
+
if member.kind == :singleton_instance
|
73
|
+
@uniq_map.delete([member.class, member.name, :instance])
|
74
|
+
@uniq_map.delete([member.class, member.name, :singleton])
|
75
|
+
end
|
76
|
+
@uniq_map.delete(member_key(member))
|
77
|
+
when RBS::AST::Members::LocationOnly
|
78
|
+
# ignore
|
79
|
+
when RBS::AST::Members::AttrAccessor
|
80
|
+
@uniq_map.delete([RBS::AST::Members::MethodDefinition, member.name, member.kind])
|
81
|
+
@uniq_map.delete([RBS::AST::Members::MethodDefinition, :"#{member.name}=", member.kind])
|
82
|
+
when RBS::AST::Members::Include
|
83
|
+
if member.name.interface?
|
84
|
+
# If interface is included, it is shared in the same namespace.
|
85
|
+
drop_known_method_definition_recur(@known_env.interface_decls[member.name])
|
86
|
+
else
|
87
|
+
@uniq_map.delete(member_key(member))
|
61
88
|
end
|
89
|
+
else
|
90
|
+
@uniq_map.delete(member_key(member))
|
62
91
|
end
|
63
92
|
end
|
93
|
+
end
|
64
94
|
|
65
|
-
|
95
|
+
def drop_known_const_definition
|
96
|
+
decl_name = @decl.name.absolute!
|
97
|
+
constants_in_uniq_map = @uniq_map.select do |key, value|
|
66
98
|
value.kind_of?(RBS::AST::Declarations::Constant)
|
67
99
|
end
|
68
100
|
constants_in_uniq_map.each do |key, value|
|
69
101
|
type_name = decl_name + value.name
|
70
|
-
if @
|
71
|
-
uniq_map.delete(key)
|
102
|
+
if @known_env.constant_decls[type_name]
|
103
|
+
@uniq_map.delete(key)
|
72
104
|
end
|
73
105
|
end
|
74
106
|
end
|
@@ -42,7 +42,7 @@ module Orthoses
|
|
42
42
|
def write_to(store:)
|
43
43
|
each do |add_content|
|
44
44
|
content = store[add_content.name]
|
45
|
-
content.header
|
45
|
+
content.header = add_content.header
|
46
46
|
content.comment ||= add_content.comment
|
47
47
|
content.concat(add_content.body)
|
48
48
|
end
|
data/lib/orthoses/content.rb
CHANGED
@@ -102,19 +102,7 @@ module Orthoses
|
|
102
102
|
|
103
103
|
case val
|
104
104
|
when Class
|
105
|
-
|
106
|
-
if val.superclass && val.superclass != Object
|
107
|
-
super_module_name = Utils.module_name(val.superclass)
|
108
|
-
|
109
|
-
if super_module_name && super_module_name != "Random::Base" # https://github.com/ruby/rbs/pull/977
|
110
|
-
" < ::#{super_module_name}#{temporary_type_params(super_module_name)}"
|
111
|
-
else
|
112
|
-
nil
|
113
|
-
end
|
114
|
-
else
|
115
|
-
nil
|
116
|
-
end
|
117
|
-
self.header = "class #{Utils.module_name(val)}#{type_params(name)}#{superclass}"
|
105
|
+
self.header = "class #{Utils.module_name(val)}#{type_params(name)}#{build_super_class(val)}"
|
118
106
|
when Module
|
119
107
|
self.header = "module #{Utils.module_name(val)}#{type_params(name)}"
|
120
108
|
else
|
@@ -124,6 +112,25 @@ module Orthoses
|
|
124
112
|
|
125
113
|
private
|
126
114
|
|
115
|
+
def build_super_class(val)
|
116
|
+
return nil unless val.superclass && val.superclass != Object
|
117
|
+
|
118
|
+
begin
|
119
|
+
# check private const
|
120
|
+
eval(val.superclass.to_s)
|
121
|
+
rescue NameError
|
122
|
+
return nil
|
123
|
+
end
|
124
|
+
|
125
|
+
super_module_name = Utils.module_name(val.superclass)
|
126
|
+
return nil unless super_module_name
|
127
|
+
|
128
|
+
# https://github.com/ruby/rbs/pull/977
|
129
|
+
return nil unless super_module_name != "Random::Base"
|
130
|
+
|
131
|
+
" < ::#{super_module_name}#{temporary_type_params(super_module_name)}"
|
132
|
+
end
|
133
|
+
|
127
134
|
class ArrayIO
|
128
135
|
def initialize
|
129
136
|
@outs = []
|
@@ -6,31 +6,62 @@ module Orthoses
|
|
6
6
|
class CreateFileByName
|
7
7
|
prepend Outputable
|
8
8
|
|
9
|
-
def initialize(loader, base_dir
|
9
|
+
def initialize(loader, base_dir: nil, to: nil, header: nil, if: nil, depth: nil, rmtree: false)
|
10
|
+
unless base_dir.nil?
|
11
|
+
warn "[Orthoses::CreateFileByName] base_dir: option is deprecated. Please use to: option instead."
|
12
|
+
end
|
13
|
+
|
14
|
+
to = to || base_dir
|
15
|
+
unless to
|
16
|
+
raise ArgumentError, "should set to: option"
|
17
|
+
end
|
18
|
+
|
19
|
+
relative_path_from_pwd = Pathname(to).expand_path.relative_path_from(Pathname.pwd).to_s
|
20
|
+
unless relative_path_from_pwd == "." || !relative_path_from_pwd.match?(%r{\A[/\.]})
|
21
|
+
raise ArgumentError, "to=\"#{to}\" should be under current dir=\"#{Pathname.pwd}\"."
|
22
|
+
end
|
23
|
+
|
10
24
|
@loader = loader
|
11
|
-
@
|
25
|
+
@to = to
|
12
26
|
@header = header
|
27
|
+
@depth = depth
|
28
|
+
@rmtree = rmtree
|
13
29
|
@if = binding.local_variable_get(:if)
|
14
30
|
end
|
15
31
|
|
16
32
|
using Utils::Underscore
|
17
33
|
|
18
34
|
def call
|
35
|
+
if @rmtree
|
36
|
+
Orthoses.logger.debug("Remove dir #{@to} since `rmtree: true`")
|
37
|
+
Pathname(@to).rmtree rescue nil
|
38
|
+
end
|
39
|
+
|
19
40
|
store = @loader.call
|
20
41
|
|
21
|
-
store.
|
22
|
-
|
42
|
+
store.select! do |name, content|
|
43
|
+
@if.nil? || @if.call(name, content)
|
44
|
+
end
|
45
|
+
grouped = store.group_by do |name, _|
|
46
|
+
splitted = name.to_s.split('::')
|
47
|
+
(@depth ? splitted[0, @depth] : splitted).join('::')
|
48
|
+
end
|
23
49
|
|
24
|
-
|
50
|
+
grouped.each do |group_name, group|
|
51
|
+
file_path = Pathname("#{@to}/#{group_name.split('::').map(&:underscore).join('/')}.rbs")
|
25
52
|
file_path.dirname.mkpath
|
26
53
|
file_path.open('w+') do |out|
|
27
54
|
if @header
|
28
55
|
out.puts @header
|
29
56
|
out.puts
|
30
57
|
end
|
31
|
-
|
58
|
+
group.sort!
|
59
|
+
contents = group.map do |(name, content)|
|
60
|
+
content.to_rbs
|
61
|
+
end.join("\n")
|
62
|
+
out.puts contents
|
63
|
+
Orthoses.logger.info("Generate file to #{file_path.to_s}")
|
32
64
|
end
|
33
|
-
Orthoses.logger.info("Generate file to #{file_path.to_s}")
|
34
65
|
end
|
35
66
|
end
|
36
67
|
end
|
@@ -10,32 +10,44 @@ module Orthoses
|
|
10
10
|
# ...
|
11
11
|
# end
|
12
12
|
class LazyTracePoint < TracePoint
|
13
|
+
METHOD_METHOD = ::Kernel.instance_method(:method)
|
14
|
+
INSTANCE_METHOD_METHOD = ::Module.instance_method(:instance_method)
|
15
|
+
UNBOUND_NAME_METHOD = ::Module.instance_method(:name)
|
16
|
+
METHOD_ADDED_HOOKS = {}
|
17
|
+
SINGLETON_METHOD_ADDED_HOOKS = {}
|
18
|
+
|
13
19
|
# for TracePoint target
|
14
|
-
|
20
|
+
module MethodAddedHook
|
15
21
|
def method_added(id)
|
22
|
+
begin
|
23
|
+
if h = METHOD_ADDED_HOOKS[id]
|
24
|
+
if mod_name = UNBOUND_NAME_METHOD.bind(self).call
|
25
|
+
h[mod_name]&.call(self, id)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
rescue TypeError => e
|
29
|
+
end
|
16
30
|
super
|
17
31
|
end
|
18
|
-
|
19
|
-
::
|
32
|
+
end
|
33
|
+
::Module.prepend MethodAddedHook
|
34
|
+
|
35
|
+
module SignletonMethodAddedHook
|
20
36
|
def singleton_method_added(id)
|
37
|
+
begin
|
38
|
+
if h = SINGLETON_METHOD_ADDED_HOOKS[id]
|
39
|
+
if mod_name = UNBOUND_NAME_METHOD.bind(self).call
|
40
|
+
h[mod_name]&.call(self, id)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue TypeError => e
|
44
|
+
end
|
21
45
|
super
|
22
46
|
end
|
23
|
-
})
|
24
|
-
|
25
|
-
METHOD_METHOD = ::Kernel.instance_method(:method)
|
26
|
-
INSTANCE_METHOD_METHOD = ::Module.instance_method(:instance_method)
|
27
|
-
UNBOUND_NAME_METHOD = ::Module.instance_method(:name)
|
28
|
-
METHOD_ADDED_METHOD = ::Module.instance_method(:method_added)
|
29
|
-
SINGLETON_METHOD_ADDED_METHOD = ::BasicObject.instance_method(:singleton_method_added)
|
30
|
-
|
31
|
-
def initialize(*events, &block)
|
32
|
-
@mod_name = nil
|
33
|
-
@instance_method_id = nil
|
34
|
-
@singleton_method_id = nil
|
35
|
-
super
|
36
47
|
end
|
48
|
+
::BasicObject.prepend SignletonMethodAddedHook
|
37
49
|
|
38
|
-
def enable(target: nil,
|
50
|
+
def enable(target: nil, &block)
|
39
51
|
return super unless target.kind_of?(String)
|
40
52
|
|
41
53
|
case
|
@@ -59,43 +71,25 @@ module Orthoses
|
|
59
71
|
private
|
60
72
|
|
61
73
|
def trace_instance_method(&block)
|
62
|
-
# try to load
|
63
74
|
target = Object.const_get(@mod_name).instance_method(@instance_method_id)
|
64
75
|
enable(target: target, &block)
|
65
76
|
rescue NameError
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
mod_name = UNBOUND_NAME_METHOD.bind(tp.self).call
|
71
|
-
|
72
|
-
next unless mod_name
|
73
|
-
next unless mod_name == @mod_name
|
74
|
-
|
75
|
-
enable(target: INSTANCE_METHOD_METHOD.bind(tp.self).call(id))
|
76
|
-
tp.disable
|
77
|
-
end.enable(target: METHOD_ADDED_METHOD, &block)
|
77
|
+
(METHOD_ADDED_HOOKS[@instance_method_id] ||= {})[@mod_name] = ->(const, id) {
|
78
|
+
enable(target: INSTANCE_METHOD_METHOD.bind(const).call(id))
|
79
|
+
}
|
80
|
+
block&.call
|
78
81
|
ensure
|
79
82
|
disable
|
80
83
|
end
|
81
84
|
|
82
85
|
def trace_singleton_method(&block)
|
83
|
-
# try to load
|
84
86
|
target = Object.const_get(@mod_name).method(@singleton_method_id)
|
85
87
|
enable(target: target, &block)
|
86
88
|
rescue NameError
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
mod_name = UNBOUND_NAME_METHOD.bind(tp.self).call
|
92
|
-
|
93
|
-
next unless mod_name
|
94
|
-
next unless mod_name == @mod_name
|
95
|
-
|
96
|
-
enable(target: METHOD_METHOD.bind(tp.self).call(id))
|
97
|
-
tp.disable
|
98
|
-
end.enable(target: SINGLETON_METHOD_ADDED_METHOD, &block)
|
89
|
+
(SINGLETON_METHOD_ADDED_HOOKS[@singleton_method_id] ||= {})[@mod_name] = ->(const, id) {
|
90
|
+
enable(target: METHOD_METHOD.bind(const).call(id))
|
91
|
+
}
|
92
|
+
block&.call
|
99
93
|
ensure
|
100
94
|
disable
|
101
95
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
class MissingName
|
5
|
+
def initialize(loader)
|
6
|
+
@loader = loader
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
@loader.call.tap do |store|
|
11
|
+
MissingClass.new(store).call
|
12
|
+
MissingModule.new(store).call
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
class MissingClass
|
19
|
+
def initialize(store)
|
20
|
+
@store = store
|
21
|
+
end
|
22
|
+
|
23
|
+
def call
|
24
|
+
@store.values.each do |content|
|
25
|
+
recur(content)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def recur(content)
|
32
|
+
content.auto_header
|
33
|
+
if content.header && content.header.include?("<")
|
34
|
+
_, superclass = content.header.split(/\s*<\s*/, 2)
|
35
|
+
superclass.sub!(/\[.*/, "")
|
36
|
+
new_name = TypeName(superclass).relative!.to_s
|
37
|
+
recur(@store[new_name])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class MissingModule
|
43
|
+
def initialize(store)
|
44
|
+
@store = store
|
45
|
+
end
|
46
|
+
|
47
|
+
def call
|
48
|
+
missings = []
|
49
|
+
@store.keys.each do |key_name|
|
50
|
+
missings.concat split_name(key_name)
|
51
|
+
end
|
52
|
+
missings.uniq!
|
53
|
+
missings.each do |missing|
|
54
|
+
@store[missing].header = "module #{missing}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def split_name(key_name)
|
61
|
+
ret = []
|
62
|
+
|
63
|
+
type_name = TypeName(key_name).relative!
|
64
|
+
if !Utils.rbs_defined_class?(type_name.to_s) && !@store.has_key?(type_name.to_s)
|
65
|
+
ret << type_name.to_s
|
66
|
+
end
|
67
|
+
|
68
|
+
path = type_name.namespace.path
|
69
|
+
path.each_with_index do |sym, index|
|
70
|
+
name = path[0, index + 1].join("::")
|
71
|
+
next if name.empty?
|
72
|
+
if !Utils.rbs_defined_class?(name) && !@store.has_key?(name)
|
73
|
+
ret << name
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
ret
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|