courgette 0.1.0
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/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:
|