rdepend 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /Gemfile.lock
3
+ /doc/
4
+ /pkg/
5
+ /tmp/
6
+ /ext/
7
+ *.bundle
8
+ *.so
9
+ *.o
10
+ *.a
11
+ mkmf.log
12
+
13
+ *.dot.svg
14
+ *.dot
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rdepend.gemspec
4
+ gemspec
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
@@ -0,0 +1,7 @@
1
+ class Drie
2
+ def initialize
3
+ end
4
+
5
+ def vier
6
+ end
7
+ end
data/fixtures/een.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Een
2
+ def initialize
3
+ Twee.twee
4
+ end
5
+
6
+ def start
7
+ Drie.new.vier
8
+ end
9
+ end
data/fixtures/twee.rb ADDED
@@ -0,0 +1,12 @@
1
+ class Twee
2
+ def initialize
3
+ end
4
+
5
+ def self.twee
6
+ new.drie
7
+ end
8
+
9
+ def drie
10
+ Drie.new
11
+ end
12
+ end
data/lib/rdepend.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'ruby-graphviz'
2
+ require 'ruby-prof'
3
+
4
+ require_relative 'rdepend/version'
5
+ require_relative 'rdepend/printer'
6
+ require_relative 'rdepend/trace'
7
+ require_relative 'rdepend/main'
@@ -0,0 +1,13 @@
1
+ module Rdepend
2
+ def self.with_trace(&block)
3
+ Rdepend::Trace.exec(&block)
4
+ end
5
+
6
+ def self.trace
7
+ Rdepend::Trace.init
8
+ end
9
+
10
+ def self.stop
11
+ Rdepend::Trace.stop
12
+ end
13
+ end
@@ -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
@@ -0,0 +1,3 @@
1
+ module Rdepend
2
+ VERSION = '0.0.1'
3
+ 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: []