rdepend 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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +51 -0
- data/Rakefile +1 -0
- data/example.rb +16 -0
- data/fixtures/drie.rb +7 -0
- data/fixtures/een.rb +9 -0
- data/fixtures/twee.rb +12 -0
- data/lib/rdepend.rb +7 -0
- data/lib/rdepend/main.rb +13 -0
- data/lib/rdepend/printer.rb +129 -0
- data/lib/rdepend/trace.rb +30 -0
- data/lib/rdepend/trace_event.rb +54 -0
- data/lib/rdepend/version.rb +3 -0
- data/rdepend.gemspec +28 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3554b4b1d7f92ffb10ab23a4448d0ac688360dd9
|
4
|
+
data.tar.gz: d7ce6651c48d344354ca76e17d90bc565ee96d22
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 69a016abcc816a5acfb306a55d649559032e6857bfe54cce1edb9e4f4ed39573c335afa0743673e063d36ad591b73d0b7270d73790d0406e7922d75eb3661684
|
7
|
+
data.tar.gz: 979f0ce215b0ea2b1f6a1ae8f29b8fc74fdf2ee9138e9b520fac8c811909bc2c754a1499eb50d56dfd02c3a3959477907f49791e28ac0db0151ca739ed81dd9e
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.2
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 jarra
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Ꝛdepend
|
2
|
+
|
3
|
+
Mind that this Gem is very experimental, a work in progress
|
4
|
+
|
5
|
+
It generates a graph visualization of the dependencies in your codebase.
|
6
|
+
|
7
|
+
A lot of incoming links are good, as that means that a function/module is
|
8
|
+
re-used a lot.
|
9
|
+
A lot of outgoing links a bad, as that means that that part of the code has
|
10
|
+
a lot of dependencies.
|
11
|
+
|
12
|
+
See also http://www.whiteboxtest.com/information-flow-metrics.php
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
gem 'rdepend'
|
20
|
+
```
|
21
|
+
|
22
|
+
And then execute:
|
23
|
+
|
24
|
+
$ bundle
|
25
|
+
|
26
|
+
Or install it yourself as:
|
27
|
+
|
28
|
+
$ gem install rdepend
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
Rdepend.with_trace do
|
34
|
+
@een = Een.new
|
35
|
+
@een.start
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
Rdepend.trace
|
41
|
+
@een = Een.new
|
42
|
+
@een.start
|
43
|
+
```
|
44
|
+
|
45
|
+
## Contributing
|
46
|
+
|
47
|
+
1. Fork it ( https://github.com/[my-github-username]/rdepend/fork )
|
48
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
49
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
50
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
51
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/example.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/lib/rdepend.rb')
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/fixtures/een.rb')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/fixtures/twee.rb')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/fixtures/drie.rb')
|
6
|
+
|
7
|
+
=begin
|
8
|
+
Rdepend.with_trace do
|
9
|
+
@een = Een.new
|
10
|
+
@een.start
|
11
|
+
end
|
12
|
+
=end
|
13
|
+
|
14
|
+
Rdepend.trace
|
15
|
+
@een = Een.new
|
16
|
+
@een.start
|
data/fixtures/drie.rb
ADDED
data/fixtures/een.rb
ADDED
data/fixtures/twee.rb
ADDED
data/lib/rdepend.rb
ADDED
data/lib/rdepend/main.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Rdepend
|
6
|
+
# Generates a graphviz graph in dot format.
|
7
|
+
# To use the dot printer:
|
8
|
+
#
|
9
|
+
# result = RubyProf.profile do
|
10
|
+
# [code to profile]
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# printer = RubyProf::Printer.new(result)
|
14
|
+
# printer.print(STDOUT)
|
15
|
+
#
|
16
|
+
# You can use either dot viewer such as GraphViz, or the dot command line tool
|
17
|
+
# to reformat the output into a wide variety of outputs:
|
18
|
+
#
|
19
|
+
# dot -Tpng graph.dot > graph.png
|
20
|
+
#
|
21
|
+
class Printer < RubyProf::AbstractPrinter
|
22
|
+
CLASS_COLOR = '"#666666"'
|
23
|
+
EDGE_COLOR = '"#666666"'
|
24
|
+
|
25
|
+
# Creates the Printer using a RubyProf::Result.
|
26
|
+
def initialize(result)
|
27
|
+
super(result)
|
28
|
+
@seen_methods = Set.new
|
29
|
+
end
|
30
|
+
|
31
|
+
# Print a graph report to the provided output.
|
32
|
+
#
|
33
|
+
# output - Any IO object, including STDOUT or a file. The default value is
|
34
|
+
# STDOUT.
|
35
|
+
#
|
36
|
+
# options - Hash of print options. See #setup_options
|
37
|
+
# for more information.
|
38
|
+
#
|
39
|
+
# When profiling results that cover a large number of method calls it
|
40
|
+
# helps to use the :min_percent option, for example:
|
41
|
+
#
|
42
|
+
# Printer.new(result).print(STDOUT, :min_percent=>5)
|
43
|
+
#
|
44
|
+
def print(output = STDOUT, options = {})
|
45
|
+
setup_options(options)
|
46
|
+
add('digraph "Profile" {')
|
47
|
+
#add("label=\"#{mode_name} >=#{min_percent}%\\nTotal: #{total_time}\";"
|
48
|
+
add("labelloc=t;")
|
49
|
+
add("labeljust=l;")
|
50
|
+
print_threads
|
51
|
+
add('}')
|
52
|
+
if output == STDOUT
|
53
|
+
@output = File.open(output, 'w')
|
54
|
+
else
|
55
|
+
File.open(output, 'w') { |file| file.write(@contents.join("\n")) }
|
56
|
+
end
|
57
|
+
`dot -Tsvg #{output} > #{output}.svg`
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# Something of a hack, figure out which constant went with the
|
63
|
+
# RubyProf.measure_mode so that we can display it. Otherwise it's easy to
|
64
|
+
# forget what measurement was made.
|
65
|
+
def mode_name
|
66
|
+
RubyProf.constants.find{|c| RubyProf.const_get(c) == RubyProf.measure_mode}
|
67
|
+
end
|
68
|
+
|
69
|
+
def print_threads
|
70
|
+
@result.threads.each do |thread|
|
71
|
+
add("subgraph \"Thread #{thread.id}\" {")
|
72
|
+
print_thread(thread)
|
73
|
+
add("}")
|
74
|
+
print_classes(thread)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Determines an ID to use to represent the subject in the Dot file.
|
79
|
+
def dot_id(subject)
|
80
|
+
subject.object_id
|
81
|
+
end
|
82
|
+
|
83
|
+
def print_thread(thread)
|
84
|
+
total_time = thread.total_time
|
85
|
+
thread.methods.sort_by(&sort_method).reverse_each do |method|
|
86
|
+
total_percentage = (method.total_time/total_time) * 100
|
87
|
+
next if total_percentage < min_percent
|
88
|
+
name = method_name(method).split("#").last
|
89
|
+
add("#{dot_id(method)} [label=\"#{name}\\n(#{total_percentage.round}%)\"];")
|
90
|
+
@seen_methods << method
|
91
|
+
print_edges(total_time, method)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def print_classes(thread)
|
96
|
+
grouped = {}
|
97
|
+
thread.methods.each{|m| grouped[m.klass_name] ||= []; grouped[m.klass_name] << m}
|
98
|
+
grouped.each do |cls, methods2|
|
99
|
+
# Filter down to just seen methods
|
100
|
+
big_methods = methods2.select{|m| @seen_methods.include? m}
|
101
|
+
if !big_methods.empty?
|
102
|
+
add("subgraph cluster_#{cls.object_id} {")
|
103
|
+
add("label = \"#{cls}\";")
|
104
|
+
add("fontcolor = #{CLASS_COLOR};")
|
105
|
+
add("fontsize = 16;")
|
106
|
+
add("color = #{CLASS_COLOR};")
|
107
|
+
big_methods.each do |m|
|
108
|
+
add("#{m.object_id};")
|
109
|
+
end
|
110
|
+
add("}")
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def print_edges(total_time, method)
|
116
|
+
method.aggregate_children.sort_by(&:total_time).reverse.each do |child|
|
117
|
+
target_percentage = (child.target.total_time / total_time) * 100.0
|
118
|
+
next if target_percentage < min_percent
|
119
|
+
# Get children method
|
120
|
+
add("#{dot_id(method)} -> #{dot_id(child.target)} [label=\"#{child.called}/#{child.target.called}\" fontsize=10 fontcolor=#{EDGE_COLOR}];")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Silly little helper for printing to the @output
|
125
|
+
def add(str)
|
126
|
+
(@contents ||= []) << str
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
at_exit do
|
2
|
+
Rdepend::Trace.halt_with_message
|
3
|
+
end
|
4
|
+
|
5
|
+
module Rdepend
|
6
|
+
class Trace
|
7
|
+
def self.exec(&block)
|
8
|
+
self.start
|
9
|
+
yield
|
10
|
+
self.stop
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.init
|
14
|
+
RubyProf.start
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.stop
|
18
|
+
result = RubyProf.stop
|
19
|
+
result.eliminate_methods!([/Integer#times/])
|
20
|
+
printer = Rdepend::Printer.new(result)
|
21
|
+
puts "Writing Ꝛdepend graph to #{$0}.dot.svg"
|
22
|
+
printer.print("#{$0}.dot")
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.halt_with_message
|
26
|
+
puts "⏳ Exiting, but writing an Ꝛdepend graph first, so please wait!"
|
27
|
+
self.stop
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
Rdepend::TraceEvent = Struct.new(:event_type, :defined_class,
|
2
|
+
:method_id, :path, :lineno) do
|
3
|
+
def event_class
|
4
|
+
"Rdepend::Event::#{event_type.to_s.classify}".constantize
|
5
|
+
end
|
6
|
+
|
7
|
+
def key
|
8
|
+
"#{path}:#{method_id}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def root?
|
12
|
+
method_id == '<main>'
|
13
|
+
end
|
14
|
+
|
15
|
+
def defined_class
|
16
|
+
self[:defined_class].to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
def instance?
|
20
|
+
!klass?
|
21
|
+
end
|
22
|
+
|
23
|
+
def klass?
|
24
|
+
defined_class =~ /^#<(Module|Class):\w*.*>$/
|
25
|
+
end
|
26
|
+
|
27
|
+
def klass
|
28
|
+
name.klass
|
29
|
+
end
|
30
|
+
|
31
|
+
def method
|
32
|
+
name.method
|
33
|
+
end
|
34
|
+
|
35
|
+
def label
|
36
|
+
if root?
|
37
|
+
'main'
|
38
|
+
else
|
39
|
+
method_id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def name
|
46
|
+
if root?
|
47
|
+
Rdepend::Event::RootName.new(self)
|
48
|
+
elsif instance?
|
49
|
+
Rdepend::Event::InstanceName.new(self)
|
50
|
+
else
|
51
|
+
Rdepend::Event::KlassName.new(self)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/rdepend.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'rdepend/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'rdepend'
|
8
|
+
spec.version = Rdepend::VERSION
|
9
|
+
spec.authors = ['jarra']
|
10
|
+
spec.email = ['suhrawardi@gmail.com']
|
11
|
+
spec.summary = %q(generates a graph visualization of the dependencies in your codebase)
|
12
|
+
spec.description = %q(a work in progress, use it at your own risk)
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r(^bin/)) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r(^(test|spec|features)/))
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 1.9.3'
|
22
|
+
|
23
|
+
spec.add_dependency 'ruby-graphviz'
|
24
|
+
spec.add_dependency 'ruby-prof'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
27
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rdepend
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jarra
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruby-graphviz
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ruby-prof
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
description: a work in progress, use it at your own risk
|
70
|
+
email:
|
71
|
+
- suhrawardi@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- ".ruby-version"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- example.rb
|
84
|
+
- fixtures/drie.rb
|
85
|
+
- fixtures/een.rb
|
86
|
+
- fixtures/twee.rb
|
87
|
+
- lib/rdepend.rb
|
88
|
+
- lib/rdepend/main.rb
|
89
|
+
- lib/rdepend/printer.rb
|
90
|
+
- lib/rdepend/trace.rb
|
91
|
+
- lib/rdepend/trace_event.rb
|
92
|
+
- lib/rdepend/version.rb
|
93
|
+
- rdepend.gemspec
|
94
|
+
homepage: ''
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.9.3
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.4.8
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: generates a graph visualization of the dependencies in your codebase
|
118
|
+
test_files: []
|