orthoses 0.8.0 → 0.11.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/Gemfile +1 -1
- data/Gemfile.lock +12 -12
- data/README.md +41 -1
- data/lib/orthoses/attribute.rb +0 -2
- data/lib/orthoses/autoload.rb +37 -0
- data/lib/orthoses/call_tracer/capturable.rb +42 -0
- data/lib/orthoses/call_tracer/lazy.rb +22 -0
- data/lib/orthoses/call_tracer.rb +9 -33
- data/lib/orthoses/content/duplication_checker.rb +15 -9
- data/lib/orthoses/content/header_builder.rb +12 -7
- data/lib/orthoses/content.rb +41 -11
- data/lib/orthoses/create_file_by_name.rb +12 -4
- data/lib/orthoses/lazy_trace_point.rb +103 -0
- data/lib/orthoses/load_rbs.rb +3 -1
- data/lib/orthoses/mixin.rb +2 -2
- data/lib/orthoses/object_space_all.rb +1 -3
- data/lib/orthoses/outputable/avoid_recursive_ancestor_error.rb +37 -0
- data/lib/orthoses/outputable.rb +21 -0
- data/lib/orthoses/path_helper.rb +38 -0
- data/lib/orthoses/rbs_prototype_runtime.rb +32 -0
- data/lib/orthoses/utils.rb +9 -4
- data/lib/orthoses/version.rb +1 -1
- data/lib/orthoses/writer.rb +2 -0
- data/lib/orthoses.rb +10 -1
- data/sig/orthoses/attribute/hook.rbs +0 -3
- data/sig/orthoses/autoload/hook.rbs +5 -0
- data/sig/orthoses/autoload.rbs +6 -0
- data/sig/orthoses/builder.rbs +0 -1
- data/sig/orthoses/call_tracer/capturable.rbs +7 -0
- data/sig/orthoses/call_tracer/lazy.rbs +6 -0
- data/sig/orthoses/call_tracer.rbs +0 -1
- data/sig/orthoses/content/array_io.rbs +7 -0
- data/sig/orthoses/content/duplication_checker.rbs +2 -3
- data/sig/orthoses/content/environment.rbs +0 -1
- data/sig/orthoses/content/header_builder.rbs +1 -0
- data/sig/orthoses/content.rbs +4 -2
- data/sig/orthoses/lazy_trace_point.rbs +15 -0
- data/sig/orthoses/load_rbs.rbs +3 -2
- data/sig/orthoses/mixin/hook.rbs +0 -2
- data/sig/orthoses/{avoid_recursive_ancestor_error.rbs → outputable/avoid_recursive_ancestor_error.rbs} +2 -2
- data/sig/orthoses/outputable.rbs +5 -0
- data/sig/orthoses/path_helper.rbs +9 -0
- data/sig/orthoses/rbs_prototype_runtime.rbs +6 -0
- data/sig/orthoses/utils.rbs +1 -13
- data/sig/orthoses.rbs +3 -3
- metadata +21 -5
- data/lib/orthoses/avoid_recursive_ancestor_error.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bbebf8271fbe9859e0e322e0e2d12fbf7a03dc30663309771edeba678674679
|
4
|
+
data.tar.gz: bfdfabbb3110a7c159a7763463077768d76b9cfd14ae77537a87d0abbd8fda74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1093d5bbc23bf0577d915afd70fa34907316bcdd2062e34cdc7506f455636e47e02bb046048e4682c16feeba2bc045985fbae2636bd2e220fc90a66f30e957b
|
7
|
+
data.tar.gz: 84fe1da94bfe208b46ddc1b3607ba7962e1133150fe454ffc8d4e40ca0dd6bc99c4b7e24f41a18f0217913eedd6e5b08e45329d07455e1e5fb913d102c13b67e
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
orthoses (0.
|
4
|
+
orthoses (0.11.0)
|
5
5
|
rbs (~> 2.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activesupport (7.0.3)
|
10
|
+
activesupport (7.0.3.1)
|
11
11
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
12
|
i18n (>= 1.6, < 2)
|
13
13
|
minitest (>= 5.1)
|
@@ -15,45 +15,45 @@ GEM
|
|
15
15
|
ast (2.4.2)
|
16
16
|
concurrent-ruby (1.1.10)
|
17
17
|
ffi (1.15.5)
|
18
|
-
i18n (1.
|
18
|
+
i18n (1.12.0)
|
19
19
|
concurrent-ruby (~> 1.0)
|
20
|
-
language_server-protocol (3.
|
20
|
+
language_server-protocol (3.17.0.0)
|
21
21
|
listen (3.7.1)
|
22
22
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
23
23
|
rb-inotify (~> 0.9, >= 0.9.10)
|
24
|
-
minitest (5.
|
24
|
+
minitest (5.16.3)
|
25
25
|
parallel (1.22.1)
|
26
|
-
parser (3.1.2.
|
26
|
+
parser (3.1.2.1)
|
27
27
|
ast (~> 2.4.1)
|
28
28
|
rainbow (3.1.1)
|
29
29
|
rake (13.0.6)
|
30
30
|
rb-fsevent (0.11.1)
|
31
31
|
rb-inotify (0.10.1)
|
32
32
|
ffi (~> 1.0)
|
33
|
-
rbs (2.
|
33
|
+
rbs (2.6.0)
|
34
34
|
rgot (1.1.0)
|
35
|
-
steep (1.
|
35
|
+
steep (1.1.1)
|
36
36
|
activesupport (>= 5.1)
|
37
37
|
language_server-protocol (>= 3.15, < 4.0)
|
38
38
|
listen (~> 3.0)
|
39
39
|
parallel (>= 1.0.0)
|
40
|
-
parser (>= 3.
|
40
|
+
parser (>= 3.1)
|
41
41
|
rainbow (>= 2.2.2, < 4.0)
|
42
42
|
rbs (>= 2.3.2)
|
43
43
|
terminal-table (>= 2, < 4)
|
44
44
|
terminal-table (3.0.2)
|
45
45
|
unicode-display_width (>= 1.1.1, < 3)
|
46
|
-
tzinfo (2.0.
|
46
|
+
tzinfo (2.0.5)
|
47
47
|
concurrent-ruby (~> 1.0)
|
48
|
-
unicode-display_width (2.
|
48
|
+
unicode-display_width (2.2.0)
|
49
49
|
|
50
50
|
PLATFORMS
|
51
51
|
ruby
|
52
52
|
|
53
53
|
DEPENDENCIES
|
54
|
-
activesupport
|
55
54
|
orthoses!
|
56
55
|
rake (~> 13.0)
|
56
|
+
rbs
|
57
57
|
rgot (~> 1.1)
|
58
58
|
steep
|
59
59
|
|
data/README.md
CHANGED
@@ -41,6 +41,34 @@ Orthoses::Builder.new do
|
|
41
41
|
end.call
|
42
42
|
```
|
43
43
|
|
44
|
+
## Utils
|
45
|
+
|
46
|
+
`Orthoses::Utils` is a collection of useful methods.
|
47
|
+
|
48
|
+
### Orthoses::Utils.each_const_recursive
|
49
|
+
|
50
|
+
Yield const by recursive.
|
51
|
+
|
52
|
+
### Orthoses::Utils.rbs_defined_const?
|
53
|
+
|
54
|
+
Checks if the const name is already defined.
|
55
|
+
|
56
|
+
### Orthoses::Utils.rbs_defined_class?
|
57
|
+
|
58
|
+
Checks if the class name is already defined.
|
59
|
+
|
60
|
+
### Orthoses::Utils.rbs_environment
|
61
|
+
|
62
|
+
Fetch cached `RBS::Environment`.
|
63
|
+
|
64
|
+
### Orthoses::Utils.object_to_rbs
|
65
|
+
|
66
|
+
Convert Ruby object to RBS string.
|
67
|
+
|
68
|
+
### Orthoses::Utils.module_name
|
69
|
+
|
70
|
+
Get true module name by `Module.instance_method(:name).bind(mod).call`.
|
71
|
+
|
44
72
|
## Middlewares
|
45
73
|
|
46
74
|
### Orthoses::Constant
|
@@ -48,10 +76,14 @@ end.call
|
|
48
76
|
Add constant signature to class/module.
|
49
77
|
Signatures are predicted from constant values.
|
50
78
|
|
79
|
+
### Orthoses::Attribute
|
80
|
+
|
81
|
+
Add `attr`, `attr_accessor`, `attr_reader` and `attr_writer` to output RBS.
|
82
|
+
All type set `untyped`.
|
83
|
+
|
51
84
|
### Orthoses::Mixin
|
52
85
|
|
53
86
|
Add module include/extend/prepend definition.
|
54
|
-
It use `Module#{includeed,extended,prepended}` for capture.
|
55
87
|
|
56
88
|
### Orthoses::ObjectSpaceAll
|
57
89
|
|
@@ -115,11 +147,19 @@ Run `rbs prototype rb` command process to `paths` option files.
|
|
115
147
|
`content_filter` option could filter with content decl.
|
116
148
|
`mixin_filter` option could filter with mixin(include, extend, prepend) decl.
|
117
149
|
|
150
|
+
### Orthoses::RBSPrototypeRuntime
|
151
|
+
|
152
|
+
Run `rbs prototype runtime` command process with `patterns` option string.
|
153
|
+
|
118
154
|
### Orthoses::AvoidRecursiveAncestorError
|
119
155
|
|
120
156
|
Mixin a module into an Object class raises `RBS::RecursiveAncestorError` when validation.
|
121
157
|
Please add this middleware then.
|
122
158
|
|
159
|
+
### Orthoses::Autoload
|
160
|
+
|
161
|
+
Force load const defined by `autoload`.
|
162
|
+
|
123
163
|
## Development
|
124
164
|
|
125
165
|
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
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
class Autoload
|
5
|
+
module Hook
|
6
|
+
def autoload(name, path)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(loader)
|
12
|
+
@loader = loader
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
::Module.prepend(Hook)
|
17
|
+
|
18
|
+
autoload = CallTracer.new
|
19
|
+
|
20
|
+
store = autoload.trace(Hook.instance_method(:autoload)) do
|
21
|
+
@loader.call
|
22
|
+
end
|
23
|
+
|
24
|
+
autoload.captures.each do |capture|
|
25
|
+
base_mod = capture.method.receiver
|
26
|
+
name = capture.argument[:name]
|
27
|
+
begin
|
28
|
+
base_mod.const_get(name)
|
29
|
+
rescue NameError, LoadError, ArgumentError => e
|
30
|
+
Orthoses.logger.warn("[Orthoses::Autoload] raise `#{e.message} (#{e.class})` when try to unautoload `#{base_mod}::#{name}`")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
store
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
class CallTracer
|
5
|
+
module Capturable
|
6
|
+
def build_capture(tp)
|
7
|
+
Capture.new(
|
8
|
+
method: build_method(tp),
|
9
|
+
argument: build_argument(tp),
|
10
|
+
)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def build_method(tp)
|
16
|
+
METHOD_METHOD.bind(tp.self).call(tp.method_id)
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_argument(tp)
|
20
|
+
tp.parameters.each_with_object({}) do |op_name, hash|
|
21
|
+
name = op_name[1]
|
22
|
+
case name
|
23
|
+
when :*, :**, :&, nil
|
24
|
+
# skip
|
25
|
+
else
|
26
|
+
hash[name] = tp.binding.local_variable_get(name).then do |var|
|
27
|
+
case var
|
28
|
+
when Module, Thread::Backtrace::Location
|
29
|
+
var
|
30
|
+
else
|
31
|
+
var.dup
|
32
|
+
end
|
33
|
+
rescue => err
|
34
|
+
warn("#dup fail (#{err.class}) #{err.message}")
|
35
|
+
var
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
class CallTracer
|
5
|
+
class Lazy
|
6
|
+
include Capturable
|
7
|
+
|
8
|
+
attr_reader :captures
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@captures = []
|
12
|
+
@lazy_trace_point = LazyTracePoint.new(:call) do |tp|
|
13
|
+
@captures << build_capture(tp)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def trace(name, &block)
|
18
|
+
@lazy_trace_point.enable(target: name, &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/orthoses/call_tracer.rb
CHANGED
@@ -16,46 +16,22 @@ module Orthoses
|
|
16
16
|
class Capture < Struct.new(:method, :argument, keyword_init: true)
|
17
17
|
end
|
18
18
|
|
19
|
+
autoload :Lazy, 'orthoses/call_tracer/lazy'
|
20
|
+
require_relative 'call_tracer/capturable'
|
21
|
+
|
22
|
+
include Capturable
|
23
|
+
|
19
24
|
attr_accessor :captures
|
20
25
|
|
21
26
|
def initialize
|
22
27
|
@captures = []
|
28
|
+
@target_tp = TracePoint.new(:call) do |tp|
|
29
|
+
@captures << build_capture(tp)
|
30
|
+
end
|
23
31
|
end
|
24
32
|
|
25
33
|
def trace(target, &block)
|
26
|
-
|
27
|
-
called_method = tp.self.method(tp.method_id)
|
28
|
-
argument = tp.parameters.each_with_object({}) do |op_name, hash|
|
29
|
-
name = op_name[1]
|
30
|
-
case name
|
31
|
-
when :*, :**, :&, nil
|
32
|
-
# skip
|
33
|
-
else
|
34
|
-
hash[name] = tp.binding.local_variable_get(name).then do |var|
|
35
|
-
case var
|
36
|
-
when Module
|
37
|
-
var # avoid missing name
|
38
|
-
else
|
39
|
-
var.dup
|
40
|
-
end
|
41
|
-
rescue => err
|
42
|
-
case var
|
43
|
-
when Thread::Backtrace::Location
|
44
|
-
# known
|
45
|
-
else
|
46
|
-
warn("#dup fail (#{err.class}) #{err.message}")
|
47
|
-
end
|
48
|
-
var
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
@captures << Capture.new(
|
54
|
-
method: called_method,
|
55
|
-
argument: argument,
|
56
|
-
)
|
57
|
-
end
|
58
|
-
t.enable(target: target, &block)
|
34
|
+
@target_tp.enable(target: target, &block)
|
59
35
|
end
|
60
36
|
end
|
61
37
|
end
|
@@ -2,18 +2,20 @@ module Orthoses
|
|
2
2
|
class Content
|
3
3
|
# Check and drop duplication method, const etc...
|
4
4
|
class DuplicationChecker
|
5
|
-
def initialize(decl)
|
5
|
+
def initialize(decl, env: nil)
|
6
6
|
@decl = decl
|
7
|
+
@env = env || Utils.rbs_environment(collection: true)
|
7
8
|
end
|
8
9
|
|
9
10
|
def update_decl
|
11
|
+
return unless @decl.respond_to?(:members)
|
10
12
|
uniq_map = {}
|
11
13
|
@decl.members.each do |member|
|
12
14
|
key = member_key(member)
|
13
15
|
drop_member = uniq_map[key]
|
14
16
|
uniq_map[key] = member
|
15
17
|
if drop_member
|
16
|
-
Orthoses.logger.
|
18
|
+
Orthoses.logger.info("#{@decl.name} \"#{member.location.source}\" was droped since duplication")
|
17
19
|
end
|
18
20
|
end
|
19
21
|
drop_known_method_definition(uniq_map)
|
@@ -23,20 +25,24 @@ module Orthoses
|
|
23
25
|
private
|
24
26
|
|
25
27
|
def drop_known_method_definition(uniq_map)
|
26
|
-
|
27
|
-
if m_entry = env.class_decls[
|
28
|
+
decl_name = @decl.name.absolute!
|
29
|
+
if m_entry = @env.class_decls[decl_name]
|
28
30
|
m_entry.decls.each do |d|
|
29
31
|
d.decl.members.grep_v(RBS::AST::Members::LocationOnly).each do |member|
|
30
32
|
uniq_map.delete(member_key(member))
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
34
|
-
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
constants_in_uniq_map = uniq_map.select do |key, value|
|
38
|
+
value.kind_of?(RBS::AST::Declarations::Constant)
|
39
|
+
end
|
40
|
+
constants_in_uniq_map.each do |key, value|
|
41
|
+
type_name = decl_name + value.name
|
42
|
+
if @env.constant_decls[type_name]
|
43
|
+
uniq_map.delete(key)
|
44
|
+
end
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
def member_key(member)
|
@@ -43,13 +43,9 @@ module Orthoses
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def build_super_class(primary)
|
46
|
-
return nil if primary.decl.super_class.then { |s| s.nil? || s.name.relative!.to_s.then { |n| n == "Object" || n == "Random::Base" } }
|
47
|
-
|
48
|
-
context = primary.outer.length.times.map do |i|
|
49
|
-
primary.outer[0, i + 1].map(&:name).inject(:+).to_namespace.absolute!
|
50
|
-
end
|
51
|
-
context.push(RBS::Namespace.root)
|
46
|
+
return nil if primary.decl.super_class.then { |s| s.nil? || s.name.relative!.to_s.then { |n| n == "Object" || n == "Random::Base" || n.start_with?("RBS::Unnamed") } }
|
52
47
|
|
48
|
+
context = build_context(entry: primary)
|
53
49
|
super_class_name = @resolver.resolve(primary.decl.super_class.name, context: context) || primary.decl.super_class.name
|
54
50
|
if primary.decl.super_class.args.empty?
|
55
51
|
if super_class_entry = @env.class_decls[super_class_name]
|
@@ -65,7 +61,16 @@ module Orthoses
|
|
65
61
|
|
66
62
|
def build_interface(entry:, name_hint: nil)
|
67
63
|
full_name = name_hint || entry.decl.name.relative!
|
68
|
-
|
64
|
+
context = build_context(entry: entry)
|
65
|
+
resolved_name = @resolver.resolve(full_name, context: context) || full_name
|
66
|
+
"interface #{name_and_params(resolved_name.relative!, entry.decl.type_params)}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def build_context(entry:)
|
70
|
+
context = entry.outer.length.times.map do |i|
|
71
|
+
entry.outer[0, i + 1].map(&:name).inject(:+).to_namespace.absolute!
|
72
|
+
end
|
73
|
+
context.push(RBS::Namespace.root)
|
69
74
|
end
|
70
75
|
|
71
76
|
def name_and_params(name, params)
|
data/lib/orthoses/content.rb
CHANGED
@@ -35,6 +35,14 @@ module Orthoses
|
|
35
35
|
@body.concat(other)
|
36
36
|
end
|
37
37
|
|
38
|
+
def empty?
|
39
|
+
@body.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete(val)
|
43
|
+
@body.delete(val)
|
44
|
+
end
|
45
|
+
|
38
46
|
def to_rbs
|
39
47
|
auto_header
|
40
48
|
uniqed_body_string
|
@@ -45,14 +53,36 @@ module Orthoses
|
|
45
53
|
uniqed_body_decl
|
46
54
|
end
|
47
55
|
|
48
|
-
|
56
|
+
def uniq!
|
57
|
+
out = ArrayIO.new
|
58
|
+
writer = RBS::Writer.new(out: out)
|
59
|
+
to_decl.members.each do |member|
|
60
|
+
writer.write_member(member)
|
61
|
+
end
|
62
|
+
@body.replace(out.to_a)
|
63
|
+
end
|
49
64
|
|
50
65
|
def original_rbs
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
66
|
+
a = [@header]
|
67
|
+
a << " #{@body.join("\n ")}" if @body.length > 0
|
68
|
+
a << "end"
|
69
|
+
a.join("\n")
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
class ArrayIO
|
75
|
+
def initialize
|
76
|
+
@outs = []
|
77
|
+
end
|
78
|
+
|
79
|
+
def puts(line)
|
80
|
+
@outs << line
|
81
|
+
end
|
82
|
+
|
83
|
+
def to_a
|
84
|
+
@outs
|
85
|
+
end
|
56
86
|
end
|
57
87
|
|
58
88
|
def uniqed_body_string
|
@@ -81,11 +111,6 @@ module Orthoses
|
|
81
111
|
end
|
82
112
|
|
83
113
|
def auto_header
|
84
|
-
if name.split('::').last.start_with?('_')
|
85
|
-
self.header = "interface #{name}"
|
86
|
-
return
|
87
|
-
end
|
88
|
-
|
89
114
|
env = Utils.rbs_environment(collection: true)
|
90
115
|
if entry = env.class_decls[TypeName(name).absolute!]
|
91
116
|
@header = Content::HeaderBuilder.new(env: env).build(entry: entry)
|
@@ -94,6 +119,11 @@ module Orthoses
|
|
94
119
|
|
95
120
|
return unless @header.nil?
|
96
121
|
|
122
|
+
if name.split('::').last.start_with?('_')
|
123
|
+
self.header = "interface #{name}"
|
124
|
+
return
|
125
|
+
end
|
126
|
+
|
97
127
|
val = Object.const_get(name)
|
98
128
|
|
99
129
|
case val
|
@@ -1,11 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'orthoses/outputable'
|
4
|
+
|
3
5
|
module Orthoses
|
4
6
|
class CreateFileByName
|
5
|
-
|
7
|
+
prepend Outputable
|
8
|
+
|
9
|
+
def initialize(loader, base_dir:, header: nil, if: nil)
|
6
10
|
@loader = loader
|
7
11
|
@base_dir = base_dir
|
8
12
|
@header = header
|
13
|
+
@if = binding.local_variable_get(:if)
|
9
14
|
end
|
10
15
|
|
11
16
|
using(Module.new {
|
@@ -28,12 +33,15 @@ module Orthoses
|
|
28
33
|
store = @loader.call
|
29
34
|
|
30
35
|
store.each do |name, content|
|
31
|
-
|
32
|
-
content.
|
36
|
+
begin
|
37
|
+
content.uniq!
|
33
38
|
rescue NameError, LoadError => err
|
34
39
|
Orthoses.logger.error(err.inspect)
|
35
40
|
next
|
36
41
|
end
|
42
|
+
|
43
|
+
next unless @if.nil? || @if.call(name, content)
|
44
|
+
|
37
45
|
file_path = Pathname("#{@base_dir}/#{name.to_s.split('::').map(&:underscore).join('/')}.rbs")
|
38
46
|
file_path.dirname.mkpath
|
39
47
|
file_path.open('w+') do |out|
|
@@ -41,7 +49,7 @@ module Orthoses
|
|
41
49
|
out.puts @header
|
42
50
|
out.puts
|
43
51
|
end
|
44
|
-
out.puts
|
52
|
+
out.puts content.original_rbs
|
45
53
|
end
|
46
54
|
Orthoses.logger.info("Generate file to #{file_path.to_s}")
|
47
55
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Orthoses
|
4
|
+
# TracePoint wrapper that allows setting hooks
|
5
|
+
# even if the target is undefined
|
6
|
+
# LazyTracePoint.new(:call) do |tp|
|
7
|
+
# ...
|
8
|
+
# end.enable(target: 'Class#class_attribute') do
|
9
|
+
# require 'active_support/core_ext/class/attribute'
|
10
|
+
# ...
|
11
|
+
# end
|
12
|
+
class LazyTracePoint < TracePoint
|
13
|
+
# for TracePoint target
|
14
|
+
::Module.prepend(Module.new{
|
15
|
+
def method_added(id)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
})
|
19
|
+
::BasicObject.prepend(Module.new{
|
20
|
+
def singleton_method_added(id)
|
21
|
+
super
|
22
|
+
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
|
+
end
|
37
|
+
|
38
|
+
def enable(target: nil, target_line: nil, target_thread: nil, &block)
|
39
|
+
return super unless target.kind_of?(String)
|
40
|
+
|
41
|
+
case
|
42
|
+
when target.include?('#')
|
43
|
+
@mod_name, instance_method_id = target.split('#', 2)
|
44
|
+
@instance_method_id = instance_method_id.to_sym
|
45
|
+
@singleton_method_id = nil
|
46
|
+
|
47
|
+
trace_instance_method(&block)
|
48
|
+
when target.include?('.')
|
49
|
+
@mod_name, singleton_method_id = target.split('.', 2)
|
50
|
+
@singleton_method_id = singleton_method_id.to_sym
|
51
|
+
@instance_method_id = nil
|
52
|
+
|
53
|
+
trace_singleton_method(&block)
|
54
|
+
else
|
55
|
+
raise ArgumentError, "argument shuold be 'Foo#foo' or 'Foo.foo' format"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def trace_instance_method(&block)
|
62
|
+
# try to load
|
63
|
+
target = Object.const_get(@mod_name).instance_method(@instance_method_id)
|
64
|
+
enable(target: target, &block)
|
65
|
+
rescue NameError
|
66
|
+
TracePoint.new(:call) do |tp|
|
67
|
+
id = tp.binding.local_variable_get(:id)
|
68
|
+
next unless id == @instance_method_id
|
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)
|
78
|
+
ensure
|
79
|
+
disable
|
80
|
+
end
|
81
|
+
|
82
|
+
def trace_singleton_method(&block)
|
83
|
+
# try to load
|
84
|
+
target = Object.const_get(@mod_name).method(@singleton_method_id)
|
85
|
+
enable(target: target, &block)
|
86
|
+
rescue NameError
|
87
|
+
TracePoint.new(:call) do |tp|
|
88
|
+
id = tp.binding.local_variable_get(:id)
|
89
|
+
next unless id == @singleton_method_id
|
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)
|
99
|
+
ensure
|
100
|
+
disable
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/orthoses/load_rbs.rb
CHANGED
@@ -11,7 +11,9 @@ module Orthoses
|
|
11
11
|
|
12
12
|
def call
|
13
13
|
@loader.call.tap do |store|
|
14
|
-
|
14
|
+
paths = @paths
|
15
|
+
paths = paths.call if paths.instance_of?(Proc)
|
16
|
+
env = Content::Environment.load_from_paths(paths.to_a)
|
15
17
|
env.write_to(store: store)
|
16
18
|
end
|
17
19
|
end
|
data/lib/orthoses/mixin.rb
CHANGED
@@ -34,8 +34,6 @@ module Orthoses
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
store["Module"].body.delete("prepend Orthoses::Mixin::Hook")
|
38
|
-
|
39
37
|
collect_definitions(store, include, :include)
|
40
38
|
collect_definitions(store, extend, :extend)
|
41
39
|
collect_definitions(store, prepend, :prepend)
|
@@ -58,6 +56,8 @@ module Orthoses
|
|
58
56
|
mod_name = Utils.module_name(mod)
|
59
57
|
next unless mod_name
|
60
58
|
|
59
|
+
next if mod_name.start_with?("Orthoses")
|
60
|
+
|
61
61
|
known_type_params = Utils.known_type_params(mod)
|
62
62
|
next unless known_type_params.nil? || known_type_params.empty?
|
63
63
|
|