cpp_dependency_graph 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/console +0 -0
- data/cpp_dependency_graph.gemspec +1 -1
- data/exe/cpp_dependency_graph +0 -0
- data/lib/cpp_dependency_graph/bidirectional_hash.rb +1 -0
- data/lib/cpp_dependency_graph/component_dependency_graph.rb +1 -0
- data/lib/cpp_dependency_graph/dir_tree.rb +4 -1
- data/lib/cpp_dependency_graph/directory_parser.rb +13 -0
- data/lib/cpp_dependency_graph/file_dependency_graph.rb +1 -0
- data/lib/cpp_dependency_graph/graph_to_dot_visualiser.rb +10 -10
- data/lib/cpp_dependency_graph/include_component_dependency_graph.rb +1 -3
- data/lib/cpp_dependency_graph/include_file_dependency_graph.rb +2 -9
- data/lib/cpp_dependency_graph/include_to_component_resolver.rb +2 -0
- data/lib/cpp_dependency_graph/project.rb +25 -4
- data/lib/cpp_dependency_graph/source_component.rb +3 -2
- data/lib/cpp_dependency_graph/source_file.rb +1 -0
- data/lib/cpp_dependency_graph/version.rb +1 -1
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bab309d43e6015c06bf3836941534efe150bd78759d81f0e4ff538b4f33a054f
|
4
|
+
data.tar.gz: 46b1aadfe5915a147b9c89090c4cc7d047cdad269d9ec70a11c12567b56e8eb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ef9120a1d26f432cfc26e9906412391fa03aadbd34ebc5a110e3dfc674e22a6258f9f453044428da590d8ea51c873307345f09116b847c384ecc3f5787dddd0
|
7
|
+
data.tar.gz: 99995d31dce112db4b38fd9a4e71c4cb4d012829d727a260a396d0dd1def7008af60d0fcd3febe717c224582dd499c36c4ccfec5574c7166629daa72564dd8b2
|
data/bin/console
CHANGED
File without changes
|
@@ -29,8 +29,8 @@ Gem::Specification.new do |s|
|
|
29
29
|
s.rubygems_version = '3.1.2'
|
30
30
|
|
31
31
|
s.add_runtime_dependency 'docopt', '~> 0.6'
|
32
|
-
s.add_runtime_dependency 'ruby-graphviz', '~> 1.2'
|
33
32
|
s.add_runtime_dependency 'json', '~> 2.3.0'
|
33
|
+
s.add_runtime_dependency 'ruby-graphviz', '~> 1.2'
|
34
34
|
|
35
35
|
s.add_development_dependency 'bundler', '~> 2.1'
|
36
36
|
s.add_development_dependency 'debase', '~> 0.2'
|
data/exe/cpp_dependency_graph
CHANGED
File without changes
|
@@ -11,7 +11,7 @@ class DirTree
|
|
11
11
|
attr_reader :tree
|
12
12
|
|
13
13
|
def initialize(path)
|
14
|
-
@tree
|
14
|
+
@tree = File.directory?(path) ? parse_dirs(path) : {}
|
15
15
|
end
|
16
16
|
|
17
17
|
private
|
@@ -22,9 +22,12 @@ class DirTree
|
|
22
22
|
# TODO: Use Dir.map.compact|filter instead here
|
23
23
|
Dir.foreach(path) do |entry|
|
24
24
|
next if ['..', '.'].include?(entry)
|
25
|
+
|
25
26
|
full_path = File.join(path, entry)
|
26
27
|
next unless File.directory?(full_path)
|
28
|
+
|
27
29
|
next unless source_files_present?(full_path)
|
30
|
+
|
28
31
|
data[:children] << parse_dirs(full_path, entry)
|
29
32
|
end
|
30
33
|
data
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Utility methods for parsing directories
|
4
|
+
module DirectoryParser
|
5
|
+
def fetch_all_dirs(root_dir)
|
6
|
+
Find.find(root_dir).select { |e| File.directory?(e) && e != root_dir }
|
7
|
+
end
|
8
|
+
|
9
|
+
def glob_files(path, extensions)
|
10
|
+
path = File.join(path, File::SEPARATOR, '**', File::SEPARATOR, '*' + extensions)
|
11
|
+
Dir.glob(path).select { |entry| File.file?(entry) }.compact
|
12
|
+
end
|
13
|
+
end
|
@@ -6,9 +6,9 @@ require 'ruby-graphviz'
|
|
6
6
|
class GraphToDotVisualiser
|
7
7
|
def generate(deps, file)
|
8
8
|
@g = GraphViz.new('dependency_graph')
|
9
|
-
|
10
|
-
connect_nodes(deps
|
11
|
-
@g.output(:
|
9
|
+
create_nodes(deps)
|
10
|
+
connect_nodes(deps)
|
11
|
+
@g.output(dot: file)
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
@@ -17,20 +17,20 @@ class GraphToDotVisualiser
|
|
17
17
|
node_names = deps.flat_map do |_, links|
|
18
18
|
links.map { |link| [link.source, link.target] }.flatten
|
19
19
|
end.uniq
|
20
|
-
|
21
|
-
|
20
|
+
node_names.each do |name|
|
21
|
+
add_node(name)
|
22
|
+
end
|
22
23
|
end
|
23
24
|
|
24
|
-
def
|
25
|
-
|
26
|
-
node
|
25
|
+
def add_node(name)
|
26
|
+
@g.add_node(name, shape: 'box3d')
|
27
27
|
end
|
28
28
|
|
29
|
-
def connect_nodes(deps
|
29
|
+
def connect_nodes(deps)
|
30
30
|
deps.each do |source, links|
|
31
31
|
links.each do |link|
|
32
32
|
if link.cyclic?
|
33
|
-
@g.add_edges(source, link.target, :
|
33
|
+
@g.add_edges(source, link.target, color: 'red')
|
34
34
|
else
|
35
35
|
@g.add_edges(source, link.target)
|
36
36
|
end
|
@@ -11,9 +11,7 @@ class IncludeComponentDependencyGraph
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def all_links
|
14
|
-
|
15
|
-
all_source_files = components.values.flat_map(&:source_files)
|
16
|
-
all_source_files.map do |file|
|
14
|
+
@project.source_files.map do |file|
|
17
15
|
links = file.includes.map { |inc| Link.new(file.basename, inc, false) }
|
18
16
|
[file.basename, links]
|
19
17
|
end.to_h
|
@@ -10,22 +10,15 @@ class IncludeFileDependencyGraph
|
|
10
10
|
@project = project
|
11
11
|
end
|
12
12
|
|
13
|
-
def all_links
|
14
|
-
# TODO: Implement
|
15
|
-
{}
|
16
|
-
end
|
17
|
-
|
18
13
|
def all_cyclic_links
|
19
14
|
# TODO: Implement
|
20
15
|
end
|
21
16
|
|
22
17
|
def links(file_name)
|
23
|
-
|
24
|
-
all_source_files = components.values.flat_map(&:source_files)
|
25
|
-
files = all_source_files.select do |file|
|
18
|
+
files = @project.source_files.select do |_, file|
|
26
19
|
file.includes.include?(file_name)
|
27
20
|
end
|
28
|
-
files.map do |file|
|
21
|
+
files.map do |_, file|
|
29
22
|
links = [Link.new(file.basename, file_name, false)]
|
30
23
|
[file.basename, links]
|
31
24
|
end.to_h
|
@@ -19,6 +19,7 @@ class IncludeToComponentResolver
|
|
19
19
|
|
20
20
|
def component_for_include(include)
|
21
21
|
return '' unless source_files.key?(include)
|
22
|
+
|
22
23
|
@component_include_map_cache[include] = component_for_include_private(include) unless @component_include_map_cache.key?(include)
|
23
24
|
@component_include_map_cache[include]
|
24
25
|
end
|
@@ -35,6 +36,7 @@ class IncludeToComponentResolver
|
|
35
36
|
header_file = source_files[include]
|
36
37
|
implementation_files = implementation_files(header_file)
|
37
38
|
return header_file.parent_component if implementation_files.empty?
|
39
|
+
|
38
40
|
implementation_files[0].parent_component
|
39
41
|
end
|
40
42
|
|
@@ -2,11 +2,14 @@
|
|
2
2
|
|
3
3
|
require 'find'
|
4
4
|
|
5
|
+
require_relative 'directory_parser'
|
5
6
|
require_relative 'include_to_component_resolver'
|
6
7
|
require_relative 'source_component'
|
7
8
|
|
8
9
|
# Parses all components of a project
|
9
10
|
class Project
|
11
|
+
include DirectoryParser
|
12
|
+
|
10
13
|
def initialize(path)
|
11
14
|
@path = path
|
12
15
|
@include_resolver = IncludeToComponentResolver.new(source_components)
|
@@ -18,9 +21,18 @@ class Project
|
|
18
21
|
|
19
22
|
def source_component(name)
|
20
23
|
return SourceComponent.new('NULL') unless source_components.key?(name)
|
24
|
+
|
21
25
|
source_components[name]
|
22
26
|
end
|
23
27
|
|
28
|
+
def project_component
|
29
|
+
@project_component ||= build_project_component
|
30
|
+
end
|
31
|
+
|
32
|
+
def source_files
|
33
|
+
@source_files ||= build_source_files
|
34
|
+
end
|
35
|
+
|
24
36
|
def dependencies(component)
|
25
37
|
# TODO: This is repeating the same work twice! component_for_include is called when calling external_includes
|
26
38
|
external_includes(component).map { |include| @include_resolver.component_for_include(include) }.reject(&:empty?).uniq
|
@@ -32,6 +44,19 @@ class Project
|
|
32
44
|
|
33
45
|
private
|
34
46
|
|
47
|
+
def build_source_files
|
48
|
+
# TODO: Breaking Demeter's law here
|
49
|
+
files = project_component.values.flat_map(&:source_files)
|
50
|
+
files.map do |file|
|
51
|
+
[file.path, file]
|
52
|
+
end.to_h
|
53
|
+
end
|
54
|
+
|
55
|
+
def build_project_component
|
56
|
+
c = SourceComponent.new(@path)
|
57
|
+
{ c.name => c }
|
58
|
+
end
|
59
|
+
|
35
60
|
def build_source_components
|
36
61
|
# TODO: Dealing with source components with same dir name?
|
37
62
|
dirs = fetch_all_dirs(@path)
|
@@ -41,8 +66,4 @@ class Project
|
|
41
66
|
end.to_h
|
42
67
|
components.delete_if { |_, v| v.source_files.size.zero? }
|
43
68
|
end
|
44
|
-
|
45
|
-
def fetch_all_dirs(source_dir)
|
46
|
-
Find.find(source_dir).select { |e| File.directory?(e) }
|
47
|
-
end
|
48
69
|
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'config'
|
4
|
+
require_relative 'directory_parser'
|
4
5
|
require_relative 'source_file'
|
5
6
|
|
6
7
|
# Abstracts a source directory containing source files
|
7
8
|
class SourceComponent
|
8
9
|
include Config
|
10
|
+
include DirectoryParser
|
9
11
|
|
10
12
|
attr_reader :path
|
11
13
|
|
@@ -32,7 +34,6 @@ class SourceComponent
|
|
32
34
|
private
|
33
35
|
|
34
36
|
def parse_source_files(extensions)
|
35
|
-
|
36
|
-
Dir.glob(path).map { |e| SourceFile.new(e) if File.file?(e) }.compact
|
37
|
+
glob_files(@path, extensions).map { |e| SourceFile.new(e) }.compact
|
37
38
|
end
|
38
39
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cpp_dependency_graph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shreyas Balakrishna
|
@@ -25,33 +25,33 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 2.3.0
|
34
34
|
type: :runtime
|
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: 2.3.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: ruby-graphviz
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 2
|
47
|
+
version: '1.2'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 2
|
54
|
+
version: '1.2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: bundler
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -231,6 +231,7 @@ files:
|
|
231
231
|
- lib/cpp_dependency_graph/cycle_detector.rb
|
232
232
|
- lib/cpp_dependency_graph/cyclic_link.rb
|
233
233
|
- lib/cpp_dependency_graph/dir_tree.rb
|
234
|
+
- lib/cpp_dependency_graph/directory_parser.rb
|
234
235
|
- lib/cpp_dependency_graph/file_dependency_graph.rb
|
235
236
|
- lib/cpp_dependency_graph/graph_to_dot_visualiser.rb
|
236
237
|
- lib/cpp_dependency_graph/graph_to_graphml_visualiser.rb
|