CppUmlClass 0.8.0 → 1.0.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 +86 -42
- data/exe/create_cpp_uml_class.rb +4 -2
- data/img/CppUMLClass.mp4 +0 -0
- data/img/class_color.png +0 -0
- data/img/setting.png +0 -0
- data/lib/CppUmlClass/version.rb +1 -1
- data/lib/config/setting.json +12 -2
- data/lib/config.ru +1 -1
- data/lib/cpp_uml_class.rb +6 -3
- data/lib/create_uml_class.rb +34 -73
- data/lib/css/index.css +297 -125
- data/lib/html/index.html +54 -57
- data/lib/ifdef_process.rb +160 -0
- data/lib/js/main.js +51 -12
- data/lib/wsserver.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e2cce57ea7d1f32941bb2bb012fe8a3c7786b1fa943aefb84a6060bf61aa934
|
4
|
+
data.tar.gz: 2df23ba7d848da1c4b57c1d1d2f44feacd648880934def6abba4cc25014bca77
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f446514ce61a3722ff9db2311e088c547506099fef34e3a85283892d0c301924511f0db6be00f36a0f71bf02c75eaa15bac4eb7b8e386ea9147c05bbd3d80473
|
7
|
+
data.tar.gz: 8f4fcf4f7784e87b1bd67e5c1d416033bbd97b0811ef535e1f0723574b30a9531595c759930fd5fd2509dbb6c40f5e4241bff0c472dc9012b102020093605b29
|
data/README.md
CHANGED
@@ -1,74 +1,115 @@
|
|
1
1
|
# CppUmlClass
|
2
2
|
|
3
|
-
CppUmlClass
|
4
|
-
PlantUML and rufo commands
|
5
|
-
The created class diagram is displayed on the browser screen.
|
3
|
+
CppUmlClass generates C++ class diagrams from your source code.
|
4
|
+
It uses PlantUML and rufo commands to create the diagrams, which are displayed in your browser.
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
---
|
7
|
+
|
8
|
+
## Version 1.0.0 Highlights
|
9
|
+
|
10
|
+
- **Full support for ifdef/ifndef/if/else/elif/endif preprocessor directives**
|
11
|
+
- New: `lib/ifdef_process.rb` allows flexible interpretation of C/C++ preprocessors, reflected in UML analysis.
|
12
|
+
- **Flexible define management with `define_hash`**
|
13
|
+
- You can control defines and their values for analysis via the `define_hash` in the settings file (`setting.json`). This can be edited from the GUI as well.
|
14
|
+
- **Enhanced settings dialog and configuration management**
|
15
|
+
- Improved settings dialog with more intuitive editing, saving, and loading.
|
16
|
+
- **Modernized UI/UX**
|
17
|
+
- Major updates to CSS, HTML, and JS provide a modern look, responsive design, and improved usability.
|
18
|
+
- **WebSocket server and log output improvements**
|
19
|
+
- Flexible port settings and real-time, improved logging/progress display.
|
20
|
+
|
21
|
+
---
|
22
|
+
|
23
|
+
## Ruby Setup
|
24
|
+
|
25
|
+
For Ubuntu:
|
26
|
+
```sh
|
27
|
+
$ sudo apt install ruby ruby-all-dev
|
28
|
+
```
|
10
29
|
|
11
30
|
## CppUmlClass Setup
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
31
|
+
|
32
|
+
For Ubuntu:
|
33
|
+
```sh
|
34
|
+
$ sudo apt install chromium-browser
|
35
|
+
$ sudo apt install plantuml
|
36
|
+
$ sudo apt install clang-format
|
37
|
+
$ sudo apt install gcc
|
38
|
+
```
|
17
39
|
|
18
40
|
## Installation
|
19
41
|
|
20
|
-
|
42
|
+
Add the gem to your application's Gemfile by running:
|
43
|
+
|
44
|
+
```sh
|
45
|
+
$ bundle add CppUmlClass
|
46
|
+
```
|
21
47
|
|
22
|
-
|
48
|
+
If you are not using bundler, install the gem directly:
|
23
49
|
|
24
|
-
|
50
|
+
```sh
|
51
|
+
$ sudo gem install CppUmlClass
|
52
|
+
```
|
25
53
|
|
26
|
-
|
54
|
+
## Usage (GUI)
|
27
55
|
|
28
|
-
|
29
|
-
A browser-based GUI opens.
|
56
|
+
A browser-based GUI will open:
|
30
57
|
|
31
|
-
|
32
|
-
|
33
|
-
|
58
|
+
```sh
|
59
|
+
$ start_cpp_uml_class.rb
|
60
|
+
```
|
61
|
+
|
62
|
+
https://github.com/user-attachments/assets/d30ff495-5cee-4431-b35b-4c22f630ca22
|
63
|
+
|
64
|
+
## Usage (Command Line)
|
65
|
+
|
66
|
+
You can also use the command line interface:
|
34
67
|
|
35
|
-
## Usage(command line)
|
36
|
-
command line interface
|
37
68
|
```
|
38
69
|
Usage: create_cpp_uml_class.rb [options] cpp_source_directory out_file
|
39
70
|
-c config_file
|
40
71
|
```
|
41
|
-
config_file defaults to CppUmlClass/config/setting.json in your home directory.
|
72
|
+
The config_file defaults to `CppUmlClass/config/setting.json` in your home directory.
|
42
73
|
|
43
|
-
Example
|
74
|
+
Example:
|
44
75
|
|
45
|
-
|
76
|
+
```sh
|
77
|
+
$ create_cpp_uml_class.rb ~/tool/cpp_test /tmp/test.pu
|
78
|
+
```
|
46
79
|
|
80
|
+
---
|
47
81
|
|
48
|
-
##
|
82
|
+
## Class Color Support
|
49
83
|
|
50
84
|

|
51
85
|
|
52
|
-
##
|
53
|
-
|
54
|
-
-
|
55
|
-
-
|
56
|
-
-
|
57
|
-
-
|
58
|
-
-
|
59
|
-
-
|
60
|
-
-
|
61
|
-
|
62
|
-
|
63
|
-
|
86
|
+
## Settings
|
87
|
+
|
88
|
+
- PlantUML command
|
89
|
+
- Editor command for PlantUML files
|
90
|
+
- Default class color 1 and source path for color 1
|
91
|
+
- Default class color 2 and source path for color 2
|
92
|
+
- Default class color 3 and source path for color 3
|
93
|
+
- Exclude path
|
94
|
+
- define_hash
|
95
|
+
|
96
|
+
The settings file is stored at `CppUmlClass/config/setting.json` in your home directory.
|
97
|
+
|
98
|
+
**Example for define_hash:**
|
99
|
+
```json
|
100
|
+
{
|
101
|
+
"TEST3": true,
|
102
|
+
"DEBUG": 1,
|
103
|
+
"TEST_FUNC": true
|
104
|
+
}
|
105
|
+
```
|
64
106
|
|
65
107
|

|
66
108
|
|
67
|
-
|
68
|
-
|
69
109
|
## Development
|
70
110
|
|
71
|
-
To install this gem
|
111
|
+
To install this gem locally, run `bundle exec rake install`.
|
112
|
+
To release a new version, update the version in `version.rb`, then run `bundle exec rake release` (this creates a git tag, pushes commits and tags, and uploads the `.gem` file to [rubygems.org](https://rubygems.org)).
|
72
113
|
|
73
114
|
## Contributing
|
74
115
|
|
@@ -76,4 +117,7 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/kuwaya
|
|
76
117
|
|
77
118
|
## License
|
78
119
|
|
79
|
-
|
120
|
+
This gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
121
|
+
|
122
|
+
---
|
123
|
+
|
data/exe/create_cpp_uml_class.rb
CHANGED
@@ -37,11 +37,13 @@ end
|
|
37
37
|
json_config = config_json_hash(json)
|
38
38
|
|
39
39
|
file = "#{dir}/lib/create_uml_class.rb"
|
40
|
-
|
40
|
+
load file
|
41
|
+
file = "#{dir}/lib/ifdef_process.rb"
|
41
42
|
load file
|
42
43
|
|
43
44
|
@config = json_config
|
44
|
-
|
45
|
+
pifdef = IfdefProcess.new
|
46
|
+
uml = create_uml_class(pifdef, in_dir, out_file)
|
45
47
|
|
46
48
|
File.open(out_file, "w") do |f|
|
47
49
|
f.puts uml
|
data/img/CppUMLClass.mp4
CHANGED
Binary file
|
data/img/class_color.png
CHANGED
Binary file
|
data/img/setting.png
CHANGED
Binary file
|
data/lib/CppUmlClass/version.rb
CHANGED
data/lib/config/setting.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"version": 0.
|
2
|
+
"version": 0.3,
|
3
3
|
"setting_list": [
|
4
4
|
{
|
5
5
|
"name": "plantuml",
|
@@ -66,10 +66,20 @@
|
|
66
66
|
},
|
67
67
|
{
|
68
68
|
"name": "exclude_path",
|
69
|
-
"value": "(
|
69
|
+
"value": "(build)",
|
70
70
|
"type": "input",
|
71
71
|
"select": "",
|
72
72
|
"description": "除外するパス(正規表現)"
|
73
|
+
},
|
74
|
+
{
|
75
|
+
"name": "define_hash",
|
76
|
+
"value": {
|
77
|
+
"DEBUG": true,
|
78
|
+
"DEBUG_PRINT2": true
|
79
|
+
},
|
80
|
+
"type": "textarea",
|
81
|
+
"select": "",
|
82
|
+
"description": "定義するdefineのリスト<br>例:<br>{<br> \"DEBUG\":true <br> \"VERSION\":1<br>}"
|
73
83
|
}
|
74
84
|
]
|
75
85
|
}
|
data/lib/config.ru
CHANGED
data/lib/cpp_uml_class.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
require "server_app_base.rb"
|
3
3
|
require "kconv"
|
4
|
-
|
4
|
+
require "create_uml_class.rb"
|
5
|
+
require "ifdef_process"
|
5
6
|
|
6
7
|
class CppUmlClass < AppMainBase
|
7
8
|
def start(argv)
|
@@ -22,9 +23,9 @@ class CppUmlClass < AppMainBase
|
|
22
23
|
out_svg = out_file.gsub(File.extname(out_file), "") + ".svg"
|
23
24
|
|
24
25
|
# uml作成
|
25
|
-
|
26
|
+
pifdef = IfdefProcess.new
|
26
27
|
|
27
|
-
uml = create_uml_class(in_dir, out_file)
|
28
|
+
uml = create_uml_class(pifdef, in_dir, out_file)
|
28
29
|
|
29
30
|
File.open(out_file, "w") do |f|
|
30
31
|
f.puts uml
|
@@ -41,6 +42,8 @@ class CppUmlClass < AppMainBase
|
|
41
42
|
yield "exec error"
|
42
43
|
yield cmd
|
43
44
|
end
|
45
|
+
|
46
|
+
app_send("popup:0:終了しました。<br><hr>#{in_dir}<br>で使用されているifdefのリスト<br><hr> #{pifdef.define_list.sort.join("<br>")}")
|
44
47
|
rescue
|
45
48
|
puts $!
|
46
49
|
puts $@
|
data/lib/create_uml_class.rb
CHANGED
@@ -3,6 +3,7 @@ $LOAD_PATH << File.dirname(File.expand_path(__FILE__))
|
|
3
3
|
require "tempfile"
|
4
4
|
require "facter"
|
5
5
|
require "check_word"
|
6
|
+
require "ifdef_process"
|
6
7
|
|
7
8
|
CStruct = Struct.new(:type,
|
8
9
|
:name,
|
@@ -19,12 +20,12 @@ def get_gcc_path
|
|
19
20
|
ENV["PATH"].split(";").each do |path|
|
20
21
|
gcc_path = "#{path}\\gcc"
|
21
22
|
if File.exists? gcc_path
|
22
|
-
return "rubyw " + gcc_path + "
|
23
|
+
return "rubyw " + gcc_path + "w1 "
|
23
24
|
end
|
24
25
|
end
|
25
26
|
return ""
|
26
27
|
else
|
27
|
-
return "gcc -fpreprocessed -
|
28
|
+
return "gcc -fpreprocessed -E "
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
@@ -64,43 +65,29 @@ end
|
|
64
65
|
# フォーマット変更(clang-format)
|
65
66
|
# コメント削除(gcc)
|
66
67
|
# ifdefの処理(unifdef)
|
67
|
-
def update_source(file)
|
68
|
-
#
|
69
|
-
gcc_out_file = Tempfile.open(["gcc", File.extname(file)])
|
70
|
-
#puts gcc_out_file.path
|
71
|
-
#puts "|#{get_gcc_path} #{file} > #{gcc_out_file.path}"
|
72
|
-
open("|#{get_gcc_path} #{file} > #{gcc_out_file.path}") do |f|
|
73
|
-
if f.read =~ /error/
|
74
|
-
puts "gcc error #{f}"
|
75
|
-
return ""
|
76
|
-
end
|
77
|
-
end
|
78
|
-
#puts File.binread gcc_out_file.path
|
68
|
+
def update_source(pifdef, file)
|
69
|
+
#puts "update_source=#{file}"
|
79
70
|
# clang-format
|
80
71
|
format_out_file = Tempfile.open(["clang_format", File.extname(file)])
|
81
|
-
#
|
82
|
-
#puts "|#{get_clang_format_path} #{gcc_out_file.path} > #{format_out_file.path}"
|
83
|
-
open("|#{get_clang_format_path} #{gcc_out_file.path} > #{format_out_file.path}") do |f|
|
72
|
+
open("|#{get_clang_format_path} #{file} > #{format_out_file.path}") do |f|
|
84
73
|
if f.read =~ /No such/
|
85
|
-
puts "
|
74
|
+
puts "clang-format error #{f}"
|
86
75
|
return ""
|
87
76
|
end
|
88
77
|
end
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
|
93
|
-
#puts unifdef_out_file.path
|
94
|
-
#puts "|#{get_unifdef_path} #{format_out_file.path} > #{unifdef_out_file.path}"
|
95
|
-
open("|#{get_unifdef_path} #{gcc_out_file.path} > #{unifdef_out_file.path}") do |f|
|
96
|
-
if f.read =~ /No such/
|
78
|
+
# コメント削除
|
79
|
+
gcc_out_file = Tempfile.open(["gcc", File.extname(file)])
|
80
|
+
open("|#{get_gcc_path} #{format_out_file.path} > #{gcc_out_file.path}") do |f|
|
81
|
+
if f.read =~ /error/
|
97
82
|
puts "gcc error #{f}"
|
98
83
|
return ""
|
99
84
|
end
|
100
85
|
end
|
101
|
-
buf = File.binread
|
102
|
-
puts buf
|
103
|
-
|
86
|
+
buf = File.binread gcc_out_file.path
|
87
|
+
#puts buf
|
88
|
+
# ifdef処理
|
89
|
+
out_buf = pifdef.process_ifdef(buf, @config["define_hash"])
|
90
|
+
return out_buf.join("\n")
|
104
91
|
end
|
105
92
|
|
106
93
|
def print_uml(out, out_list)
|
@@ -110,7 +97,7 @@ def print_uml(out, out_list)
|
|
110
97
|
elsif o_list.type == :module_start
|
111
98
|
out.push "namespace #{o_list.name} {"
|
112
99
|
elsif o_list.type == :class_end
|
113
|
-
pp o_list if o_list.name == ""
|
100
|
+
#pp o_list if o_list.name == ""
|
114
101
|
out.push "class #{o_list.name} #{o_list.class_color}{"
|
115
102
|
# インスタンス変数の出力
|
116
103
|
o_list.var_list.uniq.each do |iv|
|
@@ -135,7 +122,7 @@ def print_uml(out, out_list)
|
|
135
122
|
o_list.method_list.size != 0 or
|
136
123
|
o_list.inherit_list.size != 0 or
|
137
124
|
o_list.composition_list.size != 0
|
138
|
-
pp o_list if o_list.name == ""
|
125
|
+
#pp o_list if o_list.name == ""
|
139
126
|
out.push "class #{o_list.name} {"
|
140
127
|
# インスタンス変数の出力
|
141
128
|
o_list.var_list.uniq.each do |iv|
|
@@ -164,22 +151,23 @@ def print_uml(out, out_list)
|
|
164
151
|
return out
|
165
152
|
end
|
166
153
|
|
167
|
-
def composition_list_create(in_dir, out_list)
|
154
|
+
def composition_list_create(pifdef,in_dir, out_list)
|
168
155
|
# composition_list
|
169
|
-
Dir.glob("#{in_dir}/**/*.{h,cpp,hpp}") do |file|
|
156
|
+
Dir.glob("#{in_dir}/**/*.{h,cpp,hpp,cc}") do |file|
|
170
157
|
if @config["exclude_path"].to_s != "" and file =~ Regexp.new(@config["exclude_path"])
|
171
158
|
#puts "skip #{file}"
|
172
159
|
next
|
173
160
|
end
|
174
|
-
#puts file
|
161
|
+
#puts "file=#{file}"
|
175
162
|
# ソースコードの整形
|
176
|
-
buf = update_source(file)
|
163
|
+
buf = update_source(pifdef, file)
|
177
164
|
# ソースを解析
|
178
165
|
cstruct_list = []
|
179
166
|
block_count = 0
|
180
167
|
buf.each_line do |line|
|
181
168
|
next if line =~ /^[\r\n]*$/ # 空行は対象外
|
182
169
|
next if line =~ /^#/ # #から始まる行は対象外
|
170
|
+
line.gsub!(/["'].*?["']/, '') # "/'囲まれた文字列を削除
|
183
171
|
#puts "comp:#{line}"
|
184
172
|
|
185
173
|
# ブロックの開始/終了
|
@@ -259,7 +247,7 @@ def composition_list_create(in_dir, out_list)
|
|
259
247
|
return out_list
|
260
248
|
end
|
261
249
|
|
262
|
-
def create_uml_class(in_dir, out_file)
|
250
|
+
def create_uml_class(pifdef, in_dir, out_file)
|
263
251
|
out = []
|
264
252
|
out.push "@startuml"
|
265
253
|
|
@@ -277,7 +265,7 @@ def create_uml_class(in_dir, out_file)
|
|
277
265
|
end
|
278
266
|
#puts file
|
279
267
|
# ソースコードの整形
|
280
|
-
buf = update_source(file)
|
268
|
+
buf = update_source(pifdef, file)
|
281
269
|
|
282
270
|
cstruct_list = []
|
283
271
|
block_count = 0
|
@@ -287,6 +275,7 @@ def create_uml_class(in_dir, out_file)
|
|
287
275
|
buf.each_line do |line|
|
288
276
|
next if line =~ /^[\r\n]*$/ # 空行は対象外
|
289
277
|
next if line =~ /^#/ # #から始まる行は対象外
|
278
|
+
line.gsub!(/["'].*?["']/, '') # "/'囲まれた文字列を削除
|
290
279
|
#puts line
|
291
280
|
|
292
281
|
# ブロックの開始/終了
|
@@ -326,7 +315,7 @@ def create_uml_class(in_dir, out_file)
|
|
326
315
|
elsif @config["class_color_path2"].to_s != "" and file =~ Regexp.new(@config["class_color_path2"])
|
327
316
|
cstruct_list.push CStruct.new(:class_end, class_name, block_count, [], [], [], [], @config["class_color2"])
|
328
317
|
elsif @config["class_color_path3"].to_s != "" and file =~ Regexp.new(@config["class_color_path3"])
|
329
|
-
pp file
|
318
|
+
#pp file
|
330
319
|
cstruct_list.push CStruct.new(:class_end, class_name, block_count, [], [], [], [], @config["class_color3"])
|
331
320
|
else
|
332
321
|
cstruct_list.push CStruct.new(:class_end, class_name, block_count, [], [], [], [], @config["default_class_color"])
|
@@ -408,12 +397,13 @@ def create_uml_class(in_dir, out_file)
|
|
408
397
|
end
|
409
398
|
if block_count != 0
|
410
399
|
# エラー
|
400
|
+
puts "error block_count=#{block_count}"
|
411
401
|
puts file
|
412
402
|
return ""
|
413
403
|
end
|
414
404
|
end
|
415
405
|
# compositon_listの作成
|
416
|
-
out_list = composition_list_create(in_dir, out_list)
|
406
|
+
out_list = composition_list_create(pifdef, in_dir, out_list)
|
417
407
|
# UMLの出力
|
418
408
|
out = print_uml(out, out_list)
|
419
409
|
|
@@ -438,39 +428,10 @@ def create_uml_class(in_dir, out_file)
|
|
438
428
|
return out.join("\n")
|
439
429
|
end
|
440
430
|
|
441
|
-
def search_func(file)
|
442
|
-
#puts file
|
443
|
-
# ソースコードの整形
|
444
|
-
buf = update_source(file)
|
445
|
-
# ソースを解析
|
446
|
-
buf.each_line do |line|
|
447
|
-
next if line =~ /^[\r\n]*$/ # 空行は対象外
|
448
|
-
next if line =~ /^#/ # #から始まる行は対象外
|
449
|
-
#puts line
|
450
|
-
if line.gsub(/<.*>/, "") =~ /^\S.*(\S+)::(\S+).*\(.*{$/
|
451
|
-
#puts line.gsub!(/<.*>/, "")
|
452
|
-
line.match(/(\w+)(?=\S+\()/) do |m|
|
453
|
-
#puts "class_name=#{m}"
|
454
|
-
end
|
455
|
-
end
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
431
|
if $0 == __FILE__
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
if true
|
467
|
-
puts create_uml_class(ARGV[0], ARGV[1])
|
468
|
-
else
|
469
|
-
out_list = []
|
470
|
-
out_list.push CStruct.new(:method_start, "DefaultVehicleHal", 1, [], [], [], [])
|
471
|
-
out_list.push CStruct.new(:method_start, "SubscriptionManager", 1, [], [], [], [])
|
472
|
-
out_list.push CStruct.new(:method_start, "ContSubConfigs", 1, [], [], [], [])
|
473
|
-
out_list.push CStruct.new(:method_start, "GetSetValuesClient", 1, [], [], [], [])
|
474
|
-
puts composition_list_create(ARGV[0], out_list)
|
475
|
-
end
|
432
|
+
@config = { "exclude_path" => "",
|
433
|
+
"define_hash" => {} }
|
434
|
+
pifdef = IfdefProcess.new
|
435
|
+
puts create_uml_class(pifdef, ARGV[0], ARGV[1])
|
436
|
+
puts pifdef.define_list
|
476
437
|
end
|