appmap 0.34.4 → 0.34.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +3 -0
- data/README.md +9 -0
- data/ext/appmap/appmap.c +63 -4
- data/lib/appmap/hook.rb +3 -0
- data/lib/appmap/hook/method.rb +27 -24
- data/lib/appmap/util.rb +1 -1
- data/lib/appmap/version.rb +1 -1
- data/spec/hook_spec.rb +7 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b4318e1ef7e025a8f616022cefd323784e7b8ee8ccf06b1b7167b9937e860df
|
4
|
+
data.tar.gz: c6a743f2c7f4ebe8cd58f7ae971b5dae15791bc808dab9d4dcf87f4971986818
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f271a71bb8bffa7004d054ae91646c9c93a476b15cbe80c459a9cafcb13ab0169be6c8a2db9b8cc993c3bc767deef4c9c0ca4befe6bd6881cf2d93c7b692b64
|
7
|
+
data.tar.gz: 3b6c5067a325fa2a0aed71b5ed92179196061cd6cfa015f907a25dab798e757c2cd53efbd028513df1f22cc2e2b8aa9345f8d19aa27018eccfbee4cd39766ece
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -57,6 +57,15 @@ end
|
|
57
57
|
|
58
58
|
Then install with `bundle`.
|
59
59
|
|
60
|
+
**Railtie**
|
61
|
+
|
62
|
+
If you are using Ruby on Rails, require the railtie after Rails is loaded.
|
63
|
+
|
64
|
+
```
|
65
|
+
# application.rb is a good place to do this, along with all the other railties.
|
66
|
+
require 'appmap/railtie'
|
67
|
+
```
|
68
|
+
|
60
69
|
# Configuration
|
61
70
|
|
62
71
|
When you run your program, the `appmap` gem reads configuration settings from `appmap.yml`. Here's a sample configuration
|
data/ext/appmap/appmap.c
CHANGED
@@ -8,7 +8,12 @@
|
|
8
8
|
(!SPECIAL_CONST_P(obj) && \
|
9
9
|
(BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
|
10
10
|
|
11
|
-
|
11
|
+
#define ARITIES_KEY "__arities__"
|
12
|
+
|
13
|
+
VALUE am_AppMapHook;
|
14
|
+
|
15
|
+
static VALUE
|
16
|
+
singleton_method_owner_name(VALUE klass, VALUE method)
|
12
17
|
{
|
13
18
|
VALUE owner = rb_funcall(method, rb_intern("owner"), 0);
|
14
19
|
VALUE attached = rb_ivar_get(owner, rb_intern("__attached__"));
|
@@ -27,10 +32,64 @@ static VALUE singleton_method_owner_name(VALUE klass, VALUE method)
|
|
27
32
|
// #to_s on the method's owner and hope for the best.
|
28
33
|
return rb_funcall(owner, rb_intern("to_s"), 0);
|
29
34
|
}
|
30
|
-
|
35
|
+
|
36
|
+
|
37
|
+
static VALUE
|
38
|
+
am_define_method_with_arity(VALUE mod, VALUE name, VALUE arity, VALUE proc)
|
39
|
+
{
|
40
|
+
VALUE arities_key = rb_intern(ARITIES_KEY);
|
41
|
+
VALUE arities = rb_ivar_get(mod, arities_key);
|
42
|
+
|
43
|
+
if (arities == Qundef || NIL_P(arities)) {
|
44
|
+
arities = rb_hash_new();
|
45
|
+
rb_ivar_set(mod, arities_key, arities);
|
46
|
+
}
|
47
|
+
rb_hash_aset(arities, name, arity);
|
48
|
+
|
49
|
+
return rb_funcall(mod, rb_intern("define_method"), 2, name, proc);
|
50
|
+
}
|
51
|
+
|
52
|
+
static VALUE
|
53
|
+
am_get_method_arity(VALUE method, VALUE orig_arity_method)
|
54
|
+
{
|
55
|
+
VALUE owner = rb_funcall(method, rb_intern("owner"), 0);
|
56
|
+
VALUE arities = rb_ivar_get(owner, rb_intern(ARITIES_KEY));
|
57
|
+
VALUE name = rb_funcall(method, rb_intern("name"), 0);
|
58
|
+
VALUE arity = Qnil;
|
59
|
+
// See if we saved an arity for the method.
|
60
|
+
if (!NIL_P(arities)) {
|
61
|
+
arity = rb_hash_aref(arities, name);
|
62
|
+
}
|
63
|
+
// Didn't find one, call the original method.
|
64
|
+
if (NIL_P(arity)) {
|
65
|
+
VALUE bound_method = rb_funcall(orig_arity_method, rb_intern("bind"), 1, method);
|
66
|
+
arity = rb_funcall(bound_method, rb_intern("call"), 0);
|
67
|
+
}
|
68
|
+
|
69
|
+
return arity;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE
|
73
|
+
am_unbound_method_arity(VALUE method)
|
74
|
+
{
|
75
|
+
VALUE orig_unbound_method_arity = rb_ivar_get(am_AppMapHook, rb_intern("@unbound_method_arity"));
|
76
|
+
return am_get_method_arity(method, orig_unbound_method_arity);
|
77
|
+
}
|
78
|
+
|
79
|
+
static VALUE
|
80
|
+
am_method_arity(VALUE method)
|
81
|
+
{
|
82
|
+
VALUE orig_method_arity = rb_ivar_get(am_AppMapHook, rb_intern("@method_arity"));
|
83
|
+
return am_get_method_arity(method, orig_method_arity);
|
84
|
+
}
|
85
|
+
|
31
86
|
void Init_appmap() {
|
32
87
|
VALUE appmap = rb_define_module("AppMap");
|
33
|
-
|
88
|
+
am_AppMapHook = rb_define_class_under(appmap, "Hook", rb_cObject);
|
89
|
+
|
90
|
+
rb_define_singleton_method(am_AppMapHook, "singleton_method_owner_name", singleton_method_owner_name, 1);
|
34
91
|
|
35
|
-
|
92
|
+
rb_define_method(rb_cModule, "define_method_with_arity", am_define_method_with_arity, 3);
|
93
|
+
rb_define_method(rb_cUnboundMethod, "arity", am_unbound_method_arity, 0);
|
94
|
+
rb_define_method(rb_cMethod, "arity", am_method_arity, 0);
|
36
95
|
}
|
data/lib/appmap/hook.rb
CHANGED
data/lib/appmap/hook/method.rb
CHANGED
@@ -30,7 +30,7 @@ module AppMap
|
|
30
30
|
msg = if method_display_name
|
31
31
|
"#{method_display_name}"
|
32
32
|
else
|
33
|
-
"#{hook_method.name} (class resolution
|
33
|
+
"#{hook_method.name} (class resolution deferred)"
|
34
34
|
end
|
35
35
|
warn "AppMap: Hooking " + msg
|
36
36
|
end
|
@@ -41,36 +41,39 @@ module AppMap
|
|
41
41
|
after_hook = self.method(:after_hook)
|
42
42
|
with_disabled_hook = self.method(:with_disabled_hook)
|
43
43
|
|
44
|
-
|
45
|
-
|
44
|
+
hook_method_def = nil
|
45
|
+
hook_class.instance_eval do
|
46
|
+
hook_method_def = Proc.new do |*args, &block|
|
47
|
+
instance_method = hook_method.bind(self).to_proc
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
# We may not have gotten the class for the method during
|
50
|
+
# initialization (e.g. for a singleton method on an embedded
|
51
|
+
# struct), so make sure we have it now.
|
52
|
+
defined_class,_ = Hook.qualify_method_name(hook_method) unless defined_class
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
54
|
+
hook_disabled = Thread.current[HOOK_DISABLE_KEY]
|
55
|
+
enabled = true if !hook_disabled && AppMap.tracing.enabled?
|
56
|
+
return instance_method.call(*args, &block) unless enabled
|
55
57
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
call_event, start_time = with_disabled_hook.() do
|
59
|
+
before_hook.(self, defined_class, args)
|
60
|
+
end
|
61
|
+
return_value = nil
|
62
|
+
exception = nil
|
63
|
+
begin
|
64
|
+
return_value = instance_method.(*args, &block)
|
65
|
+
rescue
|
66
|
+
exception = $ERROR_INFO
|
67
|
+
raise
|
68
|
+
ensure
|
69
|
+
with_disabled_hook.() do
|
70
|
+
after_hook.(call_event, start_time, return_value, exception)
|
71
|
+
end
|
69
72
|
end
|
70
73
|
end
|
71
74
|
end
|
75
|
+
hook_class.define_method_with_arity(hook_method.name, hook_method.arity, hook_method_def)
|
72
76
|
end
|
73
|
-
|
74
77
|
protected
|
75
78
|
|
76
79
|
def before_hook(receiver, defined_class, args)
|
data/lib/appmap/util.rb
CHANGED
@@ -43,7 +43,7 @@ module AppMap
|
|
43
43
|
require 'hashie'
|
44
44
|
h.extend(Hashie::Extensions::DeepLocate)
|
45
45
|
keys = %i(path location)
|
46
|
-
|
46
|
+
h.deep_locate ->(k,v,o) {
|
47
47
|
next unless keys.include?(k)
|
48
48
|
|
49
49
|
fix = ->(v) {v.gsub(%r{#{Gem.dir}/gems/.*(?=lib)}, '')}
|
data/lib/appmap/version.rb
CHANGED
data/spec/hook_spec.rb
CHANGED
@@ -669,4 +669,11 @@ describe 'AppMap class Hooking', docker: false do
|
|
669
669
|
end
|
670
670
|
end
|
671
671
|
end
|
672
|
+
|
673
|
+
it "preserves the arity of hooked methods" do
|
674
|
+
invoke_test_file 'spec/fixtures/hook/instance_method.rb' do
|
675
|
+
expect(InstanceMethod.instance_method(:say_echo).arity).to be(1)
|
676
|
+
expect(InstanceMethod.new.method(:say_echo).arity).to be(1)
|
677
|
+
end
|
678
|
+
end
|
672
679
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: appmap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.34.
|
4
|
+
version: 0.34.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Gilpin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-09-
|
11
|
+
date: 2020-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|