ruby_uml_class 0.3.0 → 0.5.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 +4 -4
- data/README.md +45 -45
- data/bin/start_ruby_uml_class.rb +0 -0
- data/bin/start_ruby_uml_class.rbw +0 -0
- data/lib/config/setting.json +26 -19
- data/lib/config.ru +107 -107
- data/lib/create_uml_class.rb +323 -322
- data/lib/history/history.json +2 -2
- data/lib/js/main.js +463 -463
- data/lib/ruby_uml_class/version.rb +5 -5
- data/lib/start.rb +0 -0
- data/ruby_uml_class.gemspec +3 -2
- metadata +30 -16
data/lib/create_uml_class.rb
CHANGED
@@ -1,322 +1,323 @@
|
|
1
|
-
require "tempfile"
|
2
|
-
require "facter"
|
3
|
-
|
4
|
-
CStruct = Struct.new(:type,
|
5
|
-
:name,
|
6
|
-
:block_count,
|
7
|
-
:var_list,
|
8
|
-
:method_list,
|
9
|
-
:inherit_list,
|
10
|
-
:composition_list)
|
11
|
-
|
12
|
-
def get_rufo_path
|
13
|
-
ENV["PATH"].split(";").each do |path|
|
14
|
-
rufo_path = "#{path}\\rufo"
|
15
|
-
if File.exists? rufo_path
|
16
|
-
return rufo_path
|
17
|
-
end
|
18
|
-
end
|
19
|
-
return ""
|
20
|
-
end
|
21
|
-
|
22
|
-
def print_uml(out, out_list)
|
23
|
-
out_list.each do |o_list|
|
24
|
-
if o_list.type == :class_start
|
25
|
-
# nop
|
26
|
-
elsif o_list.type == :module_start
|
27
|
-
out.push "namespace #{o_list.name} {"
|
28
|
-
elsif o_list.type == :class_end
|
29
|
-
pp o_list if o_list.name == ""
|
30
|
-
out.push "class #{o_list.name} {"
|
31
|
-
# インスタンス変数の出力
|
32
|
-
o_list.var_list.uniq.each do |iv|
|
33
|
-
out.push iv
|
34
|
-
end
|
35
|
-
# メソッドの出力
|
36
|
-
o_list.method_list.each do |ml|
|
37
|
-
out.push ml
|
38
|
-
end
|
39
|
-
out.push "}"
|
40
|
-
# 継承リストの出力
|
41
|
-
o_list.inherit_list.each do |ih|
|
42
|
-
out.push "#{o_list.name} --|> #{ih}"
|
43
|
-
end
|
44
|
-
# compo
|
45
|
-
o_list.composition_list.uniq.each do |co|
|
46
|
-
out.push "#{o_list.name} *-- #{co}"
|
47
|
-
end
|
48
|
-
elsif o_list.type == :module_end
|
49
|
-
# インスタンス変数がある場合はモジュール名と同じクラスを定義
|
50
|
-
if o_list.var_list.size != 0 or
|
51
|
-
o_list.method_list.size != 0 or
|
52
|
-
o_list.inherit_list.size != 0 or
|
53
|
-
o_list.composition_list.size != 0
|
54
|
-
pp o_list if o_list.name == ""
|
55
|
-
out.push "class #{o_list.name} {"
|
56
|
-
# インスタンス変数の出力
|
57
|
-
o_list.var_list.uniq.each do |iv|
|
58
|
-
out.push iv
|
59
|
-
end
|
60
|
-
# メソッドの出力
|
61
|
-
o_list.method_list.each do |ml|
|
62
|
-
out.push ml
|
63
|
-
end
|
64
|
-
out.push "}"
|
65
|
-
# 継承リストの出力
|
66
|
-
o_list.inherit_list.each do |ih|
|
67
|
-
out.push "#{o_list.name} --|> #{ih}"
|
68
|
-
end
|
69
|
-
# compo
|
70
|
-
o_list.composition_list.uniq.each do |co|
|
71
|
-
out.push "#{o_list.name} *-- #{co}"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
out.push "}"
|
75
|
-
else
|
76
|
-
# error
|
77
|
-
puts "error!"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
return out
|
81
|
-
end
|
82
|
-
|
83
|
-
def delete_here_doc(buf)
|
84
|
-
new_buf = []
|
85
|
-
here_doc = false
|
86
|
-
here_word = ""
|
87
|
-
buf.each_line do |line|
|
88
|
-
if line =~ /(<<|<<~|<<-)[A-Z]+/
|
89
|
-
here_doc = true
|
90
|
-
here_word = line.match(/(<<|<<~|<<-)[A-Z]+/).to_s.gsub(/[<~-]/, "")
|
91
|
-
end
|
92
|
-
if here_word != "" and line =~ Regexp.new("^\s*#{here_word}$")
|
93
|
-
here_word = ""
|
94
|
-
here_doc = false
|
95
|
-
pp line
|
96
|
-
end
|
97
|
-
if here_doc == false
|
98
|
-
new_buf.push line
|
99
|
-
else
|
100
|
-
pp line
|
101
|
-
end
|
102
|
-
end
|
103
|
-
return new_buf.join("")
|
104
|
-
end
|
105
|
-
|
106
|
-
def create_uml_class(in_dir, out_file)
|
107
|
-
out = []
|
108
|
-
out.push "@startuml"
|
109
|
-
|
110
|
-
puts "in_dir = #{in_dir}"
|
111
|
-
main_composition_list = []
|
112
|
-
main_method_list = []
|
113
|
-
global_var = []
|
114
|
-
|
115
|
-
Dir.glob("#{in_dir}/**/*.{rb,ru}") do |f|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
#puts "
|
150
|
-
#
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
if
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
method_type = :
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
when :
|
239
|
-
method_list.push "
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
cstruct_list
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
1
|
+
require "tempfile"
|
2
|
+
require "facter"
|
3
|
+
|
4
|
+
CStruct = Struct.new(:type,
|
5
|
+
:name,
|
6
|
+
:block_count,
|
7
|
+
:var_list,
|
8
|
+
:method_list,
|
9
|
+
:inherit_list,
|
10
|
+
:composition_list)
|
11
|
+
|
12
|
+
def get_rufo_path
|
13
|
+
ENV["PATH"].split(";").each do |path|
|
14
|
+
rufo_path = "#{path}\\rufo"
|
15
|
+
if File.exists? rufo_path
|
16
|
+
return rufo_path
|
17
|
+
end
|
18
|
+
end
|
19
|
+
return ""
|
20
|
+
end
|
21
|
+
|
22
|
+
def print_uml(out, out_list)
|
23
|
+
out_list.each do |o_list|
|
24
|
+
if o_list.type == :class_start
|
25
|
+
# nop
|
26
|
+
elsif o_list.type == :module_start
|
27
|
+
out.push "namespace #{o_list.name} {"
|
28
|
+
elsif o_list.type == :class_end
|
29
|
+
pp o_list if o_list.name == ""
|
30
|
+
out.push "class #{o_list.name} {"
|
31
|
+
# インスタンス変数の出力
|
32
|
+
o_list.var_list.uniq.each do |iv|
|
33
|
+
out.push iv
|
34
|
+
end
|
35
|
+
# メソッドの出力
|
36
|
+
o_list.method_list.each do |ml|
|
37
|
+
out.push ml
|
38
|
+
end
|
39
|
+
out.push "}"
|
40
|
+
# 継承リストの出力
|
41
|
+
o_list.inherit_list.each do |ih|
|
42
|
+
out.push "#{o_list.name} --|> #{ih}"
|
43
|
+
end
|
44
|
+
# compo
|
45
|
+
o_list.composition_list.uniq.each do |co|
|
46
|
+
out.push "#{o_list.name} *-- #{co}"
|
47
|
+
end
|
48
|
+
elsif o_list.type == :module_end
|
49
|
+
# インスタンス変数がある場合はモジュール名と同じクラスを定義
|
50
|
+
if o_list.var_list.size != 0 or
|
51
|
+
o_list.method_list.size != 0 or
|
52
|
+
o_list.inherit_list.size != 0 or
|
53
|
+
o_list.composition_list.size != 0
|
54
|
+
pp o_list if o_list.name == ""
|
55
|
+
out.push "class #{o_list.name} {"
|
56
|
+
# インスタンス変数の出力
|
57
|
+
o_list.var_list.uniq.each do |iv|
|
58
|
+
out.push iv
|
59
|
+
end
|
60
|
+
# メソッドの出力
|
61
|
+
o_list.method_list.each do |ml|
|
62
|
+
out.push ml
|
63
|
+
end
|
64
|
+
out.push "}"
|
65
|
+
# 継承リストの出力
|
66
|
+
o_list.inherit_list.each do |ih|
|
67
|
+
out.push "#{o_list.name} --|> #{ih}"
|
68
|
+
end
|
69
|
+
# compo
|
70
|
+
o_list.composition_list.uniq.each do |co|
|
71
|
+
out.push "#{o_list.name} *-- #{co}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
out.push "}"
|
75
|
+
else
|
76
|
+
# error
|
77
|
+
puts "error!"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
return out
|
81
|
+
end
|
82
|
+
|
83
|
+
def delete_here_doc(buf)
|
84
|
+
new_buf = []
|
85
|
+
here_doc = false
|
86
|
+
here_word = ""
|
87
|
+
buf.each_line do |line|
|
88
|
+
if line =~ /(<<|<<~|<<-)[A-Z]+/
|
89
|
+
here_doc = true
|
90
|
+
here_word = line.match(/(<<|<<~|<<-)[A-Z]+/).to_s.gsub(/[<~-]/, "")
|
91
|
+
end
|
92
|
+
if here_word != "" and line =~ Regexp.new("^\s*#{here_word}$")
|
93
|
+
here_word = ""
|
94
|
+
here_doc = false
|
95
|
+
#pp line
|
96
|
+
end
|
97
|
+
if here_doc == false
|
98
|
+
new_buf.push line
|
99
|
+
else
|
100
|
+
#pp line
|
101
|
+
end
|
102
|
+
end
|
103
|
+
return new_buf.join("")
|
104
|
+
end
|
105
|
+
|
106
|
+
def create_uml_class(in_dir, out_file)
|
107
|
+
out = []
|
108
|
+
out.push "@startuml"
|
109
|
+
|
110
|
+
puts "in_dir = #{in_dir}"
|
111
|
+
main_composition_list = []
|
112
|
+
main_method_list = []
|
113
|
+
global_var = []
|
114
|
+
|
115
|
+
Dir.glob("#{in_dir}/**/*.{rb,ru}") do |f|
|
116
|
+
if f =~ Regexp.new(@config["exclude_path"])
|
117
|
+
puts "skip #{f}"
|
118
|
+
next
|
119
|
+
end
|
120
|
+
puts f
|
121
|
+
buf = ""
|
122
|
+
Tempfile.create("rufo") do |tmp_file|
|
123
|
+
FileUtils.cp(f, tmp_file.path)
|
124
|
+
kernel = Facter.value(:kernel)
|
125
|
+
if kernel == "windows"
|
126
|
+
open("|rubyw #{get_rufo_path} #{tmp_file.path}") do |f|
|
127
|
+
if f.read =~ /error/
|
128
|
+
puts "rufo error #{f}"
|
129
|
+
return
|
130
|
+
else
|
131
|
+
buf = File.binread tmp_file.path
|
132
|
+
end
|
133
|
+
end
|
134
|
+
else
|
135
|
+
open("|rufo #{tmp_file.path}") do |f|
|
136
|
+
if f.read =~ /error/
|
137
|
+
puts "rufo error #{f}"
|
138
|
+
return
|
139
|
+
else
|
140
|
+
buf = File.binread tmp_file.path
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# コメント削除
|
147
|
+
buf.gsub!(/(([\/\"\'].*?[\/\"\'])|([^\/\"\'\)\s]*#.+?$))/) do |m|
|
148
|
+
if m[0] == "#" and m[0] != "{"
|
149
|
+
#puts "comment #{m}"
|
150
|
+
# コメント
|
151
|
+
""
|
152
|
+
else
|
153
|
+
#puts "not comment #{m}"
|
154
|
+
# コメント以外
|
155
|
+
m
|
156
|
+
end
|
157
|
+
end
|
158
|
+
# ヒアドキュメント削除
|
159
|
+
buf = delete_here_doc(buf)
|
160
|
+
|
161
|
+
out_list = []
|
162
|
+
cstruct_list = []
|
163
|
+
block_count = 0
|
164
|
+
method_type = :public
|
165
|
+
class_name = ""
|
166
|
+
# ソースを解析
|
167
|
+
buf.each_line do |line|
|
168
|
+
next if line =~ /^[\r\n]*$/ # 空行は対象外
|
169
|
+
|
170
|
+
# ブロックの開始/終了
|
171
|
+
indent_num = line.match(/^[ ]+/).to_s.size / 2
|
172
|
+
if block_count == indent_num
|
173
|
+
# 変化なし
|
174
|
+
elsif block_count > indent_num
|
175
|
+
# ブロックの終了
|
176
|
+
block_count = indent_num
|
177
|
+
else
|
178
|
+
# ブロックの開始
|
179
|
+
block_count = indent_num
|
180
|
+
end
|
181
|
+
|
182
|
+
#line.gsub!(/\".+\"/, "\"delete_string\"") # 文字列を削除
|
183
|
+
if line =~ /^\s*class\s/
|
184
|
+
unless line =~ /<</ # 特異クラスではない
|
185
|
+
work = line.gsub(/class\s/, "")
|
186
|
+
class_name = work.split("<")[0].to_s.chomp.match(/[A-Z][A-Za-z0-9_:]+/).to_s
|
187
|
+
base_name = work.split("<")[1].to_s.chomp.match(/[A-Z][A-Za-z0-9_:]+/).to_s
|
188
|
+
class_name.gsub!(/::/, ".")
|
189
|
+
class_name.gsub!(/;/, "")
|
190
|
+
if out_list.size != 0 and out_list[-1].type == :class_start # classが連続している
|
191
|
+
class_name = out_list[-1].name + "." + class_name
|
192
|
+
out_list[-1].name = class_name
|
193
|
+
cstruct_list[-1].name = class_name
|
194
|
+
else
|
195
|
+
out_list.push CStruct.new(:class_start, class_name, block_count, [], [], [], [])
|
196
|
+
cstruct_list.push CStruct.new(:class_end, class_name, block_count, [], [], [], [])
|
197
|
+
end
|
198
|
+
#pp line if class_name == ""
|
199
|
+
if base_name != ""
|
200
|
+
#base_name.gsub!(/::/, ".")
|
201
|
+
cstruct_list[-1].inherit_list.push base_name
|
202
|
+
end
|
203
|
+
end
|
204
|
+
next unless line =~ /end\s*$/ # 1行で終了しない場合
|
205
|
+
elsif line =~ /^\s*module\s/
|
206
|
+
module_name = line.split(" ")[1].to_s.chomp
|
207
|
+
module_name.gsub!(/^[:]+/, "")
|
208
|
+
module_name.gsub!(/::/, ".")
|
209
|
+
module_name.gsub!(/;/, "")
|
210
|
+
out_list.push CStruct.new(:module_start, module_name, block_count, [], [], [], [])
|
211
|
+
cstruct_list.push CStruct.new(:module_end, module_name, block_count, [], [], [], [])
|
212
|
+
next unless line =~ /end\s*$/ # 1行で終了しない場合
|
213
|
+
end
|
214
|
+
|
215
|
+
if line =~ /^\s*private$/
|
216
|
+
method_type = :private
|
217
|
+
elsif line =~ /^\s*protected$/
|
218
|
+
method_type = :protected
|
219
|
+
elsif line =~ /^\s*public$/
|
220
|
+
method_type = :public
|
221
|
+
end
|
222
|
+
|
223
|
+
if line =~ /^\s*def\s/
|
224
|
+
# 関数名を取り出す
|
225
|
+
method = line.chomp.gsub(/\s*def\s*/, "")
|
226
|
+
unless method =~ /\(/
|
227
|
+
# 関数名にカッコをつける
|
228
|
+
sp = method.split(" ")
|
229
|
+
if sp.size > 1
|
230
|
+
method = sp[0].to_s + "(" + sp[1..-1].to_s + ")"
|
231
|
+
else
|
232
|
+
method = method + "()"
|
233
|
+
end
|
234
|
+
end
|
235
|
+
if cstruct_list.size != 0
|
236
|
+
method_list = cstruct_list[-1].method_list
|
237
|
+
case method_type
|
238
|
+
when :public
|
239
|
+
method_list.push "+ #{method}"
|
240
|
+
when :private
|
241
|
+
method_list.push "- #{method}"
|
242
|
+
when :protected
|
243
|
+
method_list.push "# #{method}"
|
244
|
+
end
|
245
|
+
else
|
246
|
+
main_method_list.push "+ #{method}"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# composition_list
|
251
|
+
line.match(/[A-Z]([a-zA-Z:]+)\.[a-z]/) do |m|
|
252
|
+
#pp m
|
253
|
+
c_name = m.to_s.split(".")[0]
|
254
|
+
if cstruct_list.size != 0
|
255
|
+
cstruct_list[-1].composition_list.push c_name
|
256
|
+
else
|
257
|
+
main_composition_list.push "main *-- #{c_name}"
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
# インスタンス変数
|
262
|
+
if line =~ /\s*@\S+/
|
263
|
+
if cstruct_list.size != 0
|
264
|
+
line.match(/@[a-zA-Z0-9_]+/) { |m|
|
265
|
+
instance_var = cstruct_list[-1].var_list
|
266
|
+
val = m.to_s.gsub(/@/, "")
|
267
|
+
case method_type
|
268
|
+
when :public
|
269
|
+
instance_var.push "+ #{val}"
|
270
|
+
when :private
|
271
|
+
instance_var.push "- #{val}"
|
272
|
+
when :protected
|
273
|
+
instance_var.push "# #{val}"
|
274
|
+
end
|
275
|
+
}
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# 外部変数
|
280
|
+
line.match(/\$[a-zA-Z0-9_]+/) { |m|
|
281
|
+
global_var.push "+ #{m.to_s}"
|
282
|
+
}
|
283
|
+
|
284
|
+
# クラスの終了
|
285
|
+
if cstruct_list.size != 0
|
286
|
+
if block_count == cstruct_list[-1].block_count # block_countが一致
|
287
|
+
#puts "end of #{cstruct_list[-1].name}"
|
288
|
+
out_list.push cstruct_list[-1]
|
289
|
+
cstruct_list.slice!(-1) # 最後の要素を削除
|
290
|
+
end
|
291
|
+
end
|
292
|
+
#puts "#{block_count} #{line.chomp}"
|
293
|
+
end
|
294
|
+
if block_count != 0
|
295
|
+
# エラー
|
296
|
+
puts f
|
297
|
+
return ""
|
298
|
+
end
|
299
|
+
|
300
|
+
# UMLの出力
|
301
|
+
out = print_uml(out, out_list)
|
302
|
+
end
|
303
|
+
|
304
|
+
if main_method_list.size != 0 or
|
305
|
+
main_composition_list.size != 0 or
|
306
|
+
main_method_list.size != 0
|
307
|
+
out.push "class main {"
|
308
|
+
main_method_list.each do |mml|
|
309
|
+
out.push mml
|
310
|
+
end
|
311
|
+
# グローバル変数の出力
|
312
|
+
global_var.uniq.each do |gv|
|
313
|
+
out.push gv
|
314
|
+
end
|
315
|
+
out.push "}"
|
316
|
+
main_composition_list.uniq.each do |mcl|
|
317
|
+
out.push mcl
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
out.push "@enduml"
|
322
|
+
return out.join("\n")
|
323
|
+
end
|
data/lib/history/history.json
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
[
|
2
|
-
|
1
|
+
[
|
2
|
+
|
3
3
|
]
|