xumlidot 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/xumlidot +2 -31
- data/lib/xumlidot/diagram/dot/klass.rb +25 -10
- data/lib/xumlidot/diagram/dot.rb +8 -8
- data/lib/xumlidot/diagram/shared/naming.rb +5 -4
- data/lib/xumlidot/diagram/xmi/argument.rb +7 -4
- data/lib/xumlidot/diagram/xmi/attribute.rb +5 -5
- data/lib/xumlidot/diagram/xmi/id.rb +45 -1
- data/lib/xumlidot/diagram/xmi/klass.rb +18 -19
- data/lib/xumlidot/diagram/xmi/method.rb +5 -2
- data/lib/xumlidot/diagram/xmi.rb +25 -26
- data/lib/xumlidot/diagram.rb +6 -4
- data/lib/xumlidot/directory_tree.rb +3 -1
- data/lib/xumlidot/loader.rb +49 -0
- data/lib/xumlidot/options.rb +63 -28
- data/lib/xumlidot/parsers/args.rb +17 -21
- data/lib/xumlidot/parsers/call.rb +32 -9
- data/lib/xumlidot/parsers/file.rb +0 -1
- data/lib/xumlidot/parsers/generic.rb +24 -31
- data/lib/xumlidot/parsers/klass_definition.rb +10 -7
- data/lib/xumlidot/parsers/method_signature.rb +27 -23
- data/lib/xumlidot/parsers/module_definition.rb +8 -8
- data/lib/xumlidot/parsers/scope.rb +6 -7
- data/lib/xumlidot/parsers/stack.rb +17 -9
- data/lib/xumlidot/parsers.rb +2 -1
- data/lib/xumlidot/types/argument.rb +1 -1
- data/lib/xumlidot/types/attribute.rb +1 -2
- data/lib/xumlidot/types/constant.rb +4 -4
- data/lib/xumlidot/types/constants.rb +3 -2
- data/lib/xumlidot/types/klass.rb +5 -5
- data/lib/xumlidot/types/method_signature.rb +8 -16
- data/lib/xumlidot/types/superklass.rb +4 -4
- data/lib/xumlidot/types.rb +2 -1
- data/lib/xumlidot.rb +2 -0
- data/spec/spec_helper.rb +21 -2
- metadata +38 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '08c6d11a210e378f99226f1933944c6023d2bb3b0b5a8eeaba85050fe6e8b3cb'
|
4
|
+
data.tar.gz: d8a37ae51f5d1dbc416d05241b456e614f56f82d23b972d9a8e1507dc84835d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bae461d270a21d92c15ff2694b955fc1972e43d6b973da8620032d96533bbfcb02c426793286a0a044b1eeb2f6a01c072e19bb2184a7c1908f596df3f7e6532c
|
7
|
+
data.tar.gz: '08f435ea1c0dddbcf49c53ab6c18820a6aceb67d2f504cbbe315203f9ea9f465dd1c378384bd70abe1202c83aede6f64793f0a7840a321af1052696bf477d203'
|
data/bin/xumlidot
CHANGED
@@ -5,35 +5,6 @@ require_relative '../lib/xumlidot'
|
|
5
5
|
options = ::Xumlidot::Options.parse(ARGV)
|
6
6
|
|
7
7
|
# TODO: user input
|
8
|
-
directories =
|
8
|
+
directories = ARGV
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
# This is our tree of klasses/modules etc
|
13
|
-
# since we can't assume rails conventions for naming
|
14
|
-
# in a Ruby program.
|
15
|
-
constants = ::Xumlidot::Parsers::Stack::Constants.new
|
16
|
-
|
17
|
-
# TODO: move into directory tree
|
18
|
-
dt.find_all_rb_files do |path|
|
19
|
-
STDERR.puts path if ::Xumlidot::Options.debug == true
|
20
|
-
file_contents = File.read(path)
|
21
|
-
|
22
|
-
@parser = Xumlidot::Parsers::File.new(file_contents, constants)
|
23
|
-
@parser.parse
|
24
|
-
end
|
25
|
-
|
26
|
-
# If a class is inherited from but does not exist in the constants
|
27
|
-
# we will create a dummy class.
|
28
|
-
#
|
29
|
-
# if a class is inherited from, we want to find it using the constant lookup
|
30
|
-
# rules definind in the resolver
|
31
|
-
#
|
32
|
-
# and what ... we want to add a reference too it?
|
33
|
-
#
|
34
|
-
# This REALLY should be done whenever we add a superklass
|
35
|
-
# i.e. yeah, its a hack
|
36
|
-
constants.resolve_inheritance()
|
37
|
-
|
38
|
-
diagram = ::Xumlidot::Diagram.new(constants, options)
|
39
|
-
diagram.draw
|
10
|
+
::Xumlidot::Loader.new(directories, options).load
|
@@ -6,8 +6,16 @@ module Xumlidot
|
|
6
6
|
class Diagram
|
7
7
|
class Dot
|
8
8
|
module Method
|
9
|
+
CHARACTER_SUBSTITUTIONS = {
|
10
|
+
'>' => '\>',
|
11
|
+
'<' => '\<',
|
12
|
+
'{' => '\{',
|
13
|
+
'}' => '\}',
|
14
|
+
'|' => '\|'
|
15
|
+
}.freeze
|
16
|
+
|
9
17
|
def to_dot
|
10
|
-
to_s.gsub(
|
18
|
+
to_s.gsub(/[#{CHARACTER_SUBSTITUTIONS.keys.join}]/, CHARACTER_SUBSTITUTIONS)
|
11
19
|
end
|
12
20
|
end
|
13
21
|
|
@@ -29,22 +37,29 @@ module Xumlidot
|
|
29
37
|
end
|
30
38
|
|
31
39
|
def draw_composition(composee)
|
32
|
-
"\"#{draw_identifier(composee.definition)}\"
|
40
|
+
"\"#{draw_identifier(composee.definition)}\"" \
|
41
|
+
" -> \"#{draw_identifier(@definition)}\"" \
|
42
|
+
' [label="", arrowhead="diamond", arrowtail="diamond"]'
|
33
43
|
end
|
34
44
|
|
35
|
-
def
|
45
|
+
def draw_inheritance # rubocop:disable Metrics/AbcSize
|
36
46
|
return nil if @definition.superklass.empty? && @definition.inherited_modules.empty?
|
37
47
|
|
38
|
-
dot =
|
39
|
-
|
40
|
-
dot += "\"#{draw_identifier(@definition)}\"
|
48
|
+
dot = ''
|
49
|
+
unless @definition.superklass.empty?
|
50
|
+
dot += "\"#{draw_identifier(@definition)}\"" \
|
51
|
+
" -> \"#{draw_ancestor(@definition.superklass)}\"" \
|
52
|
+
" [label=\"\", arrowhead=\"empty\", arrowtail=\"onormal\"]\n"
|
41
53
|
end
|
42
54
|
|
43
55
|
return dot if @definition.inherited_modules.empty?
|
44
56
|
|
45
57
|
@definition.inherited_modules.each do |m|
|
46
58
|
next if m.empty?
|
47
|
-
|
59
|
+
|
60
|
+
dot += "\"#{draw_identifier(@definition)}\"" \
|
61
|
+
" -> \"#{draw_ancestor(m)}\"" \
|
62
|
+
" [label=\"#{m.type}s\", arrowhead=\"empty\", arrowtail=\"onormal\"]\n"
|
48
63
|
end
|
49
64
|
|
50
65
|
dot
|
@@ -52,19 +67,19 @@ module Xumlidot
|
|
52
67
|
|
53
68
|
private
|
54
69
|
|
55
|
-
def draw_methods
|
70
|
+
def draw_methods # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
56
71
|
@attributes.each { |a| a.extend(Attribute) }
|
57
72
|
@class_methods.each { |a| a.extend(Method) }
|
58
73
|
@instance_methods.each { |a| a.extend(Method) }
|
59
74
|
|
60
75
|
km = ''
|
61
76
|
km += @attributes.map(&:to_dot).join('\l')
|
62
|
-
km += '\\l'
|
77
|
+
km += '\\l' if @attributes.any?
|
63
78
|
|
64
79
|
km += @class_methods.map(&:to_dot).join('\l')
|
65
80
|
km += '\\l' unless km.end_with?('\\l')
|
66
|
-
km += '|' if instance_methods.size.positive?
|
67
81
|
|
82
|
+
km += '|' if instance_methods.any?
|
68
83
|
km += @instance_methods.map(&:to_dot).join('\l')
|
69
84
|
km += '\\l' unless km.end_with?('\\l')
|
70
85
|
km
|
data/lib/xumlidot/diagram/dot.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'dot/klass'
|
2
4
|
require_relative 'dot/module'
|
3
5
|
|
4
6
|
module Xumlidot
|
5
7
|
class Diagram
|
6
8
|
class Dot
|
7
|
-
|
8
|
-
def initialize(stack, options = nil)
|
9
|
+
def initialize(stack)
|
9
10
|
@stack = stack
|
10
|
-
@options = options
|
11
11
|
@output = []
|
12
12
|
end
|
13
13
|
|
14
14
|
# We have to draw any connecting labels AFTER we have drawn the klasses
|
15
15
|
# in order to have something to connect.
|
16
|
-
def draw
|
16
|
+
def draw # rubocop:disable Metrics/AbcSize
|
17
17
|
@output << header
|
18
18
|
@stack.traverse do |klass|
|
19
19
|
klass.extend(::Xumlidot::Diagram::Dot::Klass)
|
@@ -21,15 +21,15 @@ module Xumlidot
|
|
21
21
|
end
|
22
22
|
|
23
23
|
@stack.traverse do |klass|
|
24
|
-
# Check - i
|
24
|
+
# Check - i shouldn't need to extend twice
|
25
25
|
klass.extend(::Xumlidot::Diagram::Dot::Klass)
|
26
26
|
|
27
|
-
if
|
28
|
-
output = klass.
|
27
|
+
if ::Xumlidot::Options.inheritance
|
28
|
+
output = klass.draw_inheritance
|
29
29
|
@output << output unless output.nil?
|
30
30
|
end
|
31
31
|
|
32
|
-
if
|
32
|
+
if ::Xumlidot::Options.composition
|
33
33
|
klass.constants.each do |k|
|
34
34
|
@output << klass.draw_composition(k)
|
35
35
|
end
|
@@ -1,17 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Xumlidot
|
2
3
|
class Diagram
|
3
4
|
module Shared
|
4
5
|
module Naming
|
5
|
-
def draw_identifier(
|
6
|
-
[
|
6
|
+
def draw_identifier(definition = @definition)
|
7
|
+
[definition.name.name, definition.name.namespace.reverse].reverse.flatten.join('::')
|
7
8
|
end
|
8
9
|
|
9
10
|
def draw_name
|
10
11
|
@definition.name.name.join('::')
|
11
12
|
end
|
12
13
|
|
13
|
-
def draw_ancestor(
|
14
|
-
[
|
14
|
+
def draw_ancestor(definition = @definition)
|
15
|
+
[definition.name, definition.namespace.reverse].reverse.flatten.join('::')
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
@@ -10,19 +10,22 @@ module Xumlidot
|
|
10
10
|
|
11
11
|
def draw
|
12
12
|
xmi = "<ownedParameter kind=\"inout\" name=\"#{name_to_xmi}\" xmi:id=\"#{id}\" xmi:type=\"uml:Parameter\">"
|
13
|
-
|
14
|
-
|
13
|
+
if default
|
14
|
+
xmi += "<defaultValue value=\"#{default_to_xmi}\" xmi:id=\"#{default_id}\" xmi:type=\"uml:LiteralString\"/>"
|
15
|
+
end
|
16
|
+
"#{xmi}</ownedParameter>"
|
15
17
|
end
|
16
18
|
|
17
19
|
private
|
18
20
|
|
19
21
|
def name_to_xmi
|
20
|
-
name
|
22
|
+
name&.encode(xml: :text)
|
21
23
|
end
|
22
24
|
|
23
25
|
def default_to_xmi
|
24
26
|
return default unless default.is_a?(String)
|
25
|
-
|
27
|
+
|
28
|
+
default.encode(xml: :text)
|
26
29
|
end
|
27
30
|
|
28
31
|
def default_id
|
@@ -8,16 +8,16 @@ module Xumlidot
|
|
8
8
|
module Attribute
|
9
9
|
include ::Xumlidot::Diagram::Xmi::ID
|
10
10
|
|
11
|
-
# TODO - public/private visibility on attributes
|
11
|
+
# TODO: - public/private visibility on attributes
|
12
12
|
def draw
|
13
|
-
|
14
|
-
|
13
|
+
'<ownedAttribute aggregation="none" isDerived="false" isDerivedUnion="false" isID="false"' \
|
14
|
+
" isLeaf=\"false\" isReadOnly=\"false\" isStatic=\"false\" name=\"#{name_to_xmi}\"" \
|
15
|
+
" visibility=\"public\" xmi:id=\"#{id}\" xmi:type=\"uml:Property\"></ownedAttribute>"
|
15
16
|
end
|
16
17
|
|
17
18
|
def name_to_xmi
|
18
|
-
name
|
19
|
+
name&.encode(xml: :text)
|
19
20
|
end
|
20
|
-
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -3,6 +3,46 @@
|
|
3
3
|
require 'securerandom'
|
4
4
|
|
5
5
|
module Xumlidot
|
6
|
+
class ID
|
7
|
+
class << self
|
8
|
+
# rubocop:disable Layout/LineLength
|
9
|
+
PREGENERATED = %w[ 915803defa2bd0509fc1ff7a652081d4 e891fc71118502b95030b5e15d887622 2cf60373a8305b3f64bb93a5fa0e786c 35cd5b04a0ab4542aede1e37046fab5e
|
10
|
+
e1521c43130d064474e1585be1d69c6f 59975b5d607a197e676e2534e3dce454 9e52022530441f1688dfab381bba4069 f84f7b576ba1ab5929b4208cebfe7935
|
11
|
+
37e5d86bb891a70011261ad861118a73 09646c77f8dfd088487c91f75c387a4c 9a064273fb75db2d41ad146063940862 ecc9ae948a23543ad23e61b0f907ae6b
|
12
|
+
b922777242d6e4d182e979a19b6b8fd9 b7f1299975494da9811c061f008cacba c906375f1de4be9d3dd3ea56e7917ea6 4265f6134237c7d0c9a4f12b838d1849
|
13
|
+
2d75d4762aa997551f95c76ff23a1e52 fe32489778ddc04b5b2e29a69a25c44e 8e89af98ee73225cac65ade347f5d653 70668faf589fcdd1034db5e8e38c0b8c
|
14
|
+
5b4d3919edab18b46790dc2af405982e bb35181dc1d23696cb914287fb3073da 1adca3c4c42e345682e0abe24dee32fb 611e830b410e4216c80b5fb62f0f0d20
|
15
|
+
648b5d6b3d87b62a3fd34620c391c6e5 bd0747fa99c86e03dd6bbeec3989f859 52653ebf9f0c0930523f583ca3a54476 52e2bdc77cba152a5f8a1e7703893b13
|
16
|
+
08b98d56e4b3e9dd7415cd0174550e01 63de406c477145edb70df08e1fe3d3e9 93f7b64cbd8e96ac5b54e0b83cfef84b cae3e7e7fc79276237aecaf68ab1bdc3
|
17
|
+
d2bde85b6c67f2c4e4f21f4eb24a9e11 b6239715d7b6dfbe845bf6218ffa9267 d018d840347248a3da9989cd56f10532 1fc72578fa0f6820991a2068aac595b0
|
18
|
+
f200b2bf3d28ce99cadeb505fe2a13f9 aba7ec911338260e448768655f9f7f62 e5019785cc3b2db9866887002aab0e82 a9490aac41fa641bf17595f5adc014e2
|
19
|
+
85917936118146692ec4ebaff9bffa25 13fe8089229ff0a7a824a11683e1afa4 8f4dcf8694457f5d09b69513034eb896 aa841e2dda7b46f397dfee83ebebfcb3
|
20
|
+
e84c823e04f190a46b92c7e96d39d802 8dc5d1471bda113d37134e6e457be7f3 ee0989ea42bd2a2e06b0b923bc27aac7 b21b9efefa95229940367caa25d7c7b6
|
21
|
+
7f32d97647fa4d3bb1cb0f8842f6280c 65864053fcd398271fd0482e4b8d6291 22c52a000c617293244d2346679bbcc7 f745cfcd9617f0ee9e8b7a609ccce424
|
22
|
+
85ee520fa2e905d454ccdbf94d789e81 f260df13675880d30ff85dd6713b3df8 afdbe21f7540febe19e2dd2efb1770fe 9c6e6b915115f94f74777e1fe3683805
|
23
|
+
8517f315cc89778e32d62b0e2ee0c01e 2303ed4f97dd09d24427400e3ed9dbaf 72549f0fe322198493927ff113bb9841 c27b2914926e6c8c7406199b0532ba00
|
24
|
+
79940b95278e119378da6e15eea86a90 cd3ee7977ead372f732a8c586ea566a7 ea6370883b3de89a8b38a03c1ec9d591 92ed3a3d54ac7c28e7544ea22f6bfe97
|
25
|
+
8c2302bf6185908b24798f359a2e4838 bef733b51d12963d596f5ecfd5197201 3fa6ac50361036266b73bca0ad3dee57 a5545b87d99a3b7c9533085498ff460e
|
26
|
+
dc3115e7ced845fc6303b2b294a42437 027b8863405ce601db60d685af987dee 71ac366b83d49ca62c3f7c0c7c101f43 6647027529522180e0ae96a176e5766d
|
27
|
+
22e2726ab1b3df71e314f8145180f1c8 b800ccd5d685adac614624ffd5abb098 6c395e62f19d0f5b04f7cea5dd616a24 e2bbe604833cc15c393450d215008306
|
28
|
+
7fa0acb9786d57b2ef4d9027f6cc7992 73d5302aedef54fb51cd08173c1f1829 01cef3c8b0d5ef6cae8574d1a5044b2b c695a6a12c418bb56699b2f5c6559da3
|
29
|
+
a14c60d2210dfea6e625208b72aa79e9 1c60dc02eece351995820d7436e7752e d2a2b30eecceb9f453697103b01b203a 3ae847a28c2248460a37e24686860479
|
30
|
+
354982e26fd1da65403c9e70866e14f7 66485373131b4d5e02261f9d085be072 2e3e154c3ec06e401f48c7f444583d45 e57c33100b8f66813ee9265e4f023e03
|
31
|
+
5afa58ca1c74f449d1b18cc3cb39b19f d5775ea87353bb12f31318533ed17382 c55778698f7c896c6f7e1a35f8698a06 178d5cdabad7e9f82f326a9ebbd01737
|
32
|
+
31cf106e33c94b139f8c8c4820b46524 50a49cf6d0b9bedcbcef845917889a62 cc8aa4100a6f3855df3518a0a4474b74 c98c57ab3db339c74d44d6da5b2e0e62
|
33
|
+
a04e46e4a1f5fea64b3a47a3cc8ca0de 750156c36b6990f2a4763949775ea6a1 423cb15b7efee4800449579ce561a58e 424041648b3414d67743957b9e2ad66c ].freeze
|
34
|
+
# rubocop:enable Layout/LineLength
|
35
|
+
|
36
|
+
def reset
|
37
|
+
@fixed = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def fixed
|
41
|
+
@fixed ||= PREGENERATED.dup
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
6
46
|
class Diagram
|
7
47
|
class Xmi
|
8
48
|
# Helper - everything needs an id and these ids need to be used in the
|
@@ -31,7 +71,11 @@ module Xumlidot
|
|
31
71
|
private
|
32
72
|
|
33
73
|
def new_id
|
34
|
-
|
74
|
+
if ::Xumlidot::Options.use_debug_ids
|
75
|
+
::Xumlidot::ID.fixed.shift
|
76
|
+
else
|
77
|
+
SecureRandom.hex
|
78
|
+
end
|
35
79
|
end
|
36
80
|
end
|
37
81
|
end
|
@@ -24,39 +24,38 @@ module Xumlidot
|
|
24
24
|
end
|
25
25
|
|
26
26
|
# TODO: Split this into model and diagram classes
|
27
|
-
class Model
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
end
|
27
|
+
# class Model
|
28
|
+
# end
|
29
|
+
# class Diagram
|
30
|
+
# end
|
32
31
|
|
33
|
-
def draw_klass
|
32
|
+
def draw_klass # rubocop:disable Metrics/AbcSize
|
34
33
|
definition.name.extend(Name)
|
35
34
|
xmi = "<ownedMember isAbstract=\"false\" isActive=\"false\" isLeaf=\"false\" name=\"#{definition.name.to_xmi}\" visibility=\"public\" xmi:id=\"#{id}\" xmi:type=\"uml:Class\">"
|
36
|
-
xmi += draw_model_inheritance if
|
35
|
+
xmi += draw_model_inheritance if ::Xumlidot::Options.inheritance
|
37
36
|
xmi += extend_and_draw(attributes)
|
38
37
|
xmi += extend_and_draw(class_methods)
|
39
38
|
xmi += extend_and_draw(instance_methods)
|
40
|
-
xmi
|
39
|
+
"#{xmi}</ownedMember>"
|
41
40
|
end
|
42
41
|
|
43
42
|
# Draws a diagram element i.e. the part which is rendered
|
44
|
-
def draw_diagram
|
43
|
+
def draw_diagram
|
45
44
|
xml = %(<uml:DiagramElement preferredShapeType="Class" subject="#{id}" xmi:id="#{id}de">
|
46
45
|
</uml:DiagramElement>)
|
47
46
|
|
48
47
|
return xml if @definition.superklass.empty? && @definition.inherited_modules.empty?
|
49
|
-
return xml unless
|
48
|
+
return xml unless ::Xumlidot::Options.inheritance
|
50
49
|
|
51
|
-
xml
|
50
|
+
xml + draw_diagram_generalisation
|
52
51
|
end
|
53
52
|
|
54
53
|
def draw_diagram_generalisation
|
55
54
|
xml = ''
|
56
55
|
|
57
|
-
|
56
|
+
unless @definition.superklass.empty?
|
58
57
|
xml += %(<uml:DiagramElement fromDiagramElement="#{@definition.superklass.id}de" preferredShapeType="Generalization" subject="#{gen_id}" toDiagramElement="#{id}de">
|
59
|
-
|
58
|
+
</uml:DiagramElement>)
|
60
59
|
end
|
61
60
|
|
62
61
|
return xml if @definition.inherited_modules.empty?
|
@@ -65,7 +64,7 @@ module Xumlidot
|
|
65
64
|
next if m.empty?
|
66
65
|
|
67
66
|
xml += %(<uml:DiagramElement fromDiagramElement="#{m.id}de" preferredShapeType="Generalization" subject="#{gen_id}" toDiagramElement="#{id}de">
|
68
|
-
|
67
|
+
</uml:DiagramElement>)
|
69
68
|
end
|
70
69
|
|
71
70
|
xml
|
@@ -77,12 +76,12 @@ module Xumlidot
|
|
77
76
|
# general =
|
78
77
|
# id = IMPORTANT; will be used to draw the lines in the diagram
|
79
78
|
#
|
80
|
-
def draw_model_inheritance
|
79
|
+
def draw_model_inheritance # rubocop:disable Metrics/AbcSize
|
81
80
|
return '' if @definition.superklass.empty? && @definition.inherited_modules.empty?
|
82
81
|
|
83
82
|
xml = ''
|
84
83
|
|
85
|
-
|
84
|
+
unless @definition.superklass.empty?
|
86
85
|
xml += %(<generalization general="#{@definition.superklass.id}" xmi:id="#{gen_id}" xmi:type="uml:Generalization">
|
87
86
|
</generalization>)
|
88
87
|
end
|
@@ -101,11 +100,11 @@ module Xumlidot
|
|
101
100
|
def draw_model_composition(composee)
|
102
101
|
%(<ownedMember isAbstract="false" isDerived="false" isLeaf="false" xmi:id="#{association_id}" xmi:type="uml:Association">
|
103
102
|
<memberEnd xmi:idref="#{association_end_id}"/>
|
104
|
-
<ownedEnd aggregation="none" association="#{association_id}" isDerived="false" isDerivedUnion="false" isLeaf="false" isNavigable="true" isReadOnly="false" isStatic="false" type="#{id}" xmi:id="
|
103
|
+
<ownedEnd aggregation="none" association="#{association_id}" isDerived="false" isDerivedUnion="false" isLeaf="false" isNavigable="true" isReadOnly="false" isStatic="false" type="#{id}" xmi:id="#{association_end_id}" xmi:type="uml:Property">
|
105
104
|
</ownedEnd>
|
106
105
|
<memberEnd xmi:idref="#{composee.association_end_id}"/>
|
107
|
-
|
108
|
-
|
106
|
+
<ownedEnd aggregation="composite" association="#{association_id}" isDerived="false" isDerivedUnion="false" isLeaf="false" isNavigable="true" isReadOnly="false" isStatic="false" type="#{composee.id}" xmi:id="#{composee.association_end_id}" xmi:type="uml:Property">
|
107
|
+
</ownedEnd>
|
109
108
|
</ownedMember>)
|
110
109
|
end
|
111
110
|
|
@@ -14,17 +14,20 @@ module Xumlidot
|
|
14
14
|
return '<<' if name == :<<
|
15
15
|
return '>>' if name == :>>
|
16
16
|
return '<=>' if name == :<=>
|
17
|
+
|
17
18
|
name
|
18
19
|
end
|
19
20
|
|
20
21
|
def draw
|
21
|
-
xmi =
|
22
|
+
xmi = '<ownedOperation isAbstract="false" isLeaf="false" isOrdered="false" isQuery="false"' \
|
23
|
+
" isStatic=\"#{superclass_method}\" isUnique=\"true\" name=\"#{name_to_xmi}\"" \
|
24
|
+
" visibility=\"#{visibility}\" xmi:id=\"#{id}\" xmi:type=\"uml:Operation\">"
|
22
25
|
xmi += "<ownedParameter kind=\"return\" xmi:id=\"#{return_id}\" xmi:type=\"uml:Parameter\"/>"
|
23
26
|
args.each do |argument|
|
24
27
|
argument.extend(::Xumlidot::Diagram::Xmi::Argument)
|
25
28
|
xmi += argument.draw
|
26
29
|
end
|
27
|
-
xmi
|
30
|
+
"#{xmi}</ownedOperation>"
|
28
31
|
end
|
29
32
|
|
30
33
|
private
|
data/lib/xumlidot/diagram/xmi.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'xmi/argument'
|
2
4
|
require_relative 'xmi/attribute'
|
3
5
|
require_relative 'xmi/klass'
|
@@ -8,16 +10,9 @@ require 'rexml/document'
|
|
8
10
|
module Xumlidot
|
9
11
|
class Diagram
|
10
12
|
class Xmi
|
11
|
-
|
12
13
|
include REXML
|
13
14
|
|
14
15
|
class Elements < Array
|
15
|
-
|
16
|
-
def initialize(options)
|
17
|
-
super()
|
18
|
-
@options = options
|
19
|
-
end
|
20
|
-
|
21
16
|
def draw
|
22
17
|
xml = header
|
23
18
|
uniq.each { |de| xml += de }
|
@@ -46,7 +41,7 @@ module Xumlidot
|
|
46
41
|
private
|
47
42
|
|
48
43
|
def header
|
49
|
-
%(<uml:Model name="#{
|
44
|
+
%(<uml:Model name="#{::Xumlidot::Options.model_name}" xmi:id="jcBKnwaFYHEAAQV_">)
|
50
45
|
end
|
51
46
|
|
52
47
|
def footer
|
@@ -58,12 +53,13 @@ module Xumlidot
|
|
58
53
|
private
|
59
54
|
|
60
55
|
def header
|
61
|
-
%(<uml:Diagram diagramType="ClassDiagram" documentation=""
|
62
|
-
|
56
|
+
%(<uml:Diagram diagramType="ClassDiagram" documentation=""
|
57
|
+
name="#{::Xumlidot::Options.title}" toolName="Visual Paradigm" xmi:id="QfZKnwaFYHEAAQj3">
|
58
|
+
<uml:Diagram.element>)
|
63
59
|
end
|
64
60
|
|
65
61
|
def footer
|
66
|
-
%(
|
62
|
+
%(</uml:Diagram.element>
|
67
63
|
</uml:Diagram>)
|
68
64
|
end
|
69
65
|
end
|
@@ -76,7 +72,7 @@ module Xumlidot
|
|
76
72
|
end
|
77
73
|
|
78
74
|
# reverse lookup
|
79
|
-
def has_value?(id)
|
75
|
+
def has_value?(id) # rubocop:disable Naming/PredicateName
|
80
76
|
@id_to_namespace[id] != nil
|
81
77
|
end
|
82
78
|
|
@@ -94,20 +90,19 @@ module Xumlidot
|
|
94
90
|
end
|
95
91
|
end
|
96
92
|
|
97
|
-
def initialize(stack
|
93
|
+
def initialize(stack)
|
98
94
|
@stack = stack
|
99
|
-
@options = options
|
100
95
|
|
101
96
|
@namespace_to_id = NamespaceToId.new
|
102
97
|
|
103
|
-
@model = ModelElements.new
|
104
|
-
@diagram = DiagramElements.new
|
98
|
+
@model = ModelElements.new
|
99
|
+
@diagram = DiagramElements.new
|
105
100
|
|
106
|
-
@model_associations = ModelAssociationElements.new
|
107
|
-
@diagram_associations = DiagramAssociationElements.new
|
101
|
+
@model_associations = ModelAssociationElements.new
|
102
|
+
@diagram_associations = DiagramAssociationElements.new
|
108
103
|
end
|
109
104
|
|
110
|
-
def draw
|
105
|
+
def draw # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
111
106
|
# First traversal we're just assigning ids to everything so that when
|
112
107
|
# we come to draw things we can do a lookup on the ids for any composition
|
113
108
|
# aggregation or subclass relationships.
|
@@ -117,10 +112,12 @@ module Xumlidot
|
|
117
112
|
|
118
113
|
klass.definition.inherited_modules.each do |m|
|
119
114
|
next if m.empty?
|
115
|
+
|
120
116
|
m.extend(::Xumlidot::Diagram::Xmi::Superklass)
|
121
|
-
end
|
117
|
+
end
|
122
118
|
|
123
119
|
next if @namespace_to_id.has?(klass.draw_identifier)
|
120
|
+
|
124
121
|
@namespace_to_id[klass.draw_identifier] = klass.id
|
125
122
|
end
|
126
123
|
|
@@ -136,22 +133,24 @@ module Xumlidot
|
|
136
133
|
# do the same with the inherited modules
|
137
134
|
klass.definition.inherited_modules.each do |m|
|
138
135
|
next if m.empty?
|
136
|
+
|
139
137
|
id = @namespace_to_id[m.draw_identifier]
|
140
138
|
m.force_id(id)
|
141
|
-
end
|
139
|
+
end
|
142
140
|
|
143
141
|
# if we have not added an id for this element it is likely a duplicate
|
144
142
|
# so do not draw it.
|
145
|
-
next unless @namespace_to_id.has_value?(klass.id)
|
143
|
+
next unless @namespace_to_id.has_value?(klass.id) # rubocop:disable Style/PreferredHashMethods
|
146
144
|
|
147
|
-
@model << klass.draw_klass
|
148
|
-
@diagram << klass.draw_diagram
|
145
|
+
@model << klass.draw_klass
|
146
|
+
@diagram << klass.draw_diagram
|
149
147
|
|
150
|
-
if
|
148
|
+
if ::Xumlidot::Options.composition
|
151
149
|
klass.constants.each do |k|
|
152
150
|
# Likewise to the above, unless we have an id for the class
|
153
151
|
# we don't want to draw the relationships
|
154
|
-
next unless @namespace_to_id.has_value?(k.id)
|
152
|
+
next unless @namespace_to_id.has_value?(k.id) # rubocop:disable Style/PreferredHashMethods
|
153
|
+
|
155
154
|
@model_associations << klass.draw_model_composition(k)
|
156
155
|
@diagram_associations << klass.draw_diagram_composition(k)
|
157
156
|
end
|
data/lib/xumlidot/diagram.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'diagram/dot'
|
2
4
|
require_relative 'diagram/xmi'
|
3
5
|
|
4
6
|
module Xumlidot
|
5
7
|
class Diagram
|
6
|
-
def initialize(stack,
|
7
|
-
@diagram = if
|
8
|
-
::Xumlidot::Diagram::Dot.new(stack
|
8
|
+
def initialize(stack, _options)
|
9
|
+
@diagram = if ::Xumlidot::Options.diagram_type == :dot
|
10
|
+
::Xumlidot::Diagram::Dot.new(stack)
|
9
11
|
else
|
10
|
-
::Xumlidot::Diagram::Xmi.new(stack
|
12
|
+
::Xumlidot::Diagram::Xmi.new(stack)
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'find'
|
2
4
|
|
3
5
|
module Xumlidot
|
@@ -9,7 +11,7 @@ module Xumlidot
|
|
9
11
|
@excluded = Regexp.new(@options.exclude)
|
10
12
|
end
|
11
13
|
|
12
|
-
def find_all_rb_files
|
14
|
+
def find_all_rb_files
|
13
15
|
@directories.each do |directory|
|
14
16
|
Find.find(directory) do |path|
|
15
17
|
next if path =~ @exluded
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Xumlidot
|
4
|
+
# This is code that was living in bin/xumlidot. We need to leverage
|
5
|
+
# it for running integration tests though
|
6
|
+
class Loader
|
7
|
+
def initialize(directories, options)
|
8
|
+
@directories = directories
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def load
|
13
|
+
dt = Xumlidot::DirectoryTree.new(directories, options)
|
14
|
+
|
15
|
+
# This is our tree of klasses/modules etc
|
16
|
+
# since we can't assume rails conventions for naming
|
17
|
+
# in a Ruby program.
|
18
|
+
constants = ::Xumlidot::Parsers::Stack::Constants.new
|
19
|
+
|
20
|
+
# TODO: move into directory tree
|
21
|
+
dt.find_all_rb_files do |path|
|
22
|
+
warn path if ::Xumlidot::Options.debug == true
|
23
|
+
file_contents = File.read(path)
|
24
|
+
|
25
|
+
@parser = Xumlidot::Parsers::File.new(file_contents, constants)
|
26
|
+
@parser.parse
|
27
|
+
end
|
28
|
+
|
29
|
+
# If a class is inherited from but does not exist in the constants
|
30
|
+
# we will create a dummy class.
|
31
|
+
#
|
32
|
+
# if a class is inherited from, we want to find it using the constant lookup
|
33
|
+
# rules defining in the resolver
|
34
|
+
#
|
35
|
+
# and what ... we want to add a reference too it?
|
36
|
+
#
|
37
|
+
# This REALLY should be done whenever we add a superklass
|
38
|
+
# i.e. yeah, its a hack
|
39
|
+
constants.resolve_inheritance
|
40
|
+
|
41
|
+
diagram = ::Xumlidot::Diagram.new(constants, options)
|
42
|
+
diagram.draw
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
attr_accessor :directories, :options
|
48
|
+
end
|
49
|
+
end
|