dependencytree 0.1.7 → 0.1.8
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/Rakefile +9 -1
- data/dependencytree.gemspec +2 -1
- data/lib/dependencytree.rb +2 -75
- data/lib/dependencytree/classmodel.rb +10 -1
- data/lib/dependencytree/dependencyresolver.rb +13 -11
- data/lib/dependencytree/treeinterpreter.rb +14 -11
- data/lib/dependencytree/treemain.rb +87 -0
- data/lib/dependencytree/version.rb +1 -1
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0eaccd9262969019a4816794b1523655b1e640d5
|
4
|
+
data.tar.gz: a8815740f3dee55ec51cf34e6155c16f340240f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 544cd47f79beda8c029892f0c6ff991baa90c1b7e3aa34a5f1643384977aee3c3824024be83438efc8ad7753ba47069e7e7587ee8b9b862451a62b0fde97a0f7
|
7
|
+
data.tar.gz: 0fef2ba73b64d6724cf947cf04ea8d75e491a2ce8a4bee079854ec621df1323e6a50e143289ea867e1264ea7c53e49edb9d6a66fe153581d2b7e62bfe132b0cd
|
data/Rakefile
CHANGED
data/dependencytree.gemspec
CHANGED
@@ -23,7 +23,8 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
25
|
spec.add_development_dependency "bundler", "~> 1.15"
|
26
|
-
spec.add_development_dependency "rake", "~>
|
26
|
+
spec.add_development_dependency "rake", "~> 12.3"
|
27
|
+
spec.add_development_dependency "minitest", "~> 5.11"
|
27
28
|
spec.add_dependency "parser", "~> 2.5.0.5"
|
28
29
|
spec.add_dependency "ast", "~> 2.4.0"
|
29
30
|
end
|
data/lib/dependencytree.rb
CHANGED
@@ -1,82 +1,9 @@
|
|
1
|
-
require "dependencytree/treeinterpreter"
|
2
|
-
require "dependencytree/dependencyresolver"
|
3
|
-
|
4
1
|
require "dependencytree/version"
|
5
|
-
require
|
6
|
-
require 'optparse'
|
7
|
-
require 'pp'
|
8
|
-
require 'json'
|
2
|
+
require "dependencytree/treemain"
|
9
3
|
require 'logger'
|
10
4
|
|
11
5
|
module Dependencytree
|
12
6
|
|
13
|
-
|
14
|
-
if options[:ignore].match(path)
|
15
|
-
return
|
16
|
-
end
|
17
|
-
if File.directory?(path)
|
18
|
-
STDERR.puts path if options[:verbose]
|
19
|
-
Dir.entries(path).each { |x|
|
20
|
-
resolved = File.join(path, x)
|
21
|
-
handle_path(options, consumer, resolved) if File.directory?(resolved) && x != "." && x != ".."
|
22
|
-
handle_path(options, consumer, resolved) if File.file?(resolved) && options[:pattern].match(resolved)
|
23
|
-
}
|
24
|
-
elsif File.file?(path)
|
25
|
-
STDERR.puts path if options[:verbose]
|
26
|
-
LOG.debug("Handling path #{path}")
|
27
|
-
tree = Parser::CurrentRuby.parse_file(path)
|
28
|
-
LOG.debug("Parsed tree: #{tree}") if LOG.debug?
|
29
|
-
consumer.visit(path, tree)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
options = {}
|
34
|
-
options[:ignore] = /^$/
|
35
|
-
options[:pattern] = /.*\.rb/
|
36
|
-
OptionParser.new do |opt|
|
37
|
-
opt.on("-v", "--verbose", "Verbose output") do |o|
|
38
|
-
options[:verbose] = true
|
39
|
-
end
|
40
|
-
opt.on("-d", "--debug", "Log debugging output to file 'dependencytree.log'") do |o|
|
41
|
-
options[:debug] = true
|
42
|
-
end
|
43
|
-
opt.on("-p", "--pattern[=OPTIONAL]", "Pattern to accept source codes with (default: #{options[:pattern].to_s})") do |o|
|
44
|
-
options[:pattern] = /#{o}/
|
45
|
-
end
|
46
|
-
opt.on("-i", "--ignore[=OPTIONAL]", "Paths to not load (default: #{options[:ignore].to_s})") do |o|
|
47
|
-
options[:ignore] = /#{o}/
|
48
|
-
end
|
49
|
-
opt.on("-o", "--output[=OPTIONAL]", "Output path for the JSON file") do |o|
|
50
|
-
options[:output] = o
|
51
|
-
end
|
52
|
-
opt.on_tail("-h", "--help", "Show this message") do
|
53
|
-
puts opt
|
54
|
-
exit
|
55
|
-
end
|
56
|
-
end.parse!
|
57
|
-
|
58
|
-
if options[:debug]
|
59
|
-
log = Logger.new('dependencytree.log')
|
60
|
-
log.level = Logger::WARN
|
61
|
-
else
|
62
|
-
log = Logger.new(STDOUT)
|
63
|
-
log.level = Logger::WARN
|
64
|
-
end
|
65
|
-
LOG = log
|
66
|
-
|
67
|
-
treeinterpreter = TreeInterpreter.new
|
68
|
-
ARGV.each do |path|
|
69
|
-
handle_path(options, treeinterpreter, File.absolute_path(path))
|
70
|
-
end
|
71
|
-
|
72
|
-
dependencyresolver = DependencyResolver.new(treeinterpreter.classes_and_modules)
|
73
|
-
dependencyresolver.resolve_references
|
74
|
-
|
75
|
-
json = dependencyresolver.classes_and_modules.to_json
|
76
|
-
if options[:output]
|
77
|
-
File.write(options[:output], json)
|
78
|
-
else
|
79
|
-
puts json
|
80
|
-
end
|
7
|
+
TreeMain.main
|
81
8
|
end
|
82
9
|
|
@@ -16,13 +16,15 @@ module Dependencytree
|
|
16
16
|
attr_reader :resolved_references
|
17
17
|
attr_reader :unresolved_references
|
18
18
|
|
19
|
+
@@generator = SecureRandom
|
20
|
+
|
19
21
|
# type: :class or :module
|
20
22
|
# path: the filesystem path the parsed class was found in
|
21
23
|
# module_name: eventual module name or :anonymous
|
22
24
|
# class_name: the class name
|
23
25
|
def initialize(type, path, name)
|
24
26
|
# unique uuid for reference
|
25
|
-
@uuid =
|
27
|
+
@uuid = @@generator.uuid
|
26
28
|
# :module or :class
|
27
29
|
@type = type
|
28
30
|
# filesystem path of (first) definition
|
@@ -36,10 +38,17 @@ module Dependencytree
|
|
36
38
|
# list of (unresolved) references as arrays
|
37
39
|
@references = []
|
38
40
|
|
41
|
+
# no parent by default (will be set later)
|
42
|
+
@parent = nil
|
43
|
+
|
39
44
|
@resolved_references = []
|
40
45
|
@unresolved_references = []
|
41
46
|
end
|
42
47
|
|
48
|
+
def self.generator=(generator)
|
49
|
+
@@generator = generator
|
50
|
+
end
|
51
|
+
|
43
52
|
# Gets the full name of the class/module as an array.
|
44
53
|
# @return the full name, for example ["ModuleA","ModuleB","ClassA"]
|
45
54
|
def full_name_array
|
@@ -12,7 +12,9 @@ module Dependencytree
|
|
12
12
|
# path: the filesystem path the parsed class was found in
|
13
13
|
# module_name: eventual module name or :anonymous
|
14
14
|
# class_name: the class name
|
15
|
-
def initialize(classes_and_modules)
|
15
|
+
def initialize(log, classes_and_modules)
|
16
|
+
# store logger
|
17
|
+
@@log = log
|
16
18
|
@classes_and_modules = classes_and_modules
|
17
19
|
@by_full_name = @classes_and_modules.each_with_object({}) { |clazz, hash| hash[clazz.full_name()] = clazz }
|
18
20
|
end
|
@@ -20,7 +22,7 @@ module Dependencytree
|
|
20
22
|
# Goes thru all classes and tries to resolve the references.
|
21
23
|
def resolve_references
|
22
24
|
@classes_and_modules.each do |clazz|
|
23
|
-
|
25
|
+
@@log.debug("Processing class #{clazz.full_name} located in #{clazz.path}")
|
24
26
|
clazz.references.each do |reference_array|
|
25
27
|
refered_class = resolve_reference(clazz, reference_array)
|
26
28
|
if refered_class
|
@@ -43,9 +45,9 @@ module Dependencytree
|
|
43
45
|
end
|
44
46
|
|
45
47
|
if refered_class_model
|
46
|
-
|
48
|
+
@@log.debug("Resolved #{reference_array.join('::')} to uuid #{refered_class_model.uuid}")
|
47
49
|
else
|
48
|
-
|
50
|
+
@@log.debug("Could not resolve #{reference_array.join('::')}")
|
49
51
|
end
|
50
52
|
refered_class_model
|
51
53
|
end
|
@@ -59,16 +61,16 @@ module Dependencytree
|
|
59
61
|
reference_part = reference_array[0..-2]
|
60
62
|
constant_name = reference_array[-1]
|
61
63
|
|
62
|
-
|
64
|
+
@@log.debug("Resolving reference array #{reference_array.to_s} as reference #{reference_part.to_s} and constant #{constant_name}")
|
63
65
|
|
64
66
|
refered_class_model = resolve_reference_direct(referer_class_model, reference_part)
|
65
67
|
if refered_class_model
|
66
|
-
|
68
|
+
@@log.debug("Found reference to possible parent #{reference_part.to_s}")
|
67
69
|
if refered_class_model.constant_names.include? constant_name.to_sym
|
68
|
-
|
70
|
+
@@log.debug("Found class #{refered_class_model.full_name} constant #{constant_name}")
|
69
71
|
refered_class_model
|
70
72
|
else
|
71
|
-
|
73
|
+
@@log.debug("Found class #{refered_class_model.full_name}, but not constant #{constant_name}. Known constants: #{refered_class_model.constant_names}")
|
72
74
|
nil
|
73
75
|
end
|
74
76
|
else
|
@@ -81,15 +83,15 @@ module Dependencytree
|
|
81
83
|
# @param reference_array the reference as in the source, can be absolute or relative to the referer class.
|
82
84
|
# @return the refered class model or nil
|
83
85
|
def resolve_reference_direct(referer_class_model, reference_array)
|
84
|
-
|
86
|
+
@@log.debug("Resolving reference array #{reference_array.to_s}")
|
85
87
|
|
86
88
|
referer_array = referer_class_model.full_name_array
|
87
89
|
i = 0
|
88
90
|
refered_class_model = nil
|
89
91
|
while !refered_class_model do
|
90
|
-
|
92
|
+
@@log.debug("Referer array #{i} is #{referer_array.to_s}")
|
91
93
|
full_name = (referer_array+reference_array).join("::")
|
92
|
-
|
94
|
+
@@log.debug("Full name #{i} is #{full_name} #{full_name.class.name}")
|
93
95
|
refered_class_model = resolve_by_full_name(full_name)
|
94
96
|
|
95
97
|
break if referer_array.empty?
|
@@ -8,7 +8,10 @@ module Dependencytree
|
|
8
8
|
class TreeInterpreter
|
9
9
|
attr_reader :classes_and_modules
|
10
10
|
|
11
|
-
def initialize
|
11
|
+
def initialize(log)
|
12
|
+
# the logging instance
|
13
|
+
@@log = log
|
14
|
+
|
12
15
|
# path will be the file system path of the source file
|
13
16
|
@path = nil
|
14
17
|
# context_stack is the stack of modules/classes loaded (namespacing)
|
@@ -52,14 +55,14 @@ module Dependencytree
|
|
52
55
|
# Handle a const expression.
|
53
56
|
# @param node the const node itself to handle.
|
54
57
|
def _const(node)
|
55
|
-
|
58
|
+
@@log.debug("const")
|
56
59
|
|
57
60
|
raise ArgumentError, "type needs to be const (#{node.type})" if node.type != :const
|
58
61
|
raise ArgumentError, "Children count needs to be 2 (#{node.children.length})" if node.children.length != 2
|
59
62
|
|
60
63
|
reference = flatten_const_tree(node)
|
61
64
|
|
62
|
-
|
65
|
+
@@log.debug("Reference to #{reference.to_s}")
|
63
66
|
top_of_stack.add_reference(reference)
|
64
67
|
end
|
65
68
|
|
@@ -69,7 +72,7 @@ module Dependencytree
|
|
69
72
|
raise ArgumentError, "Children count for module is != 2 (#{node.children.length})" if node.children.length != 2
|
70
73
|
raise ArgumentError, "First module child needs to be a const (#{node.children[0].type} #{node.children[0].type})" if node.children[0].type != :const
|
71
74
|
|
72
|
-
|
75
|
+
@@log.debug("module #{node.children[0].children[1]}")
|
73
76
|
|
74
77
|
current_module_name = node.children[0].children[1]
|
75
78
|
_handle_class_module_common(:module, current_module_name, node)
|
@@ -80,7 +83,7 @@ module Dependencytree
|
|
80
83
|
def _class(node)
|
81
84
|
raise ArgumentError, "Children count for class is != 3 (#{node.children.length})" if node.children.length != 3
|
82
85
|
raise ArgumentError, "First class child needs to be a const (#{node.children[0].type} #{node.children[0].type})" if node.children[0].type != :const
|
83
|
-
|
86
|
+
@@log.debug("class #{node.children[0].children[1]}")
|
84
87
|
|
85
88
|
current_class_name = node.children[0].children[1]
|
86
89
|
_handle_class_module_common(:class, current_class_name, node)
|
@@ -97,7 +100,7 @@ module Dependencytree
|
|
97
100
|
parent = @context_stack[-1]
|
98
101
|
full_name = parent.full_name.to_s + "::" + name.to_s
|
99
102
|
end
|
100
|
-
|
103
|
+
@@log.debug("Full name is #{full_name}")
|
101
104
|
resolved = _resolve(full_name)
|
102
105
|
|
103
106
|
if ! resolved.nil?
|
@@ -113,7 +116,7 @@ module Dependencytree
|
|
113
116
|
end
|
114
117
|
|
115
118
|
if resolved.nil?
|
116
|
-
|
119
|
+
@@log.debug("Created new ClassModel for #{model.full_name}")
|
117
120
|
end
|
118
121
|
|
119
122
|
@context_stack << model
|
@@ -127,7 +130,7 @@ module Dependencytree
|
|
127
130
|
def _def(node)
|
128
131
|
raise ArgumentError, "Children count for def is != 3 (#{node.children.length})" if node.children.length != 3
|
129
132
|
|
130
|
-
|
133
|
+
@@log.debug("def #{node.children[0]}")
|
131
134
|
|
132
135
|
top_of_stack.add_method(node.children[0])
|
133
136
|
|
@@ -139,7 +142,7 @@ module Dependencytree
|
|
139
142
|
def _casgn(node)
|
140
143
|
raise ArgumentError, "Children count for casgn is != 3 (#{node.children.length})" if node.children.length != 3
|
141
144
|
|
142
|
-
|
145
|
+
@@log.debug("casgn #{node.children[1]}")
|
143
146
|
|
144
147
|
top_of_stack.add_constant(node.children[1])
|
145
148
|
|
@@ -179,12 +182,12 @@ module Dependencytree
|
|
179
182
|
# @param tree the AST tree node.
|
180
183
|
def visit(path, tree)
|
181
184
|
begin
|
182
|
-
|
185
|
+
@@log.debug("Visiting path #{path}")
|
183
186
|
@path = path
|
184
187
|
visit_node(tree)
|
185
188
|
@path = nil
|
186
189
|
rescue Exception => e
|
187
|
-
|
190
|
+
@@log.error("Error in path #{path}")
|
188
191
|
puts "Error in path #{path}"
|
189
192
|
raise e
|
190
193
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "dependencytree/treeinterpreter"
|
2
|
+
require "dependencytree/dependencyresolver"
|
3
|
+
|
4
|
+
require "dependencytree/version"
|
5
|
+
require 'parser/current'
|
6
|
+
require 'optparse'
|
7
|
+
require 'pp'
|
8
|
+
require 'json'
|
9
|
+
require 'logger'
|
10
|
+
|
11
|
+
module Dependencytree
|
12
|
+
|
13
|
+
# Contains the main method for handling the program flow.
|
14
|
+
class TreeMain
|
15
|
+
def self.handle_path(options, consumer, path)
|
16
|
+
if options[:ignore].match(path)
|
17
|
+
return
|
18
|
+
end
|
19
|
+
if File.directory?(path)
|
20
|
+
STDERR.puts path if options[:verbose]
|
21
|
+
Dir.entries(path).each { |x|
|
22
|
+
resolved = File.join(path, x)
|
23
|
+
handle_path(options, consumer, resolved) if File.directory?(resolved) && x != "." && x != ".."
|
24
|
+
handle_path(options, consumer, resolved) if File.file?(resolved) && options[:pattern].match(resolved)
|
25
|
+
}
|
26
|
+
elsif File.file?(path)
|
27
|
+
STDERR.puts path if options[:verbose]
|
28
|
+
@@log.debug("Handling path #{path}")
|
29
|
+
tree = Parser::CurrentRuby.parse_file(path)
|
30
|
+
@@log.debug("Parsed tree: #{tree}") if @@log.debug?
|
31
|
+
consumer.visit(path, tree)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.main
|
36
|
+
options = {}
|
37
|
+
options[:ignore] = /^$/
|
38
|
+
options[:pattern] = /.*\.rb/
|
39
|
+
OptionParser.new do |opt|
|
40
|
+
opt.on("-v", "--verbose", "Verbose output") do |o|
|
41
|
+
options[:verbose] = true
|
42
|
+
end
|
43
|
+
opt.on("-d", "--debug", "Log debugging output to file 'dependencytree.log'") do |o|
|
44
|
+
options[:debug] = true
|
45
|
+
end
|
46
|
+
opt.on("-p", "--pattern[=OPTIONAL]", "Pattern to accept source codes with (default: #{options[:pattern].to_s})") do |o|
|
47
|
+
options[:pattern] = /#{o}/
|
48
|
+
end
|
49
|
+
opt.on("-i", "--ignore[=OPTIONAL]", "Paths to not load (default: #{options[:ignore].to_s})") do |o|
|
50
|
+
options[:ignore] = /#{o}/
|
51
|
+
end
|
52
|
+
opt.on("-o", "--output[=OPTIONAL]", "Output path for the JSON file") do |o|
|
53
|
+
options[:output] = o
|
54
|
+
end
|
55
|
+
opt.on_tail("-h", "--help", "Show this message") do
|
56
|
+
puts opt
|
57
|
+
return
|
58
|
+
end
|
59
|
+
end.parse!
|
60
|
+
|
61
|
+
if options[:debug]
|
62
|
+
log = Logger.new('dependencytree.log')
|
63
|
+
log.level = Logger::WARN
|
64
|
+
else
|
65
|
+
log = Logger.new(STDOUT)
|
66
|
+
log.level = Logger::WARN
|
67
|
+
end
|
68
|
+
@@log = log
|
69
|
+
|
70
|
+
treeinterpreter = TreeInterpreter.new(log)
|
71
|
+
ARGV.each do |path|
|
72
|
+
handle_path(options, treeinterpreter, File.absolute_path(path))
|
73
|
+
end
|
74
|
+
|
75
|
+
dependencyresolver = DependencyResolver.new(log, treeinterpreter.classes_and_modules)
|
76
|
+
dependencyresolver.resolve_references
|
77
|
+
|
78
|
+
json = dependencyresolver.classes_and_modules.to_json
|
79
|
+
if options[:output]
|
80
|
+
File.write(options[:output], json)
|
81
|
+
else
|
82
|
+
puts json
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dependencytree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephan Fuhrmann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -30,14 +30,28 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '12.3'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '12.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.11'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.11'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: parser
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,6 +102,7 @@ files:
|
|
88
102
|
- lib/dependencytree/classmodel.rb
|
89
103
|
- lib/dependencytree/dependencyresolver.rb
|
90
104
|
- lib/dependencytree/treeinterpreter.rb
|
105
|
+
- lib/dependencytree/treemain.rb
|
91
106
|
- lib/dependencytree/version.rb
|
92
107
|
homepage: http://www.1und1.de
|
93
108
|
licenses:
|