courgette 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Rakefile +8 -0
- data/bin/courgette.rb +40 -0
- data/courgette.gemspec +28 -0
- data/lib/courgette/capturer.rb +88 -0
- data/lib/courgette/commands/graph.rb +46 -0
- data/lib/courgette/commands/stats.rb +42 -0
- data/lib/courgette/directory_analyser.rb +38 -0
- data/lib/courgette/file_to_sexpr.rb +15 -0
- data/lib/courgette/graph.rb +20 -0
- data/lib/courgette/graph2dot.rb +56 -0
- data/lib/courgette/name_resolution.rb +27 -0
- data/lib/courgette/node_grouper.rb +31 -0
- data/lib/courgette/reference_to_dependency.rb +20 -0
- data/lib/courgette/scope.rb +14 -0
- data/lib/courgette/version.rb +4 -0
- data/lib/courgette.rb +2 -0
- data/test/courgette/test_name_resolution.rb +72 -0
- data/test/courgette/test_scope.rb +31 -0
- metadata +151 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 57adf4c4137fcf9342cc36a2da2d18bae46adff3
|
4
|
+
data.tar.gz: c7d05925b78857a07c8765859e9c945dbcffd3e8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 17e68370df6b304fdf7973b9f969e53d5bc9f30764a2eebdf0b33442b48bfddf6d4b40a81bcb4bd35679448e23a1962e222688339fc1797670d75943f732d5a4
|
7
|
+
data.tar.gz: bf96fc9d079926ea905030564e21a12f2543fbe546249056c53c85565deed8d05ac56e49b608e68d2fc3750009480a258506e7968aa8f5cd67aa5a6640e0ff2c
|
data/Gemfile
ADDED
data/Rakefile
ADDED
data/bin/courgette.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'commander/import'
|
5
|
+
|
6
|
+
require 'courgette/commands/graph'
|
7
|
+
require 'courgette/commands/stats'
|
8
|
+
|
9
|
+
program :version, '1.0.0'
|
10
|
+
program :description, 'Dependency graph fetcher'
|
11
|
+
|
12
|
+
default_command :stats
|
13
|
+
|
14
|
+
command :stats do |c|
|
15
|
+
c.syntax = 'courgette stats [options]'
|
16
|
+
c.summary = ''
|
17
|
+
c.description = ''
|
18
|
+
c.example 'description', 'command example'
|
19
|
+
c.option '--glob STRING', String, 'Glob to run metrics over (default: **/*.rb)'
|
20
|
+
c.action do |args, options|
|
21
|
+
options.default :glob => '**/*.rb'
|
22
|
+
|
23
|
+
Courgette::Commands::Stats.new(options).run
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
command :graph do |c|
|
28
|
+
c.syntax = 'courgette graph [options]'
|
29
|
+
c.summary = ''
|
30
|
+
c.description = ''
|
31
|
+
c.example 'description', 'command example'
|
32
|
+
c.option '--glob STRING', String, 'Glob to run metrics over (default: **/*.rb)'
|
33
|
+
c.option '--name STRING', String, 'Glob to run metrics over (default: graph)'
|
34
|
+
c.option '--format STRING', String, 'Format (default: png)'
|
35
|
+
c.action do |args, options|
|
36
|
+
options.default :glob => '**/*.rb', :format => 'png', :name => 'graph'
|
37
|
+
|
38
|
+
Courgette::Commands::Graph.new(options).run
|
39
|
+
end
|
40
|
+
end
|
data/courgette.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 'courgette/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "courgette"
|
8
|
+
spec.version = Courgette::VERSION
|
9
|
+
spec.authors = ["Hugo Peixoto"]
|
10
|
+
spec.email = ["hugo.peixoto@gmail.com"]
|
11
|
+
spec.description = %q{Static ruby dependency analyser}
|
12
|
+
spec.summary = %q{Courgette analyses a set of files, and calculates a dependency graph}
|
13
|
+
spec.homepage = "https://github.com/hugopeixoto/courgette"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
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.add_dependency "ruby_parser"
|
22
|
+
spec.add_dependency "commander"
|
23
|
+
spec.add_dependency "graph"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
spec.add_development_dependency "minitest"
|
28
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'courgette/scope'
|
2
|
+
|
3
|
+
module Courgette
|
4
|
+
class Capturer
|
5
|
+
def initialize
|
6
|
+
@references = []
|
7
|
+
@definitions = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def capture sexpr
|
11
|
+
iterate sexpr, []
|
12
|
+
end
|
13
|
+
|
14
|
+
def references
|
15
|
+
@references.uniq! { |reference| reference.to_a }
|
16
|
+
@references
|
17
|
+
end
|
18
|
+
|
19
|
+
def definitions
|
20
|
+
@definitions.uniq! { |definition| definition.to_a }
|
21
|
+
@definitions
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
Reference = Struct.new :name, :context
|
26
|
+
|
27
|
+
def add_definition definition
|
28
|
+
@definitions << definition.flatten
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_reference context, reference
|
32
|
+
@references << Reference.new(reference, context)
|
33
|
+
end
|
34
|
+
|
35
|
+
def scope sexpr
|
36
|
+
Courgette::Scope.new.scope sexpr
|
37
|
+
end
|
38
|
+
|
39
|
+
def iterate_many sexprs, context
|
40
|
+
sexprs.each do |sexpr|
|
41
|
+
iterate sexpr, context
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def iterate_cdecl sexpr, context
|
46
|
+
s = scope sexpr[1]
|
47
|
+
new_context = context + [s]
|
48
|
+
add_definition new_context
|
49
|
+
|
50
|
+
iterate_many sexpr[2..-1], context
|
51
|
+
end
|
52
|
+
|
53
|
+
def iterate_definition sexpr, context
|
54
|
+
s = scope sexpr[1]
|
55
|
+
new_context = context + [s]
|
56
|
+
add_definition new_context
|
57
|
+
|
58
|
+
iterate_many sexpr[2..-1], new_context
|
59
|
+
end
|
60
|
+
|
61
|
+
def iterate_call sexpr, context
|
62
|
+
iterate sexpr[1], context
|
63
|
+
iterate_many sexpr[3..-1], context
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def iterate sexpr, context
|
68
|
+
return unless sexpr.is_a? Enumerable
|
69
|
+
|
70
|
+
case sexpr[0]
|
71
|
+
when :const, :colon2
|
72
|
+
add_reference context, scope(sexpr)
|
73
|
+
when :module, :class
|
74
|
+
iterate_definition sexpr, context
|
75
|
+
when :cdecl
|
76
|
+
iterate_cdecl sexpr, context
|
77
|
+
when :defn
|
78
|
+
iterate_many sexpr[3..-1], context
|
79
|
+
|
80
|
+
when :call
|
81
|
+
iterate_call sexpr, context
|
82
|
+
when :nil, :lit
|
83
|
+
else
|
84
|
+
iterate_many sexpr[1..-1], context
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'courgette/directory_analyser'
|
2
|
+
require 'courgette/graph2dot'
|
3
|
+
|
4
|
+
module Courgette
|
5
|
+
module Commands
|
6
|
+
class Graph
|
7
|
+
def initialize options
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
factory.load graph
|
13
|
+
|
14
|
+
formats.each do |fmt|
|
15
|
+
factory.save name, fmt
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
def glob
|
21
|
+
@options.glob
|
22
|
+
end
|
23
|
+
|
24
|
+
def formats
|
25
|
+
Array(@options.format)
|
26
|
+
end
|
27
|
+
|
28
|
+
def name
|
29
|
+
@options.name
|
30
|
+
end
|
31
|
+
|
32
|
+
def factory
|
33
|
+
@factory ||= Courgette::Graph2Dot.new do
|
34
|
+
boxes
|
35
|
+
node_attribs << filled
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def graph
|
40
|
+
@graph ||= Courgette::DirectoryAnalyser.new.tap do |da|
|
41
|
+
da.analyse glob
|
42
|
+
end.graph
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'courgette/directory_analyser'
|
2
|
+
|
3
|
+
module Courgette
|
4
|
+
module Commands
|
5
|
+
class Stats
|
6
|
+
def initialize options
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
stats.each do |fanout, fanin, reference|
|
12
|
+
print_reference fanout, fanin, reference
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def print_reference fo, fi, ref
|
17
|
+
print "%8d %8d: %s\n" % [fo, fi, ref.join("::")]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def glob
|
22
|
+
@options.glob
|
23
|
+
end
|
24
|
+
|
25
|
+
def stats
|
26
|
+
@stats ||= graph.nodes.map do |node|
|
27
|
+
[
|
28
|
+
graph.dependency_count(node),
|
29
|
+
graph.depender_count(node),
|
30
|
+
node
|
31
|
+
]
|
32
|
+
end.sort
|
33
|
+
end
|
34
|
+
|
35
|
+
def graph
|
36
|
+
@graph ||= Courgette::DirectoryAnalyser.new.tap do |da|
|
37
|
+
da.analyse glob
|
38
|
+
end.graph
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'courgette/capturer'
|
2
|
+
require 'courgette/reference_to_dependency'
|
3
|
+
require 'courgette/file_to_sexpr'
|
4
|
+
require 'courgette/graph'
|
5
|
+
|
6
|
+
module Courgette
|
7
|
+
class DirectoryAnalyser
|
8
|
+
def initialize
|
9
|
+
@capturer = Courgette::Capturer.new
|
10
|
+
@file2sexpr = Courgette::FileToSexpr.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def analyse pattern
|
14
|
+
Dir.glob(pattern) do |file|
|
15
|
+
capturer.capture file2sexpr.convert(file)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def graph
|
20
|
+
Courgette::Graph.new definitions, dependencies
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
attr_reader :capturer, :file2sexpr
|
25
|
+
|
26
|
+
def definitions
|
27
|
+
capturer.definitions
|
28
|
+
end
|
29
|
+
|
30
|
+
def dependencies
|
31
|
+
r2d = Courgette::ReferenceToDependency.new definitions
|
32
|
+
|
33
|
+
capturer.references.map do |reference|
|
34
|
+
r2d.transform reference
|
35
|
+
end.compact
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Courgette
|
2
|
+
class Graph
|
3
|
+
attr_reader :nodes, :edges
|
4
|
+
|
5
|
+
def initialize nodes, edges
|
6
|
+
@nodes = nodes
|
7
|
+
@edges = edges
|
8
|
+
end
|
9
|
+
|
10
|
+
def dependency_count node
|
11
|
+
edges.select { |r| r.referrer == node }.count
|
12
|
+
end
|
13
|
+
|
14
|
+
def depender_count node
|
15
|
+
edges.select { |r| r.reference == node }.count
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'courgette/node_grouper'
|
2
|
+
require 'graph'
|
3
|
+
|
4
|
+
module Courgette
|
5
|
+
class Graph2Dot
|
6
|
+
def initialize &block
|
7
|
+
@dot = digraph &block
|
8
|
+
end
|
9
|
+
|
10
|
+
def load graph
|
11
|
+
calculate_distinct_namespaces graph.nodes
|
12
|
+
set_colorscheme
|
13
|
+
|
14
|
+
graph.nodes.each do |node|
|
15
|
+
add_node node
|
16
|
+
end
|
17
|
+
|
18
|
+
graph.edges.each do |edge|
|
19
|
+
add_edge edge
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def save *args
|
24
|
+
dot.save *args
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
attr_reader :dot
|
29
|
+
|
30
|
+
def set_colorscheme
|
31
|
+
dot.colorscheme(:set2, [4, [8, @grouper.groups.count + 1].min].max)
|
32
|
+
end
|
33
|
+
|
34
|
+
def calculate_distinct_namespaces nodes
|
35
|
+
@grouper = Courgette::NodeGrouper.new nodes, 8
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_node node
|
39
|
+
color(node) << dot.node(label(node))
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_edge edge
|
43
|
+
dot.edge(label(edge.referrer), label(edge.reference))
|
44
|
+
end
|
45
|
+
|
46
|
+
def color node
|
47
|
+
idx = @grouper.group node
|
48
|
+
|
49
|
+
dot.send "c#{idx}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def label node
|
53
|
+
node.flatten.join("::")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Courgette
|
2
|
+
class NameResolution
|
3
|
+
def initialize definitions
|
4
|
+
@definitions = definitions
|
5
|
+
end
|
6
|
+
|
7
|
+
def resolve reference
|
8
|
+
definitions.find do |definition|
|
9
|
+
match_name?(definition, reference) &&
|
10
|
+
match_scope?(definition, reference)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
attr_reader :definitions
|
16
|
+
|
17
|
+
def match_name? definition, reference
|
18
|
+
definition.last == reference.name.last
|
19
|
+
end
|
20
|
+
|
21
|
+
def match_scope? definition, reference
|
22
|
+
(0..reference.context.length).any? do |level|
|
23
|
+
reference.context[0...level].flatten + reference.name == definition
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Courgette
|
2
|
+
class NodeGrouper
|
3
|
+
def initialize nodes, max_groups
|
4
|
+
@nodes = nodes
|
5
|
+
@max_groups = max_groups
|
6
|
+
|
7
|
+
calculate
|
8
|
+
end
|
9
|
+
|
10
|
+
def group node
|
11
|
+
idx = namespaces.index node[0...-1][0...1]
|
12
|
+
idx ||= -1
|
13
|
+
idx = [2 + idx, @max_groups].min
|
14
|
+
end
|
15
|
+
|
16
|
+
def groups
|
17
|
+
@namespaces
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
attr_reader :nodes, :namespaces
|
22
|
+
|
23
|
+
def calculate
|
24
|
+
@namespaces = nodes.
|
25
|
+
group_by { |n| n[0...-1][0...1] }.
|
26
|
+
reject { |k, v| k.empty? || v.length < 4 }.
|
27
|
+
map(&:first).
|
28
|
+
uniq
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'courgette/name_resolution'
|
2
|
+
|
3
|
+
module Courgette
|
4
|
+
class ReferenceToDependency
|
5
|
+
def initialize definitions
|
6
|
+
@resolver = Courgette::NameResolution.new definitions
|
7
|
+
end
|
8
|
+
|
9
|
+
def transform reference
|
10
|
+
definition = @resolver.resolve reference
|
11
|
+
return if definition.nil?
|
12
|
+
|
13
|
+
Dependency.new definition, reference.context.flatten
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
attr_reader :resolver
|
18
|
+
Dependency = Struct.new :reference, :referrer
|
19
|
+
end
|
20
|
+
end
|
data/lib/courgette.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'courgette/name_resolution'
|
3
|
+
|
4
|
+
FakeReference = Struct.new :name, :context
|
5
|
+
|
6
|
+
class TestCourgetteNameResolution < MiniTest::Unit::TestCase
|
7
|
+
def create definitions
|
8
|
+
@resolver = Courgette::NameResolution.new definitions
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_root_level
|
12
|
+
create [[:RootA], [:RootB]]
|
13
|
+
|
14
|
+
ref = FakeReference.new [:RootA], []
|
15
|
+
|
16
|
+
assert_equal [:RootA], @resolver.resolve(ref)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_root_unknown
|
20
|
+
create [[:Root]]
|
21
|
+
|
22
|
+
ref = FakeReference.new [:Unknown], []
|
23
|
+
|
24
|
+
assert_equal nil, @resolver.resolve(ref)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_top_definition_referenced_from_nested
|
28
|
+
create [[:Root]]
|
29
|
+
|
30
|
+
ref = FakeReference.new [:Root], [[:A, :B]]
|
31
|
+
assert_equal [:Root], @resolver.resolve(ref)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_nested_definition_referenced_from_nested
|
35
|
+
create [[:Scoped, :Name]]
|
36
|
+
|
37
|
+
ref = FakeReference.new [:Name], [[:Scoped]]
|
38
|
+
assert_equal [:Scoped, :Name], @resolver.resolve(ref)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_double_scope
|
42
|
+
definition = [:Potato, :Scoped, :Name]
|
43
|
+
create [definition]
|
44
|
+
|
45
|
+
ref = FakeReference.new [:Name], [[:Potato], [:Scoped]]
|
46
|
+
assert_equal definition, @resolver.resolve(ref)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_grouped_double_scope
|
50
|
+
definition = [:Potato, :Scoped, :Name]
|
51
|
+
create [definition]
|
52
|
+
|
53
|
+
ref = FakeReference.new [:Name], [[:Potato, :Scoped]]
|
54
|
+
assert_equal definition, @resolver.resolve(ref)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_scoped_definition_referenced_double
|
58
|
+
definition = [:Potato, :Name]
|
59
|
+
create [definition]
|
60
|
+
|
61
|
+
ref = FakeReference.new [:Name], [[:Potato], [:Scoped]]
|
62
|
+
assert_equal definition, @resolver.resolve(ref)
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_scoped_definition_referenced_grouped
|
66
|
+
definition = [:Potato, :Name]
|
67
|
+
create [definition]
|
68
|
+
|
69
|
+
ref = FakeReference.new [:Name], [[:Potato, :Scoped]]
|
70
|
+
assert_equal nil, @resolver.resolve(ref)
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'courgette/scope'
|
3
|
+
|
4
|
+
class TestCourgetteScope < MiniTest::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@scope = Courgette::Scope.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_const
|
10
|
+
assert_equal [:Name], @scope.scope([:const, :Name])
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_other
|
14
|
+
assert_equal [:potato], @scope.scope(:potato)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_colon2
|
18
|
+
assert_equal [:Scoped, :Name],
|
19
|
+
@scope.scope([:colon2, :Scoped, :Name])
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_compose
|
23
|
+
assert_equal [:Really, :Scoped, :Name],
|
24
|
+
@scope.scope(
|
25
|
+
[:colon2,
|
26
|
+
[:colon2,
|
27
|
+
[:const, :Really],
|
28
|
+
[:const, :Scoped]],
|
29
|
+
[:const, :Name]])
|
30
|
+
end
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: courgette
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Hugo Peixoto
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ruby_parser
|
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: commander
|
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: graph
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: bundler
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.3'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Static ruby dependency analyser
|
98
|
+
email:
|
99
|
+
- hugo.peixoto@gmail.com
|
100
|
+
executables:
|
101
|
+
- courgette.rb
|
102
|
+
extensions: []
|
103
|
+
extra_rdoc_files: []
|
104
|
+
files:
|
105
|
+
- Gemfile
|
106
|
+
- Rakefile
|
107
|
+
- bin/courgette.rb
|
108
|
+
- courgette.gemspec
|
109
|
+
- lib/courgette.rb
|
110
|
+
- lib/courgette/capturer.rb
|
111
|
+
- lib/courgette/commands/graph.rb
|
112
|
+
- lib/courgette/commands/stats.rb
|
113
|
+
- lib/courgette/directory_analyser.rb
|
114
|
+
- lib/courgette/file_to_sexpr.rb
|
115
|
+
- lib/courgette/graph.rb
|
116
|
+
- lib/courgette/graph2dot.rb
|
117
|
+
- lib/courgette/name_resolution.rb
|
118
|
+
- lib/courgette/node_grouper.rb
|
119
|
+
- lib/courgette/reference_to_dependency.rb
|
120
|
+
- lib/courgette/scope.rb
|
121
|
+
- lib/courgette/version.rb
|
122
|
+
- test/courgette/test_name_resolution.rb
|
123
|
+
- test/courgette/test_scope.rb
|
124
|
+
homepage: https://github.com/hugopeixoto/courgette
|
125
|
+
licenses:
|
126
|
+
- MIT
|
127
|
+
metadata: {}
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
require_paths:
|
131
|
+
- lib
|
132
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
|
+
requirements:
|
139
|
+
- - '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
requirements: []
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 2.0.3
|
145
|
+
signing_key:
|
146
|
+
specification_version: 4
|
147
|
+
summary: Courgette analyses a set of files, and calculates a dependency graph
|
148
|
+
test_files:
|
149
|
+
- test/courgette/test_name_resolution.rb
|
150
|
+
- test/courgette/test_scope.rb
|
151
|
+
has_rdoc:
|