code_node 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/cog/generators/overview.rb +49 -0
- data/lib/code_node/ir/graph.rb +9 -3
- data/lib/code_node/ir/node.rb +3 -2
- data/lib/code_node/sexp_walker.rb +9 -7
- data/lib/code_node/spec_helpers.rb +23 -0
- data/lib/code_node/spec_helpers/dot_file.rb +114 -0
- data/lib/code_node/spec_helpers/runner.rb +25 -0
- data/lib/code_node/version.rb +1 -1
- metadata +8 -4
@@ -0,0 +1,49 @@
|
|
1
|
+
require '/Users/kevin/bc/code_node/lib/code_node.rb'
|
2
|
+
|
3
|
+
# Makes a graph of the project_source_path.
|
4
|
+
# Nodes in the graph are clases and modules from your project.
|
5
|
+
CodeNode.graph 'overview' do |g|
|
6
|
+
|
7
|
+
# Nodes
|
8
|
+
# =====
|
9
|
+
|
10
|
+
# Ignore nodes with no relations to other nodes
|
11
|
+
g.ignore &:island?
|
12
|
+
|
13
|
+
# Uncomment and change the value to ignore a specific node
|
14
|
+
# g.ignore 'Foo::Bar::Car'
|
15
|
+
|
16
|
+
# Uncomment to ignore nodes named ClassMethods
|
17
|
+
# g.ignore /::ClassMethods$/
|
18
|
+
|
19
|
+
# Uncomment and change the value to ignore all nodes descending
|
20
|
+
# from a specific node
|
21
|
+
# g.ignore {|node| node.inherits_from? 'Foo::Bar::Car'}
|
22
|
+
|
23
|
+
# Apply styles common to all classes
|
24
|
+
g.style :shape => 'ellipse', :fillcolor => '#cccccc', :fontcolor => :black do |node|
|
25
|
+
node.class?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Apply styles common to all nodes
|
29
|
+
g.style :shape => 'box', :fillcolor => '#333333', :fontcolor => :white do |node|
|
30
|
+
node.module?
|
31
|
+
end
|
32
|
+
|
33
|
+
# Apply more specific style here
|
34
|
+
# ...
|
35
|
+
|
36
|
+
# Edges
|
37
|
+
# =====
|
38
|
+
#
|
39
|
+
# There is currently no way to style edges from the DSL.
|
40
|
+
# For now, there are only four categories of edges:
|
41
|
+
# - containment
|
42
|
+
# - inheritance
|
43
|
+
# - inclusion
|
44
|
+
# - extension
|
45
|
+
#
|
46
|
+
# They are style in the template. You can override the template
|
47
|
+
# and change the color if you like.
|
48
|
+
# $ cog -t code_node template new -f code_node/graph.dot
|
49
|
+
end
|
data/lib/code_node/ir/graph.rb
CHANGED
@@ -154,11 +154,17 @@ module CodeNode
|
|
154
154
|
return if name.nil?
|
155
155
|
|
156
156
|
node = if opt[:not_sure_if_nested]
|
157
|
-
|
158
|
-
|
157
|
+
candidate = if name.is_a?(Array)
|
158
|
+
parts = name.dup
|
159
|
+
n = !@scope.empty? && @scope.last.find(parts.shift)
|
160
|
+
while n && !parts.empty?
|
161
|
+
n = n.find parts.shift
|
162
|
+
end
|
163
|
+
n
|
159
164
|
else
|
160
|
-
|
165
|
+
!@scope.empty? && @scope.last.find(name)
|
161
166
|
end
|
167
|
+
candidate || Node.new(name, :node_type => node_type)
|
162
168
|
else
|
163
169
|
Node.new name, :parent => @scope.last, :node_type => node_type
|
164
170
|
end
|
data/lib/code_node/ir/node.rb
CHANGED
@@ -105,14 +105,15 @@ module CodeNode
|
|
105
105
|
# @param path [String] a class or module path in the form <tt>Foo::Bar::Car</tt>
|
106
106
|
# @return [Boolean] does this node inherit from (directly or indirectly) a {#class?} node with the given {#path}? Note that a node inherits from itself according to this method. Recursively checks the ancestry of the node.
|
107
107
|
def inherits_from?(path)
|
108
|
-
|
108
|
+
# TODO: need process all nodes first, marking for deletion on the first pass, because the superclass gets deleting and then the inherits from relation breaks down
|
109
|
+
self.path == path || @inherits_from && @inherits_from.inherits_from?(path)
|
109
110
|
end
|
110
111
|
|
111
112
|
# @return [Boolean] whether or not this node represents a singleton module. A singleton module is one which contains an <tt>extend self</tt> statement.
|
112
113
|
def singleton?
|
113
114
|
@singleton
|
114
115
|
end
|
115
|
-
|
116
|
+
|
116
117
|
# @return [Boolean] whether or not this node is an island. An island is a node with no connections to other nodes.
|
117
118
|
def island?
|
118
119
|
([@parent, @inherits_from].all?(&:nil?) &&
|
@@ -33,16 +33,18 @@ module CodeNode
|
|
33
33
|
walk(c) if c.class == Sexp
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
unless @graph.scope.empty?
|
37
37
|
@graph.scope.last.contains node
|
38
38
|
end
|
39
39
|
elsif find_relations? && s[0] == :call && s.length >= 4 && [:extend, :include].member?(s[2]) && !@graph.scope.empty?
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
s.slice(3..-1).each do |mod_sexp|
|
41
|
+
node = @graph.node_for :module, mod_sexp, :not_sure_if_nested => true
|
42
|
+
unless node.nil?
|
43
|
+
if s[2] == :extend
|
44
|
+
@graph.scope.last.extends node
|
45
|
+
else
|
46
|
+
@graph.scope.last.includes node
|
47
|
+
end
|
46
48
|
end
|
47
49
|
end
|
48
50
|
else
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'cog/spec_helpers'
|
2
|
+
require 'code_node/spec_helpers/runner'
|
3
|
+
require 'code_node/spec_helpers/dot_file'
|
4
|
+
|
5
|
+
module CodeNode
|
6
|
+
|
7
|
+
# RSpec helpers specific to code_node
|
8
|
+
module SpecHelpers
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
module Cog
|
14
|
+
|
15
|
+
# Customizations to cog RSpec helpers for use with code_node
|
16
|
+
module SpecHelpers
|
17
|
+
|
18
|
+
def spec_root
|
19
|
+
File.expand_path File.join(File.dirname(__FILE__), '..', '..', 'spec')
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module CodeNode
|
2
|
+
module SpecHelpers
|
3
|
+
|
4
|
+
# Represents a generated dot file
|
5
|
+
class DotFile
|
6
|
+
|
7
|
+
include Cog::SpecHelpers
|
8
|
+
|
9
|
+
# @param name [String] name of the dotfile without the <tt>.dot</tt> extension. The file will be looked for in the lib subdirectory of the active fixture dir.
|
10
|
+
def initialize(name)
|
11
|
+
@filename = generated_file "#{name}.dot"
|
12
|
+
@nodes = {} # :node_type => []
|
13
|
+
@edges = {} # :edge_type => []
|
14
|
+
if File.exists? @filename
|
15
|
+
@i = 0
|
16
|
+
@lines = File.read(@filename).split "\n"
|
17
|
+
read_until '/* Module nodes */'
|
18
|
+
read_nodes :module
|
19
|
+
read_until '/* Class nodes */'
|
20
|
+
read_nodes :class
|
21
|
+
read_until '/* A contains B */'
|
22
|
+
read_edges :containment
|
23
|
+
read_until '/* A inherits from B */'
|
24
|
+
read_edges :inheritance
|
25
|
+
read_until '/* A includes B */'
|
26
|
+
read_edges :inclusion
|
27
|
+
read_until '/* A extends B */'
|
28
|
+
read_edges :extension
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Boolean] does the file exist?
|
33
|
+
def exists?
|
34
|
+
File.exists? @filename
|
35
|
+
end
|
36
|
+
|
37
|
+
def has_match?(pattern)
|
38
|
+
if exists?
|
39
|
+
!!(pattern =~ File.read(@filename))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_node?(path)
|
44
|
+
has_class?(path) || has_module?(path)
|
45
|
+
end
|
46
|
+
|
47
|
+
def has_class?(path)
|
48
|
+
key = path.to_s.split('::').join '_'
|
49
|
+
@nodes[:class].member?(key)
|
50
|
+
end
|
51
|
+
|
52
|
+
def has_module?(path)
|
53
|
+
key = path.to_s.split('::').join '_'
|
54
|
+
@nodes[:module].member?(key)
|
55
|
+
end
|
56
|
+
|
57
|
+
def has_edge?(path1, path2)
|
58
|
+
has_containment?(path1, path2) || has_inheritance?(path1, path2) || has_inclusion?(path1, path2) || has_extension?(path1, path2)
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_containment?(path1, path2)
|
62
|
+
key1 = path1.to_s.split('::').join '_'
|
63
|
+
key2 = path2.to_s.split('::').join '_'
|
64
|
+
@edges[:containment].member?([key1, key2])
|
65
|
+
end
|
66
|
+
|
67
|
+
def has_inheritance?(path1, path2)
|
68
|
+
key1 = path1.to_s.split('::').join '_'
|
69
|
+
key2 = path2.to_s.split('::').join '_'
|
70
|
+
@edges[:inheritance].member?([key1, key2])
|
71
|
+
end
|
72
|
+
|
73
|
+
def has_inclusion?(path1, path2)
|
74
|
+
key1 = path1.to_s.split('::').join '_'
|
75
|
+
key2 = path2.to_s.split('::').join '_'
|
76
|
+
@edges[:inclusion].member?([key1, key2])
|
77
|
+
end
|
78
|
+
|
79
|
+
def has_extension?(path1, path2)
|
80
|
+
key1 = path1.to_s.split('::').join '_'
|
81
|
+
key2 = path2.to_s.split('::').join '_'
|
82
|
+
@edges[:extension].member?([key1, key2])
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def read_nodes(type)
|
88
|
+
@nodes[type] ||= []
|
89
|
+
until (line = @lines[@i]).strip.empty?
|
90
|
+
/^([A-Za-z0-9_]+)/ =~ line
|
91
|
+
@nodes[type] << $1 unless $1.nil?
|
92
|
+
@i += 1
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def read_edges(type)
|
97
|
+
@edges[type] ||= []
|
98
|
+
until (line = @lines[@i]).strip.empty?
|
99
|
+
/^([A-Za-z0-9_]+)\s\-\>\s([A-Za-z0-9_]+)/ =~ line
|
100
|
+
@edges[type] << [$1, $2] unless $1.nil?
|
101
|
+
@i += 1
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def read_until(line)
|
106
|
+
while @lines[@i] != line && @i < @lines.length
|
107
|
+
@i += 1
|
108
|
+
end
|
109
|
+
@i += 1
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Cog
|
4
|
+
module SpecHelpers
|
5
|
+
|
6
|
+
class Runner
|
7
|
+
def initialize(app)
|
8
|
+
@cog = app
|
9
|
+
@tools = []
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Invocation
|
14
|
+
|
15
|
+
# Redefine exec for testing code_node
|
16
|
+
def exec(&block)
|
17
|
+
ENV['COG_TOOLS'] = File.expand_path File.join(File.dirname(__FILE__), '..', 'cog_tool.rb')
|
18
|
+
Open3.popen3 *@cmd do |i,o,e,t|
|
19
|
+
block.call i,o,e
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/code_node/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: code_node
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kevin Tonon
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-11-
|
18
|
+
date: 2012-11-27 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: cog
|
@@ -111,6 +111,7 @@ extra_rdoc_files: []
|
|
111
111
|
|
112
112
|
files:
|
113
113
|
- LICENSE
|
114
|
+
- cog/generators/overview.rb
|
114
115
|
- cog/templates/code_node/generator.rb.erb
|
115
116
|
- cog/templates/code_node/graph.dot.erb
|
116
117
|
- cog/templates/code_node/node.dot.erb
|
@@ -122,6 +123,9 @@ files:
|
|
122
123
|
- lib/code_node/ir/node_matcher.rb
|
123
124
|
- lib/code_node/ir.rb
|
124
125
|
- lib/code_node/sexp_walker.rb
|
126
|
+
- lib/code_node/spec_helpers/dot_file.rb
|
127
|
+
- lib/code_node/spec_helpers/runner.rb
|
128
|
+
- lib/code_node/spec_helpers.rb
|
125
129
|
- lib/code_node/version.rb
|
126
130
|
- lib/code_node.rb
|
127
131
|
homepage: https://github.com/ktonon/code_node
|