appmap 0.31.0 → 0.34.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.rbenv-gemsets +1 -0
- data/CHANGELOG.md +22 -0
- data/README.md +38 -4
- data/Rakefile +10 -3
- data/appmap.gemspec +5 -0
- data/ext/appmap/appmap.c +26 -0
- data/ext/appmap/extconf.rb +6 -0
- data/lib/appmap.rb +23 -10
- data/lib/appmap/class_map.rb +13 -7
- data/lib/appmap/config.rb +54 -30
- data/lib/appmap/cucumber.rb +19 -2
- data/lib/appmap/event.rb +25 -16
- data/lib/appmap/hook.rb +52 -77
- data/lib/appmap/hook/method.rb +103 -0
- data/lib/appmap/open.rb +57 -0
- data/lib/appmap/rails/action_handler.rb +7 -7
- data/lib/appmap/rails/sql_handler.rb +10 -8
- data/lib/appmap/rspec.rb +1 -1
- data/lib/appmap/trace.rb +7 -7
- data/lib/appmap/util.rb +19 -0
- data/lib/appmap/version.rb +1 -1
- data/spec/abstract_controller4_base_spec.rb +1 -1
- data/spec/abstract_controller_base_spec.rb +9 -2
- data/spec/fixtures/hook/instance_method.rb +4 -0
- data/spec/fixtures/hook/singleton_method.rb +21 -12
- data/spec/hook_spec.rb +140 -44
- data/spec/open_spec.rb +19 -0
- data/spec/record_sql_rails_pg_spec.rb +56 -33
- data/test/cli_test.rb +12 -2
- data/test/fixtures/openssl_recorder/Gemfile +3 -0
- data/test/fixtures/openssl_recorder/appmap.yml +3 -0
- data/{spec/fixtures/hook/openssl_sign.rb → test/fixtures/openssl_recorder/lib/openssl_cert_sign.rb} +11 -4
- data/test/fixtures/openssl_recorder/lib/openssl_encrypt.rb +34 -0
- data/test/fixtures/openssl_recorder/lib/openssl_key_sign.rb +28 -0
- data/test/openssl_test.rb +203 -0
- data/test/test_helper.rb +1 -0
- metadata +58 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 81605d2c95140e963991e04af89235ee903cce0e3a86b2477f0f80961704e2d6
|
4
|
+
data.tar.gz: 7e526d9ffbc559bb3968b8a973dcd757147676d17a5028f737192fd8956d1b43
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a34ba2662d48a7e0083e16d6abe4693b57711f9ac0020da6631ca6c40172aeb8f3ef734edd504cec00f2f437742e45fc0cf631b425cb960c9d51239556bc461
|
7
|
+
data.tar.gz: 156f126aac6f63e819c175d6b4d481679cbced9184007871c12fb174f187198afd8e7788befc4ab0ff35b10293e1e163eee25a985b35bd93853c03aa8268d192
|
data/.gitignore
CHANGED
data/.rbenv-gemsets
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
appmap-ruby
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
# v0.34.2
|
2
|
+
* Add an extension that gets the name of the owner of a singleton method without calling
|
3
|
+
any methods that may have been redefined (e.g. `#to_s` or `.name`).
|
4
|
+
|
5
|
+
# v0.34.1
|
6
|
+
* Ensure that capturing events doesn't change the behavior of a hooked method that uses
|
7
|
+
`Time.now`. For example, if a test expects that `Time.now` will be called a certain
|
8
|
+
number of times by a hooked method, that expectation will now be met.
|
9
|
+
* Make sure `appmap/cucumber` requires `appmap`.
|
10
|
+
|
11
|
+
# v0.34.0
|
12
|
+
|
13
|
+
* Records builtin security and I/O methods from `OpenSSL`, `Net`, and `IO`.
|
14
|
+
|
15
|
+
# v0.33.0
|
16
|
+
|
17
|
+
* Added command `AppMap.open` to open an AppMap in the browser.
|
18
|
+
|
19
|
+
# v0.32.0
|
20
|
+
|
21
|
+
* Removes un-necessary fields from `return` events.
|
22
|
+
|
1
23
|
# v0.31.0
|
2
24
|
|
3
25
|
* Add the ability to hook methods by default, and optionally add labels to them in the
|
data/README.md
CHANGED
@@ -33,7 +33,7 @@ There are several ways to record AppMaps of your Ruby program using the `appmap`
|
|
33
33
|
|
34
34
|
Once you have recorded some AppMaps (for example, by running RSpec tests), you use the `appland upload` command
|
35
35
|
to upload them to the AppLand server. This command, and some others, is provided
|
36
|
-
by the [AppLand CLI](https://github.com/applandinc/appland-cli/releases)
|
36
|
+
by the [AppLand CLI](https://github.com/applandinc/appland-cli/releases).
|
37
37
|
Then, on the [AppLand website](https://app.land), you can
|
38
38
|
visualize the design of your code and share links with collaborators.
|
39
39
|
|
@@ -87,12 +87,25 @@ Each entry in the `packages` list is a YAML object which has the following keys:
|
|
87
87
|
|
88
88
|
To record RSpec tests, follow these additional steps:
|
89
89
|
|
90
|
-
1) Require `appmap/rspec` in your `spec_helper.rb
|
90
|
+
1) Require `appmap/rspec` in your `spec_helper.rb` before any other classes are loaded.
|
91
91
|
|
92
92
|
```ruby
|
93
93
|
require 'appmap/rspec'
|
94
94
|
```
|
95
95
|
|
96
|
+
Note that `spec_helper.rb` in a Rails project typically loads the application's classes this way:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
require File.expand_path("../../config/environment", __FILE__)
|
100
|
+
```
|
101
|
+
|
102
|
+
and `appmap/rspec` must be required before this:
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
require 'appmap/rspec'
|
106
|
+
require File.expand_path("../../config/environment", __FILE__)
|
107
|
+
```
|
108
|
+
|
96
109
|
2) *Optional* Add `feature: '<feature name>'` and `feature_group: '<feature group name>'` annotations to your
|
97
110
|
examples.
|
98
111
|
|
@@ -136,6 +149,19 @@ To record Minitest tests, follow these additional steps:
|
|
136
149
|
require 'appmap/minitest'
|
137
150
|
```
|
138
151
|
|
152
|
+
Note that `test_helper.rb` in a Rails project typically loads the application's classes this way:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
require_relative '../config/environment'
|
156
|
+
```
|
157
|
+
|
158
|
+
and `appmap/rspec` must be required before this:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
require 'appmap/rspec'
|
162
|
+
require_relative '../config/environment'
|
163
|
+
```
|
164
|
+
|
139
165
|
2) Run the tests with the environment variable `APPMAP=true`:
|
140
166
|
|
141
167
|
```sh-session
|
@@ -159,6 +185,8 @@ To record Cucumber tests, follow these additional steps:
|
|
159
185
|
require 'appmap/cucumber'
|
160
186
|
```
|
161
187
|
|
188
|
+
Be sure to require it before `config/environment` is required.
|
189
|
+
|
162
190
|
2) Create an `Around` hook in `support/hooks.rb` to record the scenario:
|
163
191
|
|
164
192
|
|
@@ -239,7 +267,13 @@ $ bundle config local.appmap $(pwd)
|
|
239
267
|
Run the tests via `rake`:
|
240
268
|
```
|
241
269
|
$ bundle exec rake test
|
242
|
-
```
|
270
|
+
```
|
271
|
+
|
272
|
+
The `test` target will build the native extension first, then run the tests. If you need
|
273
|
+
to build the extension separately, run
|
274
|
+
```
|
275
|
+
$ bundle exec rake compile
|
276
|
+
```
|
243
277
|
|
244
278
|
## Using fixture apps
|
245
279
|
|
@@ -258,7 +292,7 @@ resources such as a PostgreSQL database.
|
|
258
292
|
To build the fixture container images, first run:
|
259
293
|
|
260
294
|
```sh-session
|
261
|
-
$ bundle exec rake fixtures:all
|
295
|
+
$ bundle exec rake build:fixtures:all
|
262
296
|
```
|
263
297
|
|
264
298
|
This will build the `appmap.gem`, along with a Docker image for each fixture app.
|
data/Rakefile
CHANGED
@@ -6,6 +6,13 @@ require 'rdoc/task'
|
|
6
6
|
|
7
7
|
require 'open3'
|
8
8
|
|
9
|
+
require "rake/extensiontask"
|
10
|
+
|
11
|
+
desc 'build the native extension'
|
12
|
+
Rake::ExtensionTask.new("appmap") do |ext|
|
13
|
+
ext.lib_dir = "lib/appmap"
|
14
|
+
end
|
15
|
+
|
9
16
|
namespace 'gem' do
|
10
17
|
require 'bundler/gem_tasks'
|
11
18
|
end
|
@@ -104,7 +111,7 @@ end
|
|
104
111
|
namespace :spec do
|
105
112
|
RUBY_VERSIONS.each do |ruby_version|
|
106
113
|
desc ruby_version
|
107
|
-
task ruby_version, [:specs] => ["build:fixtures:#{ruby_version}:all"] do |_, task_args|
|
114
|
+
task ruby_version, [:specs] => ["compile", "build:fixtures:#{ruby_version}:all"] do |_, task_args|
|
108
115
|
run_specs(ruby_version, task_args)
|
109
116
|
end.tap do|t|
|
110
117
|
desc "Run all specs"
|
@@ -119,13 +126,13 @@ Rake::RDocTask.new do |rd|
|
|
119
126
|
rd.title = 'AppMap'
|
120
127
|
end
|
121
128
|
|
122
|
-
Rake::TestTask.new(:
|
129
|
+
Rake::TestTask.new(minitest: 'compile') do |t|
|
123
130
|
t.libs << 'test'
|
124
131
|
t.libs << 'lib'
|
125
132
|
t.test_files = FileList['test/*_test.rb']
|
126
133
|
end
|
127
134
|
|
128
|
-
task spec:
|
135
|
+
task spec: %i[spec:all]
|
129
136
|
|
130
137
|
task test: %i[spec:all minitest]
|
131
138
|
|
data/appmap.gemspec
CHANGED
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
19
|
spec.files = `git ls-files --no-deleted`.split("
|
20
20
|
")
|
21
|
+
spec.extensions << "ext/appmap/extconf.rb"
|
22
|
+
|
21
23
|
spec.bindir = 'exe'
|
22
24
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
25
|
spec.require_paths = ['lib']
|
@@ -26,6 +28,7 @@ Gem::Specification.new do |spec|
|
|
26
28
|
spec.add_dependency 'faraday'
|
27
29
|
spec.add_dependency 'gli'
|
28
30
|
spec.add_dependency 'parser'
|
31
|
+
spec.add_dependency 'rack'
|
29
32
|
|
30
33
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
31
34
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
@@ -33,6 +36,7 @@ Gem::Specification.new do |spec|
|
|
33
36
|
spec.add_development_dependency 'rake', '>= 12.3.3'
|
34
37
|
spec.add_development_dependency 'rdoc'
|
35
38
|
spec.add_development_dependency 'rubocop'
|
39
|
+
spec.add_development_dependency "rake-compiler"
|
36
40
|
|
37
41
|
# Testing
|
38
42
|
spec.add_development_dependency 'climate_control'
|
@@ -41,4 +45,5 @@ Gem::Specification.new do |spec|
|
|
41
45
|
spec.add_development_dependency 'rspec'
|
42
46
|
spec.add_development_dependency 'selenium-webdriver'
|
43
47
|
spec.add_development_dependency 'webdrivers', '~> 4.0'
|
48
|
+
spec.add_development_dependency 'timecop'
|
44
49
|
end
|
data/ext/appmap/appmap.c
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ruby/intern.h>
|
3
|
+
|
4
|
+
// Seems like CLASS_OR_MODULE_P should really be in a header file in
|
5
|
+
// the ruby source -- it's in object.c and duplicated in eval.c. In
|
6
|
+
// the future, we'll fail if it does get moved to a header.
|
7
|
+
#define CLASS_OR_MODULE_P(obj) \
|
8
|
+
(!SPECIAL_CONST_P(obj) && \
|
9
|
+
(BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
|
10
|
+
|
11
|
+
static VALUE singleton_method_owner_name(VALUE klass, VALUE method)
|
12
|
+
{
|
13
|
+
VALUE owner = rb_funcall(method, rb_intern("owner"), 0);
|
14
|
+
VALUE attached = rb_ivar_get(owner, rb_intern("__attached__"));
|
15
|
+
if (!CLASS_OR_MODULE_P(attached)) {
|
16
|
+
attached = rb_funcall(attached, rb_intern("class"), 0);
|
17
|
+
}
|
18
|
+
return rb_mod_name(attached);
|
19
|
+
}
|
20
|
+
|
21
|
+
void Init_appmap() {
|
22
|
+
VALUE appmap = rb_define_module("AppMap");
|
23
|
+
VALUE hook = rb_define_class_under(appmap, "Hook", rb_cObject);
|
24
|
+
|
25
|
+
rb_define_singleton_method(hook, "singleton_method_owner_name", singleton_method_owner_name, 1);
|
26
|
+
}
|
data/lib/appmap.rb
CHANGED
@@ -13,19 +13,24 @@ require 'appmap/config'
|
|
13
13
|
require 'appmap/trace'
|
14
14
|
require 'appmap/class_map'
|
15
15
|
require 'appmap/metadata'
|
16
|
+
require 'appmap/util'
|
17
|
+
require 'appmap/open'
|
18
|
+
|
19
|
+
# load extension
|
20
|
+
require 'appmap/appmap'
|
16
21
|
|
17
22
|
module AppMap
|
18
23
|
class << self
|
19
24
|
@configuration = nil
|
20
25
|
@configuration_file_path = nil
|
21
26
|
|
22
|
-
#
|
27
|
+
# Gets the configuration. If there is no configuration, the default
|
23
28
|
# configuration is initialized.
|
24
29
|
def configuration
|
25
|
-
@configuration ||=
|
30
|
+
@configuration ||= initialize
|
26
31
|
end
|
27
32
|
|
28
|
-
#
|
33
|
+
# Sets the configuration. This is only expected to happen once per
|
29
34
|
# Ruby process.
|
30
35
|
def configuration=(config)
|
31
36
|
warn 'AppMap is already configured' if @configuration && config
|
@@ -33,22 +38,24 @@ module AppMap
|
|
33
38
|
@configuration = config
|
34
39
|
end
|
35
40
|
|
36
|
-
#
|
41
|
+
# Configures AppMap for recording. Default behavior is to configure from "appmap.yml".
|
37
42
|
# This method also activates the code hooks which record function calls as trace events.
|
38
43
|
# Call this function before the program code is loaded by the Ruby VM, otherwise
|
39
44
|
# the load events won't be seen and the hooks won't activate.
|
40
45
|
def initialize(config_file_path = 'appmap.yml')
|
41
46
|
warn "Configuring AppMap from path #{config_file_path}"
|
42
|
-
|
43
|
-
|
47
|
+
Config.load_from_file(config_file_path).tap do |configuration|
|
48
|
+
self.configuration = configuration
|
49
|
+
Hook.new(configuration).enable
|
50
|
+
end
|
44
51
|
end
|
45
52
|
|
46
|
-
#
|
53
|
+
# Used to start tracing, stop tracing, and record events.
|
47
54
|
def tracing
|
48
55
|
@tracing ||= Trace::Tracing.new
|
49
56
|
end
|
50
57
|
|
51
|
-
#
|
58
|
+
# Records the events which occur while processing a block,
|
52
59
|
# and returns an AppMap as a Hash.
|
53
60
|
def record
|
54
61
|
tracer = tracing.trace
|
@@ -69,12 +76,18 @@ module AppMap
|
|
69
76
|
}
|
70
77
|
end
|
71
78
|
|
72
|
-
#
|
79
|
+
# Uploads an AppMap to the AppLand website and displays it.
|
80
|
+
def open(appmap = nil, &block)
|
81
|
+
appmap ||= AppMap.record(&block)
|
82
|
+
AppMap::Open.new(appmap).perform
|
83
|
+
end
|
84
|
+
|
85
|
+
# Builds a class map from a config and a list of Ruby methods.
|
73
86
|
def class_map(methods)
|
74
87
|
ClassMap.build_from_methods(configuration, methods)
|
75
88
|
end
|
76
89
|
|
77
|
-
#
|
90
|
+
# Returns default metadata detected from the Ruby system and from the
|
78
91
|
# filesystem.
|
79
92
|
def detect_metadata
|
80
93
|
@metadata ||= Metadata.detect.freeze
|
data/lib/appmap/class_map.rb
CHANGED
@@ -61,7 +61,7 @@ module AppMap
|
|
61
61
|
location: location,
|
62
62
|
static: static,
|
63
63
|
labels: labels
|
64
|
-
}.delete_if {|k,v| v.nil?}
|
64
|
+
}.delete_if { |k,v| v.nil? || v == [] }
|
65
65
|
end
|
66
66
|
end
|
67
67
|
end
|
@@ -80,10 +80,6 @@ module AppMap
|
|
80
80
|
protected
|
81
81
|
|
82
82
|
def add_function(root, package, method)
|
83
|
-
location = method.source_location
|
84
|
-
location_file, lineno = location
|
85
|
-
location_file = location_file[Dir.pwd.length + 1..-1] if location_file.index(Dir.pwd) == 0
|
86
|
-
|
87
83
|
static = method.static
|
88
84
|
|
89
85
|
object_infos = [
|
@@ -101,12 +97,22 @@ module AppMap
|
|
101
97
|
function_info = {
|
102
98
|
name: method.name,
|
103
99
|
type: 'function',
|
104
|
-
location: [ location_file, lineno ].join(':'),
|
105
100
|
static: static
|
106
101
|
}
|
102
|
+
location = method.source_location
|
103
|
+
|
104
|
+
function_info[:location] = \
|
105
|
+
if location
|
106
|
+
location_file, lineno = location
|
107
|
+
location_file = location_file[Dir.pwd.length + 1..-1] if location_file.index(Dir.pwd) == 0
|
108
|
+
[ location_file, lineno ].join(':')
|
109
|
+
else
|
110
|
+
[ method.defined_class, static ? '.' : '#', method.name ].join
|
111
|
+
end
|
112
|
+
|
107
113
|
function_info[:labels] = package.labels if package.labels
|
108
114
|
object_infos << function_info
|
109
|
-
|
115
|
+
|
110
116
|
parent = root
|
111
117
|
object_infos.each do |info|
|
112
118
|
parent = find_or_create parent.children, info do
|
data/lib/appmap/config.rb
CHANGED
@@ -1,33 +1,54 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module AppMap
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
class Config
|
5
|
+
Package = Struct.new(:path, :package_name, :exclude, :labels) do
|
6
|
+
def initialize(path, package_name: nil, exclude: [], labels: [])
|
7
|
+
super path, package_name, exclude, labels
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_h
|
11
|
+
{
|
12
|
+
path: path,
|
13
|
+
package_name: package_name,
|
14
|
+
exclude: exclude.blank? ? nil : exclude,
|
15
|
+
labels: labels.blank? ? nil : labels
|
16
|
+
}.compact
|
17
|
+
end
|
7
18
|
end
|
8
|
-
|
9
|
-
|
10
|
-
{
|
11
|
-
path: path,
|
12
|
-
exclude: exclude.blank? ? nil : exclude,
|
13
|
-
labels: labels.blank? ? nil : labels
|
14
|
-
}.compact
|
19
|
+
|
20
|
+
Hook = Struct.new(:method_names, :package) do
|
15
21
|
end
|
16
|
-
end
|
17
22
|
|
18
|
-
|
23
|
+
OPENSSL_PACKAGE = Package.new('openssl', package_name: 'openssl', labels: %w[security crypto])
|
24
|
+
|
19
25
|
# Methods that should always be hooked, with their containing
|
20
26
|
# package and labels that should be applied to them.
|
21
27
|
HOOKED_METHODS = {
|
22
|
-
'ActiveSupport::SecurityUtils' =>
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
'ActiveSupport::SecurityUtils' => Hook.new(:secure_compare, Package.new('active_support', package_name: 'active_support', labels: %w[security crypto]))
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
BUILTIN_METHODS = {
|
32
|
+
'OpenSSL::PKey::PKey' => Hook.new(:sign, OPENSSL_PACKAGE),
|
33
|
+
'Digest::Instance' => Hook.new(:digest, OPENSSL_PACKAGE),
|
34
|
+
'OpenSSL::X509::Request' => Hook.new(%i[sign verify], OPENSSL_PACKAGE),
|
35
|
+
'OpenSSL::PKCS5' => Hook.new(%i[pbkdf2_hmac_sha1 pbkdf2_hmac], OPENSSL_PACKAGE),
|
36
|
+
'OpenSSL::Cipher' => Hook.new(%i[encrypt decrypt final], OPENSSL_PACKAGE),
|
37
|
+
'OpenSSL::X509::Certificate' => Hook.new(:sign, OPENSSL_PACKAGE),
|
38
|
+
'Logger' => Hook.new(:add, Package.new('logger', labels: %w[log io])),
|
39
|
+
'Net::HTTP' => Hook.new(:request, Package.new('net/http', package_name: 'net/http', labels: %w[http io])),
|
40
|
+
'Net::SMTP' => Hook.new(:send, Package.new('net/smtp', package_name: 'net/smtp', labels: %w[smtp email io])),
|
41
|
+
'Net::POP3' => Hook.new(:mails, Package.new('net/pop3', package_name: 'net/pop', labels: %w[pop pop3 email io])),
|
42
|
+
'Net::IMAP' => Hook.new(:send_command, Package.new('net/imap', package_name: 'net/imap', labels: %w[imap email io])),
|
43
|
+
'IO' => Hook.new(%i[read write open close], Package.new('io', labels: %w[io])),
|
44
|
+
'Marshal' => Hook.new(%i[dump load], Package.new('marshal', labels: %w[serialization marshal])),
|
45
|
+
'Psych' => Hook.new(%i[dump dump_stream load load_stream parse parse_stream], Package.new('yaml', package_name: 'psych', labels: %w[serialization yaml])),
|
46
|
+
'JSON::Ext::Parser' => Hook.new(:parse, Package.new('json', package_name: 'json', labels: %w[serialization json])),
|
47
|
+
'JSON::Ext::Generator::State' => Hook.new(:generate, Package.new('json', package_name: 'json', labels: %w[serialization json]))
|
48
|
+
}.freeze
|
29
49
|
|
30
50
|
attr_reader :name, :packages
|
51
|
+
|
31
52
|
def initialize(name, packages = [])
|
32
53
|
@name = name
|
33
54
|
@packages = packages
|
@@ -43,7 +64,7 @@ module AppMap
|
|
43
64
|
# Loads configuration from a Hash.
|
44
65
|
def load(config_data)
|
45
66
|
packages = (config_data['packages'] || []).map do |package|
|
46
|
-
Package.new(package['path'], package['exclude'] || [])
|
67
|
+
Package.new(package['path'], exclude: package['exclude'] || [])
|
47
68
|
end
|
48
69
|
Config.new config_data['name'], packages
|
49
70
|
end
|
@@ -57,14 +78,14 @@ module AppMap
|
|
57
78
|
end
|
58
79
|
|
59
80
|
def package_for_method(method)
|
81
|
+
defined_class, _, method_name = ::AppMap::Hook.qualify_method_name(method)
|
82
|
+
package = find_package(defined_class, method_name)
|
83
|
+
return package if package
|
84
|
+
|
60
85
|
location = method.source_location
|
61
86
|
location_file, = location
|
62
87
|
return unless location_file
|
63
88
|
|
64
|
-
defined_class,_,method_name = Hook.qualify_method_name(method)
|
65
|
-
hooked_method = find_hooked_method(defined_class, method_name)
|
66
|
-
return hooked_method if hooked_method
|
67
|
-
|
68
89
|
location_file = location_file[Dir.pwd.length + 1..-1] if location_file.index(Dir.pwd) == 0
|
69
90
|
packages.find do |pkg|
|
70
91
|
(location_file.index(pkg.path) == 0) &&
|
@@ -77,15 +98,18 @@ module AppMap
|
|
77
98
|
end
|
78
99
|
|
79
100
|
def always_hook?(defined_class, method_name)
|
80
|
-
!!
|
101
|
+
!!find_package(defined_class, method_name)
|
81
102
|
end
|
82
103
|
|
83
|
-
def
|
84
|
-
|
104
|
+
def find_package(defined_class, method_name)
|
105
|
+
hook = find_hook(defined_class)
|
106
|
+
return nil unless hook
|
107
|
+
|
108
|
+
Array(hook.method_names).include?(method_name) ? hook.package : nil
|
85
109
|
end
|
86
|
-
|
87
|
-
def
|
88
|
-
HOOKED_METHODS[defined_class] ||
|
110
|
+
|
111
|
+
def find_hook(defined_class)
|
112
|
+
HOOKED_METHODS[defined_class] || BUILTIN_METHODS[defined_class]
|
89
113
|
end
|
90
114
|
end
|
91
115
|
end
|