delfos 0.0.1.pre.rc1 → 0.0.1
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/lib/delfos.rb +22 -78
- data/lib/delfos/call_stack.rb +39 -0
- data/lib/delfos/call_stack/stack.rb +59 -0
- data/lib/delfos/file_system/common_path.rb +62 -0
- data/lib/delfos/{distance/calculation.rb → file_system/distance_calculation.rb} +4 -15
- data/lib/delfos/file_system/path_determination.rb +37 -0
- data/lib/delfos/{distance → file_system}/relation.rb +1 -1
- data/lib/delfos/method_logging.rb +32 -49
- data/lib/delfos/method_logging/call_site_parsing.rb +74 -0
- data/lib/delfos/method_logging/code_location.rb +34 -98
- data/lib/delfos/method_logging/{args.rb → method_parameters.rb} +17 -18
- data/lib/delfos/neo4j.rb +58 -0
- data/lib/delfos/neo4j/batch/execution.rb +149 -0
- data/lib/delfos/neo4j/{execution_persistence.rb → call_stack_query.rb} +12 -22
- data/lib/delfos/neo4j/distance/call_site_fetcher.rb +19 -0
- data/lib/delfos/neo4j/distance/update.rb +50 -0
- data/lib/delfos/neo4j/informer.rb +62 -34
- data/lib/delfos/neo4j/query_execution/errors.rb +30 -0
- data/lib/delfos/neo4j/query_execution/http.rb +61 -0
- data/lib/delfos/neo4j/query_execution/http_query.rb +67 -0
- data/lib/delfos/neo4j/query_execution/sync.rb +35 -0
- data/lib/delfos/neo4j/query_execution/transactional.rb +68 -0
- data/lib/delfos/neo4j/schema.rb +73 -0
- data/lib/delfos/patching/basic_object.rb +1 -5
- data/lib/delfos/patching/method_cache.rb +83 -0
- data/lib/delfos/patching/method_override.rb +76 -66
- data/lib/delfos/patching/module_defining_methods.rb +105 -0
- data/lib/delfos/patching/unstubber.rb +34 -0
- data/lib/delfos/setup.rb +88 -0
- metadata +42 -15
- data/lib/delfos/common_path.rb +0 -58
- data/lib/delfos/execution_chain.rb +0 -75
- data/lib/delfos/method_logging/added_methods.rb +0 -67
- data/lib/delfos/neo4j/distance_update.rb +0 -73
- data/lib/delfos/neo4j/query_execution.rb +0 -79
- data/lib/delfos/patching/unstubbing_spec_helper.rb +0 -58
@@ -1,67 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "Forwardable" unless defined? Forwardable
|
3
|
-
|
4
|
-
module Delfos
|
5
|
-
module MethodLogging
|
6
|
-
class AddedMethods
|
7
|
-
class << self
|
8
|
-
extend Forwardable
|
9
|
-
|
10
|
-
def_delegators :instance,
|
11
|
-
:all_method_sources_for,
|
12
|
-
:method_source_for,
|
13
|
-
:append,
|
14
|
-
:find
|
15
|
-
|
16
|
-
def instance
|
17
|
-
@instance ||= new
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize
|
22
|
-
@added_methods = {}
|
23
|
-
end
|
24
|
-
|
25
|
-
attr_reader :added_methods
|
26
|
-
|
27
|
-
def all_method_sources_for(klass)
|
28
|
-
fetch(klass).values.map(&:source_location)
|
29
|
-
end
|
30
|
-
|
31
|
-
def method_source_for(klass, key)
|
32
|
-
meth = find(klass, key)
|
33
|
-
|
34
|
-
if meth
|
35
|
-
meth.source_location
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def append(klass, key, original_method)
|
40
|
-
m = fetch(klass)[key]
|
41
|
-
|
42
|
-
if m.nil?
|
43
|
-
fetch(klass)[key] = original_method
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def find(klass, key)
|
48
|
-
fetch(klass)[key]
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def fetch(klass)
|
54
|
-
# Find method definitions defined in klass or its ancestors
|
55
|
-
super_klass = klass.ancestors.detect do |k|
|
56
|
-
(fetch_without_default(k) || {}).values.length.positive?
|
57
|
-
end
|
58
|
-
|
59
|
-
added_methods[(super_klass || klass).to_s] ||= {}
|
60
|
-
end
|
61
|
-
|
62
|
-
def fetch_without_default(klass)
|
63
|
-
added_methods[klass.to_s]
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require_relative "../distance/calculation"
|
3
|
-
require_relative "query_execution"
|
4
|
-
require "json"
|
5
|
-
|
6
|
-
module Delfos
|
7
|
-
module Neo4j
|
8
|
-
class DistanceUpdate
|
9
|
-
def perform
|
10
|
-
update Delfos::Neo4j::QueryExecution.execute(query)
|
11
|
-
end
|
12
|
-
|
13
|
-
def determine_full_path(f)
|
14
|
-
f = Pathname.new f
|
15
|
-
return f.realpath if File.exist?(f)
|
16
|
-
|
17
|
-
Delfos.application_directories.map do |d|
|
18
|
-
path = Pathname.new(d + f.to_s.gsub(%r{[^/]*/}, ""))
|
19
|
-
path if path.exist?
|
20
|
-
end.compact.first
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def query
|
26
|
-
<<-QUERY
|
27
|
-
MATCH
|
28
|
-
(klass:Class) - [:OWNS] -> (method:Method),
|
29
|
-
(method) - [:CONTAINS] -> (call_site:CallSite),
|
30
|
-
(call_site) - [:CALLS] -> (called:Method),
|
31
|
-
(called_klass:Class) - [:OWNS] -> (called:Method)
|
32
|
-
|
33
|
-
RETURN
|
34
|
-
head(labels(klass)),
|
35
|
-
call_site, id(call_site),
|
36
|
-
method,
|
37
|
-
called, id(called),
|
38
|
-
head(labels(called_klass))
|
39
|
-
QUERY
|
40
|
-
end
|
41
|
-
|
42
|
-
def update(results)
|
43
|
-
Array(results).compact.map do |_klass, call_site, call_site_id, _meth, called, called_id, _called_klass|
|
44
|
-
start = determine_full_path call_site["file"]
|
45
|
-
finish = determine_full_path called["file"]
|
46
|
-
|
47
|
-
calc = Delfos::Distance::Calculation.new(start, finish)
|
48
|
-
|
49
|
-
perform_query(calc, call_site_id, called_id)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def perform_query(calc, call_site_id, called_id)
|
54
|
-
Delfos::Neo4j::QueryExecution.execute <<-QUERY, {call_site_id: call_site_id, called_id: called_id, sum_traversals: calc.sum_traversals, sum_possible_traversals: calc.sum_possible_traversals}
|
55
|
-
START call_site = node({call_site_id}),
|
56
|
-
called = node({called_id})
|
57
|
-
|
58
|
-
MERGE (call_site) - #{rel} -> (called)
|
59
|
-
QUERY
|
60
|
-
end
|
61
|
-
|
62
|
-
def rel
|
63
|
-
<<-REL
|
64
|
-
[:EFFERENT_COUPLING{
|
65
|
-
distance: {sum_traversals},
|
66
|
-
possible_distance: {sum_possible_traversals}
|
67
|
-
}
|
68
|
-
]
|
69
|
-
REL
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,79 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "delfos"
|
3
|
-
require "json"
|
4
|
-
require "net/http"
|
5
|
-
require "uri"
|
6
|
-
|
7
|
-
module Delfos
|
8
|
-
module Neo4j
|
9
|
-
module QueryExecution
|
10
|
-
class ExecutionError < IOError
|
11
|
-
def initialize(response, query, params)
|
12
|
-
message = response.inspect
|
13
|
-
|
14
|
-
super [message, query, params.to_json].join("\n\n ")
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class << self
|
19
|
-
def execute(query, params={})
|
20
|
-
return unless query.length.positive?
|
21
|
-
|
22
|
-
parse_response(*response_for(query, params))
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
|
28
|
-
def parse_response(result, query, params)
|
29
|
-
result = JSON.parse result.body
|
30
|
-
|
31
|
-
if result["errors"].length.positive?
|
32
|
-
raise ExecutionError.new(result["errors"], query, params)
|
33
|
-
end
|
34
|
-
|
35
|
-
strip_out_meta_data(result)
|
36
|
-
end
|
37
|
-
|
38
|
-
def strip_out_meta_data(result)
|
39
|
-
results = result["results"]
|
40
|
-
|
41
|
-
if results
|
42
|
-
result = results.first
|
43
|
-
if result
|
44
|
-
data = result["data"]
|
45
|
-
data &.map { |r| r["row"] }
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def response_for(query, params)
|
51
|
-
request = request_for(query, params)
|
52
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
53
|
-
|
54
|
-
response = http.request(request)
|
55
|
-
[response, query, params]
|
56
|
-
end
|
57
|
-
|
58
|
-
def request_for(query, params)
|
59
|
-
build_request do
|
60
|
-
"{\"statements\": [{\"statement\": #{query.inspect} , \"parameters\": #{params.to_json}}]}"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def build_request
|
65
|
-
Net::HTTP::Post.new(uri.request_uri).tap do |request|
|
66
|
-
request.basic_auth(Delfos.neo4j.username, Delfos.neo4j.password)
|
67
|
-
request.content_type = "application/json"
|
68
|
-
|
69
|
-
request.body = yield
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def uri
|
74
|
-
@uri ||= URI.parse "#{Delfos.neo4j.url}/db/data/transaction/commit"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
|
4
|
-
# These `Unstubbing` modules because we are testing something that redefines
|
5
|
-
# methods.
|
6
|
-
|
7
|
-
# We don't want to call the logging defined in
|
8
|
-
# `Delfos::Patching::MethodOverride#setup` multiple times. So we replace with
|
9
|
-
# the original definition, or to as close as possible.
|
10
|
-
|
11
|
-
# If there is a better way to do this please suggest
|
12
|
-
|
13
|
-
module Delfos
|
14
|
-
module Patching
|
15
|
-
module Unstubbing
|
16
|
-
module ClassMethods
|
17
|
-
def add_instance_to_unstub!(object)
|
18
|
-
instances_to_unstub.push(object)
|
19
|
-
end
|
20
|
-
|
21
|
-
def unstub_all!
|
22
|
-
instances_to_unstub.each(&:unstub!)
|
23
|
-
@instances_to_unstub = []
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def instances_to_unstub
|
29
|
-
@instances_to_unstub ||= []
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
module InstanceMethods
|
34
|
-
def initialize(*args)
|
35
|
-
super(*args)
|
36
|
-
self.class.add_instance_to_unstub!(self) unless bail?
|
37
|
-
end
|
38
|
-
|
39
|
-
# This method is the inverse of `Delfos::Patching::MethodOverride#setup`
|
40
|
-
def unstub!
|
41
|
-
method = Delfos::MethodLogging::AddedMethods.find(klass, key)
|
42
|
-
return unless method
|
43
|
-
file = File.expand_path(__FILE__)
|
44
|
-
|
45
|
-
cm = class_method
|
46
|
-
if cm
|
47
|
-
method.unbind.bind(klass)
|
48
|
-
else
|
49
|
-
klass.send(:define_method, name) do |*args, **kw_args, &block|
|
50
|
-
arguments = Delfos::Patching::MethodOverride::MethodArguments.new(args, kw_args, block, cm)
|
51
|
-
arguments.apply_to(method.bind(self))
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|