delfos 0.0.1.pre.rc1 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|