umlify 1.2.1 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/umlify +1 -1
- data/lib/umlify.rb +11 -1
- data/lib/umlify/parser_sexp.rb +10 -2
- data/lib/umlify/runner.rb +6 -4
- data/lib/umlify/version.rb +1 -1
- data/test/parser_sexp_test.rb +17 -2
- data/test/runner_test.rb +8 -0
- metadata +2 -5
- data/lib/umlify/parser.rb +0 -86
- data/test/parser_test.rb +0 -126
data/bin/umlify
CHANGED
data/lib/umlify.rb
CHANGED
@@ -34,8 +34,18 @@
|
|
34
34
|
|
35
35
|
require 'umlify/version'
|
36
36
|
require 'umlify/runner'
|
37
|
-
require 'umlify/parser'
|
38
37
|
require 'umlify/parser_sexp'
|
39
38
|
require 'umlify/extension'
|
40
39
|
require 'umlify/uml_class'
|
41
40
|
require 'umlify/diagram'
|
41
|
+
|
42
|
+
module Umlify
|
43
|
+
class << self
|
44
|
+
|
45
|
+
# Executes umlify with the given set of options
|
46
|
+
def execute args
|
47
|
+
Umlify::Runner.new(args).run
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
data/lib/umlify/parser_sexp.rb
CHANGED
@@ -51,7 +51,14 @@ module Umlify
|
|
51
51
|
|
52
52
|
# Creates a UmlClass from a class s-expression
|
53
53
|
def parse_class class_s_exp
|
54
|
-
|
54
|
+
|
55
|
+
# Checks if the class is in a module
|
56
|
+
if class_s_exp[1].class == Symbol
|
57
|
+
uml_class = UmlClass.new class_s_exp[1].to_s
|
58
|
+
else
|
59
|
+
classname = class_s_exp[1][1][1].to_s+'::'+class_s_exp[1][2].to_s
|
60
|
+
uml_class = UmlClass.new classname
|
61
|
+
end
|
55
62
|
|
56
63
|
# Let's start by building the associations of the class
|
57
64
|
each_association_for class_s_exp do |variable, type, cardinality|
|
@@ -65,7 +72,8 @@ module Umlify
|
|
65
72
|
uml_class.parent = class_s_exp[2][1].to_s
|
66
73
|
elsif class_s_exp[2] and class_s_exp[2][0] == :colon2
|
67
74
|
# If the parent class belongs to a module
|
68
|
-
|
75
|
+
classname = class_s_exp[2][1][1].to_s+'::'+class_s_exp[2][2].to_s
|
76
|
+
uml_class.parent = classname
|
69
77
|
end
|
70
78
|
|
71
79
|
# Looks-up for instance methods
|
data/lib/umlify/runner.rb
CHANGED
@@ -7,12 +7,13 @@ module Umlify
|
|
7
7
|
# and generates and save a uml diagram using yUML API.
|
8
8
|
class Runner
|
9
9
|
|
10
|
-
attr_reader :smart_mode
|
10
|
+
attr_reader :smart_mode, :html_mode
|
11
11
|
|
12
12
|
# Takes as input an array with file names
|
13
13
|
def initialize args
|
14
14
|
@args = args
|
15
15
|
@smart_mode = false
|
16
|
+
@html_mode = false
|
16
17
|
end
|
17
18
|
|
18
19
|
# Runs the application
|
@@ -24,9 +25,9 @@ module Umlify
|
|
24
25
|
else
|
25
26
|
puts "umlifying"
|
26
27
|
|
27
|
-
@
|
28
|
+
@parser_sexp = ParserSexp.new @args
|
28
29
|
|
29
|
-
if classes = @
|
30
|
+
if classes = @parser_sexp.parse_sources!
|
30
31
|
@diagram = Diagram.new
|
31
32
|
|
32
33
|
if @smart_mode
|
@@ -42,7 +43,7 @@ module Umlify
|
|
42
43
|
image = download_image
|
43
44
|
save_to_file image
|
44
45
|
|
45
|
-
puts 'http://yuml.me'+@diagram.get_uri
|
46
|
+
puts 'http://yuml.me'+@diagram.get_uri if @debug_mode
|
46
47
|
puts "Saved in uml.png"
|
47
48
|
else
|
48
49
|
puts "No ruby files in the directory"
|
@@ -54,6 +55,7 @@ module Umlify
|
|
54
55
|
def parse_options
|
55
56
|
OptionParser.new do |opts|
|
56
57
|
opts.on("-s", "--smart") { @smart_mode = true }
|
58
|
+
opts.on("-h", "--html") { @html_mode = true }
|
57
59
|
end.parse! @args
|
58
60
|
end
|
59
61
|
|
data/lib/umlify/version.rb
CHANGED
data/test/parser_sexp_test.rb
CHANGED
@@ -128,9 +128,25 @@ class ParserSexpTest < Test::Unit::TestCase
|
|
128
128
|
END_FILE
|
129
129
|
bar = @p.parse_file(test)[0]
|
130
130
|
assert_instance_of Umlify::UmlClass, bar
|
131
|
-
assert_equal "Hash", bar.parent
|
131
|
+
assert_equal "SomeModule::Hash", bar.parent
|
132
132
|
end
|
133
133
|
|
134
|
+
should "parse classes from a module" do
|
135
|
+
test = <<-END_FILE
|
136
|
+
class SomeModule::Bar < Hash
|
137
|
+
|
138
|
+
def initialize
|
139
|
+
end
|
140
|
+
|
141
|
+
def save
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
END_FILE
|
146
|
+
bar = @p.parse_file(test)[0]
|
147
|
+
assert_instance_of Umlify::UmlClass, bar
|
148
|
+
assert_equal "SomeModule::Bar", bar.name
|
149
|
+
end
|
134
150
|
|
135
151
|
should "parse file with multiple classes" do
|
136
152
|
test = <<-END_FILE
|
@@ -148,7 +164,6 @@ class ParserSexpTest < Test::Unit::TestCase
|
|
148
164
|
should "return an array of UmlClasses when the parsing is done" do
|
149
165
|
p = Umlify::ParserSexp.new Dir[File.dirname(__FILE__)+'/fixtures/*']
|
150
166
|
parsed_classes = p.parse_sources!
|
151
|
-
puts "here : #{parsed_classes}"
|
152
167
|
assert_equal 3, parsed_classes.count
|
153
168
|
end
|
154
169
|
|
data/test/runner_test.rb
CHANGED
@@ -14,6 +14,14 @@ class RunnerTest < Test::Unit::TestCase
|
|
14
14
|
assert r.smart_mode
|
15
15
|
end
|
16
16
|
|
17
|
+
should "print the api url when passed -h or --html option" do
|
18
|
+
r = Umlify::Runner.new(["-h"])
|
19
|
+
r.run
|
20
|
+
assert r.html_mode
|
21
|
+
r = Umlify::Runner.new(["--html"])
|
22
|
+
r.run
|
23
|
+
assert r.html_mode
|
24
|
+
end
|
17
25
|
end
|
18
26
|
end
|
19
27
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: umlify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.2.
|
5
|
+
version: 1.2.4
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Michael Sokol
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-03-
|
13
|
+
date: 2011-03-14 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -61,12 +61,10 @@ files:
|
|
61
61
|
- lib/umlify.rb
|
62
62
|
- lib/umlify/version.rb
|
63
63
|
- lib/umlify/runner.rb
|
64
|
-
- lib/umlify/parser.rb
|
65
64
|
- lib/umlify/parser_sexp.rb
|
66
65
|
- lib/umlify/extension.rb
|
67
66
|
- lib/umlify/uml_class.rb
|
68
67
|
- lib/umlify/diagram.rb
|
69
|
-
- test/parser_test.rb
|
70
68
|
- test/diagram_test.rb
|
71
69
|
- test/uml_class_test.rb
|
72
70
|
- test/runner_test.rb
|
@@ -101,7 +99,6 @@ signing_key:
|
|
101
99
|
specification_version: 3
|
102
100
|
summary: umlify is a tool that creates class diagrams from your code.
|
103
101
|
test_files:
|
104
|
-
- test/parser_test.rb
|
105
102
|
- test/uml_class_test.rb
|
106
103
|
- test/parser_sexp_test.rb
|
107
104
|
- test/diagram_test.rb
|
data/lib/umlify/parser.rb
DELETED
@@ -1,86 +0,0 @@
|
|
1
|
-
module Umlify
|
2
|
-
|
3
|
-
# First version of the ruby parser, using regular expression.
|
4
|
-
# Parser is responsible for parsing ruby source files and building an array
|
5
|
-
# of uml classes
|
6
|
-
class Parser
|
7
|
-
|
8
|
-
# An array containing all the parsed classes
|
9
|
-
# type: UmlClass
|
10
|
-
attr_accessor :classes
|
11
|
-
|
12
|
-
# files should be an array containing file names with the correct path
|
13
|
-
def initialize files
|
14
|
-
@files = files
|
15
|
-
@classes = []
|
16
|
-
end
|
17
|
-
|
18
|
-
# Parses the source code of the files in @files
|
19
|
-
# to build uml classes. Returns an array containing all the
|
20
|
-
# parsed classes or nil if no ruby file were found in the
|
21
|
-
# @files array.
|
22
|
-
def parse_sources!
|
23
|
-
|
24
|
-
@source_files = @files.select {|f| f.match /\.rb/}
|
25
|
-
return nil if @source_files.empty?
|
26
|
-
|
27
|
-
@source_files.each do |file|
|
28
|
-
puts "processing #{file}..."
|
29
|
-
f = File.open file, 'r'
|
30
|
-
(parse_file f).each {|c| @classes << c}
|
31
|
-
f.close
|
32
|
-
end
|
33
|
-
|
34
|
-
@classes
|
35
|
-
end
|
36
|
-
|
37
|
-
# Parse the given file or string, and return the parsed classes
|
38
|
-
def parse_file file
|
39
|
-
classes_in_file = []
|
40
|
-
current_class = nil
|
41
|
-
type_annotation = nil
|
42
|
-
|
43
|
-
file.each do |line|
|
44
|
-
|
45
|
-
# This parses the classes
|
46
|
-
line.match(/^\s*class ([\w]*)\b[\s]*$/) do |m|
|
47
|
-
current_class = UmlClass.new m[1]
|
48
|
-
classes_in_file << current_class
|
49
|
-
end
|
50
|
-
|
51
|
-
# This parses the classes and its parent (class Foo < Bar)
|
52
|
-
line.match(/^\s*class ([\w]*) < ([\w]*)\b/) do |m|
|
53
|
-
current_class = UmlClass.new m[1]
|
54
|
-
current_class.parent = m[2]
|
55
|
-
classes_in_file << current_class
|
56
|
-
end
|
57
|
-
|
58
|
-
if current_class
|
59
|
-
|
60
|
-
# This parses the @variables
|
61
|
-
line.match(/@([\w]*)\b/) do |m|
|
62
|
-
current_class.variables << m[1] unless current_class.variables.include? m[1]
|
63
|
-
end
|
64
|
-
|
65
|
-
# This parses the methods
|
66
|
-
line.match(/def ([\w]*)\b/) do |m|
|
67
|
-
current_class.methods << m[1] unless current_class.methods.include? m[1]
|
68
|
-
end
|
69
|
-
|
70
|
-
# This raises the type_annotation flag
|
71
|
-
line.match(/# type: ([\w]*)\b/) {|m| type_annotation = m[1]}
|
72
|
-
|
73
|
-
# This adds an association to the current class, using the type_annotation
|
74
|
-
# if type_annotation has been set
|
75
|
-
line.match(/(attr_accessor|attr_reader|attr_writer) :([\w]*)\b/) do |m|
|
76
|
-
current_class.associations[m[2]] = type_annotation
|
77
|
-
type_annotation = nil
|
78
|
-
end if type_annotation
|
79
|
-
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
classes_in_file
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
data/test/parser_test.rb
DELETED
@@ -1,126 +0,0 @@
|
|
1
|
-
require 'shoulda'
|
2
|
-
require 'umlify'
|
3
|
-
|
4
|
-
class ParserTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
context "Parser" do
|
7
|
-
|
8
|
-
setup do
|
9
|
-
fixture = ["somefile.rb", "someotherfile.rb"]
|
10
|
-
@p = Umlify::Parser.new fixture
|
11
|
-
end
|
12
|
-
|
13
|
-
should "respond to parse_sources!" do
|
14
|
-
assert_respond_to @p, :parse_sources!
|
15
|
-
end
|
16
|
-
|
17
|
-
should "return nil if no source file in the given directory" do
|
18
|
-
parser = Umlify::Parser.new ["not_source", "still_not_source"]
|
19
|
-
assert_equal nil, parser.parse_sources!
|
20
|
-
end
|
21
|
-
|
22
|
-
should "parse class names" do
|
23
|
-
test = <<-END_FILE
|
24
|
-
class AClassName
|
25
|
-
end
|
26
|
-
END_FILE
|
27
|
-
assert_equal 'AClassName', @p.parse_file(test)[0].name
|
28
|
-
end
|
29
|
-
|
30
|
-
should "parse class name of inherited classes" do
|
31
|
-
test = <<-END_FILE
|
32
|
-
class AClassName < SuperClass
|
33
|
-
end
|
34
|
-
END_FILE
|
35
|
-
assert_equal 'AClassName', @p.parse_file(test)[0].name
|
36
|
-
end
|
37
|
-
|
38
|
-
should "parse @variables in classes" do
|
39
|
-
test = <<-END_FILE
|
40
|
-
class Bar
|
41
|
-
def foo
|
42
|
-
@a_variable = "foo"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
END_FILE
|
46
|
-
bar = @p.parse_file(test)[0]
|
47
|
-
assert_instance_of Umlify::UmlClass, bar
|
48
|
-
assert bar.variables.include? "a_variable"
|
49
|
-
end
|
50
|
-
|
51
|
-
should "parse attr_accessor when preceeded by a # type: Type annotation" do
|
52
|
-
test = <<-END_FILE
|
53
|
-
class Bar
|
54
|
-
|
55
|
-
# type: FooBar
|
56
|
-
attr_accessor :unicorn
|
57
|
-
|
58
|
-
def foo
|
59
|
-
end
|
60
|
-
end
|
61
|
-
END_FILE
|
62
|
-
bar = @p.parse_file(test)[0]
|
63
|
-
assert_instance_of Umlify::UmlClass, bar
|
64
|
-
assert_equal "FooBar", bar.associations['unicorn']
|
65
|
-
end
|
66
|
-
|
67
|
-
should "parse attr_reader when preceeded by a # type: Type annotation" do
|
68
|
-
test = <<-END_FILE
|
69
|
-
class Bar
|
70
|
-
|
71
|
-
# type: FooBar
|
72
|
-
attr_reader :unicorn
|
73
|
-
|
74
|
-
def foo
|
75
|
-
end
|
76
|
-
end
|
77
|
-
END_FILE
|
78
|
-
bar = @p.parse_file(test)[0]
|
79
|
-
assert_instance_of Umlify::UmlClass, bar
|
80
|
-
assert_equal "FooBar", bar.associations['unicorn']
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
should "parse attr_writer when preceeded by a # type: Type annotation" do
|
85
|
-
test = <<-END_FILE
|
86
|
-
class Bar
|
87
|
-
|
88
|
-
# type: FooBar
|
89
|
-
attr_writer :unicorn
|
90
|
-
|
91
|
-
def foo
|
92
|
-
end
|
93
|
-
end
|
94
|
-
END_FILE
|
95
|
-
bar = @p.parse_file(test)[0]
|
96
|
-
assert_instance_of Umlify::UmlClass, bar
|
97
|
-
assert_equal "FooBar", bar.associations['unicorn']
|
98
|
-
end
|
99
|
-
|
100
|
-
should "parse inherited classes" do
|
101
|
-
test = <<-END_FILE
|
102
|
-
class Bar < Hash
|
103
|
-
|
104
|
-
def initialize
|
105
|
-
end
|
106
|
-
|
107
|
-
def save
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
end
|
112
|
-
END_FILE
|
113
|
-
bar = @p.parse_file(test)[0]
|
114
|
-
assert_instance_of Umlify::UmlClass, bar
|
115
|
-
assert_equal "Hash", bar.parent
|
116
|
-
end
|
117
|
-
|
118
|
-
should "return an array of UmlClasses when the parsing is done" do
|
119
|
-
p = Umlify::Parser.new Dir[File.dirname(__FILE__)+'/fixtures/*']
|
120
|
-
parsed_classes = p.parse_sources!
|
121
|
-
puts "here : #{parsed_classes}"
|
122
|
-
assert_equal 3, parsed_classes.count
|
123
|
-
end
|
124
|
-
|
125
|
-
end
|
126
|
-
end
|